* device/lib/pic/libm: NEW, added math library functions
[fw/sdcc] / src / pic / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for pic
3   
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8     cont'd   -  Raphael Neider <rneider AT web.de> (2005)
9   
10   This program is free software; you can redistribute it and/or modify it
11   under the terms of the GNU General Public License as published by the
12   Free Software Foundation; either version 2, or (at your option) any
13   later version.
14   
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License for more details.
19   
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23   
24   In other words, you are welcome to use, share and improve this program.
25   You are forbidden to forbid anyone else to use, share and improve
26   what you give them.   Help stamp out software-hoarding!
27   
28   Notes:
29   000123 mlh  Moved aopLiteral to SDCCglue.c to help the split
30       Made everything static
31 -------------------------------------------------------------------------*/
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include "SDCCglobl.h"
38 #include "newalloc.h" 
39
40 #include "common.h"
41 #include "SDCCpeeph.h"
42 #include "ralloc.h"
43 #include "pcode.h"
44 #include "gen.h"
45 #include "glue.h"
46
47 /* When changing these, you must also update the assembler template
48  * in device/lib/libsdcc/macros.inc */
49 #define GPTRTAG_DATA    0x00
50 #define GPTRTAG_CODE    0x80
51
52 /* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
53 #define PIC_IS_DATA_PTR(x)      (IS_DATA_PTR(x) || IS_FARPTR(x))
54 #define PIC_IS_FARPTR(x)        (PIC_IS_DATA_PTR(x))
55
56 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
57 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
58 void genMult8X8_8 (operand *, operand *,operand *);
59 extern void printpBlock(FILE *of, pBlock *pb);
60
61 static int labelOffset=0;
62 extern int debug_verbose;
63 extern int pic14_hasInterrupt;
64 //static int optimized_for_speed = 0;
65
66 /* max_key keeps track of the largest label number used in 
67 a function. This is then used to adjust the label offset
68 for the next function.
69 */
70 static int max_key=0;
71 static int GpsuedoStkPtr=0;
72
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 const char *AopType(short type);
76
77 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
78
79 /* this is the down and dirty file with all kinds of 
80 kludgy & hacky stuff. This is what it is all about
81 CODE GENERATION for a specific MCU . some of the
82 routines may be reusable, will have to see */
83
84 static char *zero = "#0x00";
85 static char *one  = "#0x01";
86 static char *spname = "sp";
87
88 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
89 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
90 static char **fReturn = fReturnpic14;
91
92 //static char *accUse[] = {"a","b"};
93
94 //static short rbank = -1;
95
96 static struct {
97         short r0Pushed;
98         short r1Pushed;
99         short accInUse;
100         short inLine;
101         short debugLine;
102         short nRegsSaved;
103         set *sendSet;
104 } _G;
105
106 /* Resolved ifx structure. This structure stores information
107 about an iCode ifx that makes it easier to generate code.
108 */
109 typedef struct resolvedIfx {
110         symbol *lbl;     /* pointer to a label */
111         int condition;   /* true or false ifx */
112         int generated;   /* set true when the code associated with the ifx
113                           * is generated */
114 } resolvedIfx;
115
116 extern int pic14_ptrRegReq ;
117 extern int pic14_nRegs;
118 extern FILE *codeOutFile;
119 static void saverbank (int, iCode *,bool);
120
121 static lineNode *lineHead = NULL;
122 static lineNode *lineCurr = NULL;
123
124 #if 0
125 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
126 0xE0, 0xC0, 0x80, 0x00};
127 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
128 0x07, 0x03, 0x01, 0x00};
129 #endif
130
131 static  pBlock *pb;
132
133 /*-----------------------------------------------------------------*/
134 /*      my_powof2(n) - If `n' is an integaer power of 2, then the          */
135 /*                                 exponent of 2 is returned, otherwise -1 is      */
136 /*                                 returned.                                                                       */
137 /* note that this is similar to the function `powof2' in SDCCsymt  */
138 /* if(n == 2^y)                                                                                                    */
139 /*       return y;                                                                                                         */
140 /* return -1;                                                                                                      */
141 /*-----------------------------------------------------------------*/
142 static int my_powof2 (unsigned long num)
143 {
144         if(num) {
145                 if( (num & (num-1)) == 0) {
146                         int nshifts = -1;
147                         while(num) {
148                                 num>>=1;
149                                 nshifts++;
150                         }
151                         return nshifts;
152                 }
153         }
154         
155         return -1;
156 }
157
158 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
159 {
160         
161         DEBUGpic14_emitcode ("; ","line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
162                 line_no,
163                 ((result) ? AopType(AOP_TYPE(result)) : "-"),
164                 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
165                 ((result) ? AOP_SIZE(result) : 0),
166                 ((left)   ? AopType(AOP_TYPE(left)) : "-"),
167                 ((left)   ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
168                 ((left)   ? AOP_SIZE(left) : 0),
169                 ((right)  ? AopType(AOP_TYPE(right)) : "-"),
170                 ((right)  ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
171                 ((right)  ? AOP_SIZE(right) : 0));
172         
173 }
174
175 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
176 {
177         
178         DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
179                 line_no,
180                 ((result) ? AopType(AOP_TYPE(result)) : "-"),
181                 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
182                 ((left)   ? AopType(AOP_TYPE(left)) : "-"),
183                 ((left)   ? (SPEC_USIGN(operandType(left))       ? 'u' : 's') : '-'),
184                 ((right)  ? AopType(AOP_TYPE(right)) : "-"),
185                 ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
186         
187 }
188
189 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
190 {
191         va_list ap;
192         char lb[INITIAL_INLINEASM];  
193         unsigned char *lbp = (unsigned char *)lb;
194         
195         if(!debug_verbose && !options.debug)
196                 return;
197         
198         va_start(ap,fmt);   
199         
200         if (inst && *inst) {
201                 if (fmt && *fmt)
202                         sprintf(lb,"%s\t",inst);
203                 else
204                         sprintf(lb,"%s",inst);
205                 vsprintf(lb+(strlen(lb)),fmt,ap);
206         }  else
207                 vsprintf(lb,fmt,ap);
208         
209         while (isspace(*lbp)) lbp++;
210         
211         if (lbp && *lbp) 
212                 lineCurr = (lineCurr ?
213                 connectLine(lineCurr,newLineNode(lb)) :
214         (lineHead = newLineNode(lb)));
215         lineCurr->isInline = _G.inLine;
216         lineCurr->isDebug  = _G.debugLine;
217         
218         addpCode2pBlock(pb,newpCodeCharP(lb));
219         
220         va_end(ap);
221 }
222
223 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
224 {
225 #if defined (HAVE_VSNPRINTF)
226   vsnprintf (buf, size, fmt, ap);
227 #elif defined (HAVE_VSPRINTF)
228   vsprintf (buf, size, fmt, ap);
229   if (strlen (buf) >= size)
230   {
231     fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
232   }
233 #elif defined (HAVE_SNPRINTF)
234   snprintf (buf, size, "vs(n)printf required");
235 #elif defined (HAVE_SRINTF)
236   sprintf (buf, "vs(n)printf required");
237   if (strlen (buf) >= size)
238   {
239     fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
240   }
241 #else
242   assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
243 #endif
244 }
245
246 void emitpComment (const char *fmt, ...)
247 {
248   va_list va;
249   char buffer[4096];
250   
251   va_start (va, fmt);
252   if (pb) {
253     Safe_vsnprintf (buffer, 4096, fmt, va);
254     //fprintf (stderr, "%s\n" ,buffer);
255     addpCode2pBlock (pb, newpCodeCharP (buffer));
256 #if 0
257   } else {
258     Safe_vsnprintf (buffer, 4096, fmt, va);
259     fprintf (stderr, "No current pBlock -- discarding comment [%s]\n", buffer);
260 #endif
261   }
262   va_end (va);
263 }
264
265 void emitpLabel(int key)
266 {
267         addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
268 }
269
270 /* gen.h defines a macro emitpcode that should be used to call emitpcode
271  * as this allows for easy debugging (ever asked the question: where was
272  * this instruction geenrated? Here is the answer... */
273 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
274 {
275         if(pcop)
276                 addpCode2pBlock(pb,newpCode(poc,pcop));
277         else {
278                 static int has_warned = 0;
279                 
280                 DEBUGpic14_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
281                 if (!has_warned) {
282                         has_warned = 1;
283                         fprintf( stderr, "WARNING: encountered NULL pcop--this is probably a compiler bug...\n" );
284                 }
285         }
286 }
287
288 void emitpcodeNULLop(PIC_OPCODE poc)
289 {
290         
291         addpCode2pBlock(pb,newpCode(poc,NULL));
292         
293 }
294
295
296 /*-----------------------------------------------------------------*/
297 /* pic14_emitcode - writes the code into a file : for now it is simple    */
298 /*-----------------------------------------------------------------*/
299 void pic14_emitcode (char *inst,char *fmt, ...)
300 {
301         va_list ap;
302         char lb[INITIAL_INLINEASM];  
303         unsigned char *lbp = (unsigned char *)lb;
304         
305         va_start(ap,fmt);   
306         
307         if (inst && *inst) {
308                 if (fmt && *fmt)
309                         sprintf(lb,"%s\t",inst);
310                 else
311                         sprintf(lb,"%s",inst);
312                 vsprintf(lb+(strlen(lb)),fmt,ap);
313         }  else
314                 vsprintf(lb,fmt,ap);
315         
316         while (isspace(*lbp)) lbp++;
317         
318         if (lbp && *lbp) 
319                 lineCurr = (lineCurr ?
320                 connectLine(lineCurr,newLineNode(lb)) :
321         (lineHead = newLineNode(lb)));
322         lineCurr->isInline = _G.inLine;
323         lineCurr->isDebug  = _G.debugLine;
324         
325         if(debug_verbose)
326                 addpCode2pBlock(pb,newpCodeCharP(lb));
327         
328         va_end(ap);
329 }
330
331 /*-----------------------------------------------------------------*/
332 /* pic14_emitDebuggerSymbol - associate the current code location  */
333 /*       with a debugger symbol                                                                            */
334 /*-----------------------------------------------------------------*/
335 void
336 pic14_emitDebuggerSymbol (char * debugSym)
337 {
338         _G.debugLine = 1;
339         pic14_emitcode ("", ";%s ==.", debugSym);
340         _G.debugLine = 0;
341 }
342
343 #if 0
344 /*-----------------------------------------------------------------*/
345 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
346 /*-----------------------------------------------------------------*/
347 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
348 {
349         bool r0iu = FALSE , r1iu = FALSE;
350         bool r0ou = FALSE , r1ou = FALSE;
351         
352         /* the logic: if r0 & r1 used in the instruction
353         then we are in trouble otherwise */
354         
355         /* first check if r0 & r1 are used by this
356         instruction, in which case we are in trouble */
357         if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
358                 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
359         {
360                 goto endOfWorld;          
361         }
362         
363         r0ou = bitVectBitValue(ic->rMask,R0_IDX);
364         r1ou = bitVectBitValue(ic->rMask,R1_IDX);
365         
366         /* if no usage of r0 then return it */
367         if (!r0iu && !r0ou) {
368                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
369                 (*aopp)->type = AOP_R0;
370                 
371                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
372         }
373         
374         /* if no usage of r1 then return it */
375         if (!r1iu && !r1ou) {
376                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
377                 (*aopp)->type = AOP_R1;
378                 
379                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
380         }    
381         
382         /* now we know they both have usage */
383         /* if r0 not used in this instruction */
384         if (!r0iu) {
385                 /* push it if not already pushed */
386                 if (!_G.r0Pushed) {
387                         //pic14_emitcode ("push","%s",
388                         //                pic14_regWithIdx(R0_IDX)->dname);
389                         _G.r0Pushed++ ;
390                 }
391                 
392                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
393                 (*aopp)->type = AOP_R0;
394                 
395                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
396         }
397         
398         /* if r1 not used then */
399         
400         if (!r1iu) {
401                 /* push it if not already pushed */
402                 if (!_G.r1Pushed) {
403                         //pic14_emitcode ("push","%s",
404                         //                pic14_regWithIdx(R1_IDX)->dname);
405                         _G.r1Pushed++ ;
406                 }
407                 
408                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
409                 (*aopp)->type = AOP_R1;
410                 return pic14_regWithIdx(R1_IDX);
411         }
412         
413 endOfWorld :
414         /* I said end of world but not quite end of world yet */
415         /* if this is a result then we can push it on the stack*/
416         if (result) {
417                 (*aopp)->type = AOP_STK;        
418                 return NULL;
419         }
420         
421         /* other wise this is true end of the world */
422         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
423                 "getFreePtr should never reach here");
424         exit(0);
425 }
426 #endif
427
428 /*-----------------------------------------------------------------*/
429 /* newAsmop - creates a new asmOp                                                                  */
430 /*-----------------------------------------------------------------*/
431 asmop *newAsmop (short type)
432 {
433         asmop *aop;
434         
435         aop = Safe_calloc(1,sizeof(asmop));
436         aop->type = type;
437         return aop;
438 }
439
440 static void genSetDPTR(int n)
441 {
442         if (!n)
443         {
444                 pic14_emitcode(";", "Select standard DPTR");
445                 pic14_emitcode("mov", "dps, #0x00");
446         }
447         else
448         {
449                 pic14_emitcode(";", "Select alternate DPTR");
450                 pic14_emitcode("mov", "dps, #0x01");
451         }
452 }
453
454 /*-----------------------------------------------------------------*/
455 /* resolveIfx - converts an iCode ifx into a form more useful for  */
456 /*                              generating code                                                                    */
457 /*-----------------------------------------------------------------*/
458 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
459 {
460         if(!resIfx) 
461                 return;
462         
463         //  DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
464         
465         resIfx->condition = 1;  /* assume that the ifx is true */
466         resIfx->generated = 0;  /* indicate that the ifx has not been used */
467         
468         if(!ifx) {
469                 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL);      / * oops, there is no ifx. so create a label */
470                                                                                         /*
471                                                                                         DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
472                                                                                         __FUNCTION__,__LINE__,resIfx->lbl->key);
473                 */
474         } else {
475                 if(IC_TRUE(ifx)) {
476                         resIfx->lbl = IC_TRUE(ifx);
477                 } else {
478                         resIfx->lbl = IC_FALSE(ifx);
479                         resIfx->condition = 0;
480                 }
481                 /*
482                 if(IC_TRUE(ifx)) 
483                 DEBUGpic14_emitcode("; ***","ifx true is non-null");
484                 if(IC_FALSE(ifx)) 
485                 DEBUGpic14_emitcode("; ***","ifx false is non-null");
486                 */
487         }
488         
489         //  DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
490         
491 }
492 /*-----------------------------------------------------------------*/
493 /* pointerCode - returns the code for a pointer type                       */
494 /*-----------------------------------------------------------------*/
495 #if 0
496 static int pointerCode (sym_link *etype)
497 {
498         
499         return PTR_TYPE(SPEC_OCLS(etype));
500         
501 }
502 #endif
503
504 /*-----------------------------------------------------------------*/
505 /* aopForSym - for a true symbol                                                                   */
506 /*-----------------------------------------------------------------*/
507 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
508 {
509         asmop *aop;
510         memmap *space= SPEC_OCLS(sym->etype);
511         
512         DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
513         /* if already has one */
514         if (sym->aop)
515                 return sym->aop;
516         
517 #if 0
518         /* assign depending on the storage class */
519         /* if it is on the stack or indirectly addressable */
520         /* space we need to assign either r0 or r1 to it         */    
521         if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
522                 sym->aop = aop = newAsmop(0);
523                 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
524                 aop->size = getSize(sym->type);
525                 
526                 /* now assign the address of the variable to 
527                 the pointer register */
528                 if (aop->type != AOP_STK) {
529                         
530                         if (sym->onStack) {
531                                 if ( _G.accInUse )
532                                         pic14_emitcode("push","acc");
533                                 
534                                 pic14_emitcode("mov","a,_bp");
535                                 pic14_emitcode("add","a,#0x%02x",
536                                         ((sym->stack < 0) ?
537                                         ((char)(sym->stack - _G.nRegsSaved )) :
538                                 ((char)sym->stack)) & 0xff);
539                                 pic14_emitcode("mov","%s,a",
540                                         aop->aopu.aop_ptr->name);
541                                 
542                                 if ( _G.accInUse )
543                                         pic14_emitcode("pop","acc");
544                         } else
545                                 pic14_emitcode("mov","%s,#%s",
546                                 aop->aopu.aop_ptr->name,
547                                 sym->rname);
548                         aop->paged = space->paged;
549                 } else
550                         aop->aopu.aop_stk = sym->stack;
551                 return aop;
552         }
553         
554         if (sym->onStack && options.stack10bit)
555         {
556                 /* It's on the 10 bit stack, which is located in
557                 * far data space.
558                 */
559                 
560                 //DEBUGpic14_emitcode(";","%d",__LINE__);
561                 
562                 if ( _G.accInUse )
563                         pic14_emitcode("push","acc");
564                 
565                 pic14_emitcode("mov","a,_bp");
566                 pic14_emitcode("add","a,#0x%02x",
567                         ((sym->stack < 0) ?
568                         ((char)(sym->stack - _G.nRegsSaved )) :
569                 ((char)sym->stack)) & 0xff);
570                 
571                 genSetDPTR(1);
572                 pic14_emitcode ("mov","dpx1,#0x40");
573                 pic14_emitcode ("mov","dph1,#0x00");
574                 pic14_emitcode ("mov","dpl1, a");
575                 genSetDPTR(0);
576                 
577                 if ( _G.accInUse )
578                         pic14_emitcode("pop","acc");
579                 
580                 sym->aop = aop = newAsmop(AOP_DPTR2);
581                 aop->size = getSize(sym->type); 
582                 return aop;
583         }
584 #endif
585
586         //DEBUGpic14_emitcode(";","%d",__LINE__);
587         /* if in bit space */
588         if (IN_BITSPACE(space)) {
589                 sym->aop = aop = newAsmop (AOP_CRY);
590                 aop->aopu.aop_dir = sym->rname ;
591                 aop->size = getSize(sym->type);
592                 //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
593                 return aop;
594         }
595         /* if it is in direct space */
596         if (IN_DIRSPACE(space)) {
597                 sym->aop = aop = newAsmop (AOP_DIR);
598                 aop->aopu.aop_dir = sym->rname ;
599                 aop->size = getSize(sym->type);
600                 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
601                 return aop;
602         }
603         
604         /* special case for a function */
605         if (IS_FUNC(sym->type)) {   
606                 
607                 sym->aop = aop = newAsmop(AOP_PCODE);
608                 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
609                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
610                 PCOI(aop->aopu.pcop)->_function = 1;
611                 PCOI(aop->aopu.pcop)->index = 0;
612                 aop->size = FPTRSIZE; 
613                 /*
614                 sym->aop = aop = newAsmop(AOP_IMMD);    
615                 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
616                 strcpy(aop->aopu.aop_immd,sym->rname);
617                 aop->size = FPTRSIZE; 
618                 */
619                 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
620                 return aop;
621         }
622         
623         if (IS_ARRAY(sym->type)) {
624                 sym->aop = aop = newAsmop(AOP_PCODE);
625                 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
626                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
627                 PCOI(aop->aopu.pcop)->_function = 0;
628                 PCOI(aop->aopu.pcop)->index = 0;
629                 aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
630                 
631                 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
632                 return aop;
633         }
634         
635         /* only remaining is far space */
636         /* in which case DPTR gets the address */
637         sym->aop = aop = newAsmop(AOP_PCODE);
638         
639         aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
640         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
641         PCOI(aop->aopu.pcop)->index = 0;
642         
643         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
644                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
645         
646         allocDirReg (IC_LEFT(ic));
647         
648         aop->size = FPTRSIZE;
649         /*
650         DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
651         sym->aop = aop = newAsmop(AOP_DPTR);
652         pic14_emitcode ("mov","dptr,#%s", sym->rname);
653         aop->size = getSize(sym->type);
654         
655           DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
656         */
657         
658         /* if it is in code space */
659         if (IN_CODESPACE(space))
660                 aop->code = 1;
661         
662         return aop;       
663 }
664
665 /*-----------------------------------------------------------------*/
666 /* aopForRemat - rematerialzes an object                                                   */
667 /*-----------------------------------------------------------------*/
668 static asmop *aopForRemat (operand *op) // x symbol *sym)
669 {
670         symbol *sym = OP_SYMBOL(op);
671         iCode *ic = NULL;
672         asmop *aop = newAsmop(AOP_PCODE);
673         int val = 0;
674         int offset = 0;
675         
676         ic = sym->rematiCode;
677
678         DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
679         if(IS_OP_POINTER(op)) {
680                 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
681         }
682         for (;;) {
683                 if (ic->op == '+') {
684                         val += (int) operandLitValue(IC_RIGHT(ic));
685                 } else if (ic->op == '-') {
686                         val -= (int) operandLitValue(IC_RIGHT(ic));
687                 } else
688                         break;
689                 
690                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
691         }
692         
693         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
694         aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
695         PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
696         PCOI(aop->aopu.pcop)->index = val;
697         
698         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
699                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
700                 val, IS_PTR_CONST(operandType(op)));
701         
702         //      DEBUGpic14_emitcode(";","aop type  %s",AopType(AOP_TYPE(IC_LEFT(ic))));
703         
704         allocDirReg (IC_LEFT(ic));
705         
706         return aop;              
707 }
708
709 int aopIdx (asmop *aop, int offset)
710 {
711         if(!aop)
712                 return -1;
713         
714         if(aop->type !=  AOP_REG)
715                 return -2;
716         
717         return aop->aopu.aop_reg[offset]->rIdx;
718         
719 }
720 /*-----------------------------------------------------------------*/
721 /* regsInCommon - two operands have some registers in common       */
722 /*-----------------------------------------------------------------*/
723 static bool regsInCommon (operand *op1, operand *op2)
724 {
725         symbol *sym1, *sym2;
726         int i;
727         
728         /* if they have registers in common */
729         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
730                 return FALSE ;
731         
732         sym1 = OP_SYMBOL(op1);
733         sym2 = OP_SYMBOL(op2);
734         
735         if (sym1->nRegs == 0 || sym2->nRegs == 0)
736                 return FALSE ;
737         
738         for (i = 0 ; i < sym1->nRegs ; i++) {
739                 int j;
740                 if (!sym1->regs[i])
741                         continue ;
742                 
743                 for (j = 0 ; j < sym2->nRegs ;j++ ) {
744                         if (!sym2->regs[j])
745                                 continue ;
746                         
747                         if (sym2->regs[j] == sym1->regs[i])
748                                 return TRUE ;
749                 }
750         }
751         
752         return FALSE ;
753 }
754
755 /*-----------------------------------------------------------------*/
756 /* operandsEqu - equivalent                                                                        */
757 /*-----------------------------------------------------------------*/
758 static bool operandsEqu ( operand *op1, operand *op2)
759 {
760         symbol *sym1, *sym2;
761         
762         /* if they not symbols */
763         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
764                 return FALSE;
765         
766         sym1 = OP_SYMBOL(op1);
767         sym2 = OP_SYMBOL(op2);
768         
769         /* if both are itemps & one is spilt
770         and the other is not then false */
771         if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
772                 sym1->isspilt != sym2->isspilt )
773                 return FALSE ;
774         
775         /* if they are the same */
776         if (sym1 == sym2)
777                 return TRUE ;
778         
779         if (sym1->rname[0] && sym2->rname[0]
780                 && strcmp (sym1->rname, sym2->rname) == 0)
781                 return TRUE;
782         
783         
784         /* if left is a tmp & right is not */
785         if (IS_ITEMP(op1)  && 
786                 !IS_ITEMP(op2) &&
787                 sym1->isspilt  &&
788                 (sym1->usl.spillLoc == sym2))
789                 return TRUE;
790         
791         if (IS_ITEMP(op2)  && 
792                 !IS_ITEMP(op1) &&
793                 sym2->isspilt  &&
794                 sym1->level > 0 &&
795                 (sym2->usl.spillLoc == sym1))
796                 return TRUE ;
797         
798         return FALSE ;
799 }
800
801 /*-----------------------------------------------------------------*/
802 /* pic14_sameRegs - two asmops have the same registers             */
803 /*-----------------------------------------------------------------*/
804 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
805 {
806         int i;
807         
808         if (aop1 == aop2)
809                 return TRUE ;
810         
811         if (aop1->type != AOP_REG ||
812                 aop2->type != AOP_REG )
813                 return FALSE ;
814         
815         if (aop1->size != aop2->size )
816                 return FALSE ;
817         
818         for (i = 0 ; i < aop1->size ; i++ )
819                 if (aop1->aopu.aop_reg[i] !=
820                         aop2->aopu.aop_reg[i] )
821                         return FALSE ;
822                 
823                 return TRUE ;
824 }
825
826 /*-----------------------------------------------------------------*/
827 /* aopOp - allocates an asmop for an operand  :                    */
828 /*-----------------------------------------------------------------*/
829 void aopOp (operand *op, iCode *ic, bool result)
830 {
831         asmop *aop;
832         symbol *sym;
833         int i;
834         
835         if (!op)
836                 return ;
837         
838         /* if this a literal */
839         if (IS_OP_LITERAL(op)) {
840                 op->aop = aop = newAsmop(AOP_LIT);
841                 aop->aopu.aop_lit = op->operand.valOperand;
842                 aop->size = getSize(operandType(op));
843                 return;
844         }
845         
846         {
847                 sym_link *type = operandType(op);
848                 if(IS_PTR_CONST(type))
849                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
850         }
851         
852         /* if already has a asmop then continue */
853         if (op->aop)
854                 return ;
855         
856         /* if the underlying symbol has a aop */
857         if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
858                 DEBUGpic14_emitcode(";","%d",__LINE__);
859                 op->aop = OP_SYMBOL(op)->aop;
860                 return;
861         }
862         
863         /* if this is a true symbol */
864         if (IS_TRUE_SYMOP(op)) {          
865                 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
866                 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
867                 return ;
868         }
869         
870         /* this is a temporary : this has
871         only four choices :
872         a) register
873         b) spillocation
874         c) rematerialize 
875         d) conditional   
876         e) can be a return use only */
877         
878         sym = OP_SYMBOL(op);
879         
880         
881         /* if the type is a conditional */
882         if (sym->regType == REG_CND) {
883                 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
884                 aop->size = 0;
885                 return;
886         }
887         
888         /* if it is spilt then two situations
889         a) is rematerialize 
890         b) has a spill location */
891         if (sym->isspilt || sym->nRegs == 0) {
892                 
893                 DEBUGpic14_emitcode(";","%d",__LINE__);
894                 /* rematerialize it NOW */
895                 if (sym->remat) {
896                         
897                         sym->aop = op->aop = aop = aopForRemat (op);
898                         aop->size = getSize(sym->type);
899                         //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
900                         return;
901                 }
902                 
903 #if 0
904                 /* WREG is not usable as an ordinary operand with PIC architecture,
905                  * one might introduce a scratch register that can be used to make
906                  * WREG accesible as an operand... disable WREG for now */
907                 if (sym->accuse) {
908                         int i;
909                         aop = op->aop = sym->aop = newAsmop(AOP_ACC);
910                         aop->size = getSize(sym->type);
911                         for ( i = 0 ; i < 2 ; i++ )
912                                 aop->aopu.aop_str[i] = accUse[i];
913                         DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
914                         return;  
915                 }
916 #endif
917                 
918                 if (sym->ruonly ) {
919                         if(sym->isptr) {        // && sym->uptr 
920                                 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
921                                 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
922                                 
923                                 //PCOI(aop->aopu.pcop)->_const = 0;
924                                 //PCOI(aop->aopu.pcop)->index = 0;
925                                 /*
926                                 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
927                                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
928                                 */
929                                 //allocDirReg (IC_LEFT(ic));
930                                 
931                                 aop->size = getSize(sym->type);
932                                 DEBUGpic14_emitcode(";","%d",__LINE__);
933                                 return;
934                                 
935                         } else {
936                                 
937                                 unsigned i;
938                                 
939                                 aop = op->aop = sym->aop = newAsmop(AOP_STR);
940                                 aop->size = getSize(sym->type);
941                                 for ( i = 0 ; i < fReturnSizePic ; i++ )
942                                         aop->aopu.aop_str[i] = fReturn[i];
943                                 
944                                 DEBUGpic14_emitcode(";","%d",__LINE__);
945                                 return;
946                         }
947                 }
948                 
949                 /* else spill location  */
950                 if (sym->usl.spillLoc)
951                 {
952                         asmop *oldAsmOp = NULL;
953
954                         if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
955                         {
956                                 /* force a new aop if sizes differ */
957                                 oldAsmOp = sym->usl.spillLoc->aop;
958                                 sym->usl.spillLoc->aop = NULL;
959                         }
960                         DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
961                                 __FUNCTION__,__LINE__,
962                                 sym->usl.spillLoc->rname,
963                                 sym->rname, sym->usl.spillLoc->offset);
964                 
965                         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
966                         if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
967                         {
968                                 /* Don't reuse the new aop, go with the last one */
969                                 sym->usl.spillLoc->aop = oldAsmOp;
970                         }
971                         //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
972                         aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
973                                 getSize(sym->type), 
974                                 sym->usl.spillLoc->offset);
975                         aop->size = getSize(sym->type);
976                 
977                         return;
978                 }
979         }
980         
981         {
982                 sym_link *type = operandType(op);
983                 if(IS_PTR_CONST(type)) 
984                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
985         }
986         
987         /* must be in a register */
988         DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
989         sym->aop = op->aop = aop = newAsmop(AOP_REG);
990         aop->size = sym->nRegs;
991         for ( i = 0 ; i < sym->nRegs ;i++)
992                 aop->aopu.aop_reg[i] = sym->regs[i];
993 }
994
995 /*-----------------------------------------------------------------*/
996 /* freeAsmop - free up the asmop given to an operand                       */
997 /*----------------------------------------------------------------*/
998 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
999 {       
1000         asmop *aop ;
1001         
1002         if (!op)
1003                 aop = aaop;
1004         else 
1005                 aop = op->aop;
1006         
1007         if (!aop)
1008                 return ;
1009         
1010         if (aop->freed)
1011                 goto dealloc; 
1012         
1013         aop->freed = 1;
1014         
1015         /* depending on the asmop type only three cases need work AOP_RO
1016         , AOP_R1 && AOP_STK */
1017 #if 0
1018         switch (aop->type) {
1019         case AOP_R0 :
1020                 if (_G.r0Pushed ) {
1021                         if (pop) {
1022                                 pic14_emitcode ("pop","ar0");     
1023                                 _G.r0Pushed--;
1024                         }
1025                 }
1026                 bitVectUnSetBit(ic->rUsed,R0_IDX);
1027                 break;
1028                 
1029         case AOP_R1 :
1030                 if (_G.r1Pushed ) {
1031                         if (pop) {
1032                                 pic14_emitcode ("pop","ar1");
1033                                 _G.r1Pushed--;
1034                         }
1035                 }
1036                 bitVectUnSetBit(ic->rUsed,R1_IDX);                      
1037                 break;
1038                 
1039         case AOP_STK :
1040                 {
1041                         int sz = aop->size;      
1042                         int stk = aop->aopu.aop_stk + aop->size;
1043                         bitVectUnSetBit(ic->rUsed,R0_IDX);
1044                         bitVectUnSetBit(ic->rUsed,R1_IDX);                
1045                         
1046                         getFreePtr(ic,&aop,FALSE);
1047                         
1048                         if (options.stack10bit)
1049                         {
1050                                 /* I'm not sure what to do here yet... */
1051                                 /* #STUB */
1052                                 fprintf(stderr, 
1053                                         "*** Warning: probably generating bad code for "
1054                                         "10 bit stack mode.\n");
1055                         }
1056                         
1057                         if (stk) {
1058                                 pic14_emitcode ("mov","a,_bp");
1059                                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1060                                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1061                         } else {
1062                                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1063                         }
1064                         
1065                         while (sz--) {
1066                                 pic14_emitcode("pop","acc");
1067                                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1068                                 if (!sz) break;
1069                                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1070                         }
1071                         op->aop = aop;
1072                         freeAsmop(op,NULL,ic,TRUE);
1073                         if (_G.r0Pushed) {
1074                                 pic14_emitcode("pop","ar0");
1075                                 _G.r0Pushed--;
1076                         }
1077                         
1078                         if (_G.r1Pushed) {
1079                                 pic14_emitcode("pop","ar1");
1080                                 _G.r1Pushed--;
1081                         }         
1082                 }
1083         }
1084 #endif
1085         
1086 dealloc:
1087         /* all other cases just dealloc */
1088         if (op ) {
1089                 op->aop = NULL;
1090                 if (IS_SYMOP(op)) {
1091                         OP_SYMBOL(op)->aop = NULL;      
1092                         /* if the symbol has a spill */
1093                         if (SPIL_LOC(op))
1094                                 SPIL_LOC(op)->aop = NULL;
1095                 }
1096         }
1097 }
1098
1099 /*-----------------------------------------------------------------*/
1100 /* aopGet - for fetching value of the aop                                                  */
1101 /*-----------------------------------------------------------------*/
1102 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1103 {
1104         char *s = buffer ;
1105         char *rs;
1106         
1107         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1108         /* offset is greater than
1109         size then zero */
1110         if (offset > (aop->size - 1) &&
1111                 aop->type != AOP_LIT)
1112                 return zero;
1113         
1114         /* depending on type */
1115         switch (aop->type) {
1116                 
1117         case AOP_R0:
1118         case AOP_R1:
1119                 DEBUGpic14_emitcode(";","%d",__LINE__);
1120                 /* if we need to increment it */           
1121                 while (offset > aop->coff) {            
1122                         pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);    
1123                         aop->coff++;
1124                 }
1125                 
1126                 while (offset < aop->coff) {
1127                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1128                         aop->coff--;
1129                 }
1130                 
1131                 aop->coff = offset ;
1132                 if (aop->paged) {
1133                         pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1134                         return (dname ? "acc" : "a");
1135                 }               
1136                 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1137                 rs = Safe_calloc(1,strlen(s)+1);
1138                 strcpy(rs,s);   
1139                 return rs;
1140                 
1141         case AOP_DPTR:
1142         case AOP_DPTR2:
1143                 DEBUGpic14_emitcode(";","%d",__LINE__);
1144                 if (aop->type == AOP_DPTR2)
1145                 {
1146                         genSetDPTR(1);
1147                 }
1148                 
1149                 while (offset > aop->coff) {
1150                         pic14_emitcode ("inc","dptr");
1151                         aop->coff++;
1152                 }
1153                 
1154                 while (offset < aop->coff) {            
1155                         pic14_emitcode("lcall","__decdptr");
1156                         aop->coff--;
1157                 }
1158                 
1159                 aop->coff = offset;
1160                 if (aop->code) {
1161                         pic14_emitcode("clr","a");
1162                         pic14_emitcode("movc","a,@a+dptr");
1163                 }
1164                 else {
1165                         pic14_emitcode("movx","a,@dptr");
1166                 }
1167                 
1168                 if (aop->type == AOP_DPTR2)
1169                 {
1170                         genSetDPTR(0);
1171                 }
1172                 
1173                 return (dname ? "acc" : "a");
1174                 
1175                 
1176         case AOP_IMMD:
1177                 if (bit16) 
1178                         sprintf (s,"%s",aop->aopu.aop_immd);
1179                 else
1180                         if (offset) 
1181                                 sprintf(s,"(%s >> %d)",
1182                                 aop->aopu.aop_immd,
1183                                 offset*8);
1184                         else
1185                                 sprintf(s,"%s",
1186                                 aop->aopu.aop_immd);
1187                         DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1188                         rs = Safe_calloc(1,strlen(s)+1);
1189                         strcpy(rs,s);   
1190                         return rs;
1191                         
1192         case AOP_DIR:
1193                 if (offset) {
1194                         sprintf(s,"(%s + %d)",
1195                                 aop->aopu.aop_dir,
1196                                 offset);
1197                         DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1198                 } else
1199                         sprintf(s,"%s",aop->aopu.aop_dir);
1200                 rs = Safe_calloc(1,strlen(s)+1);
1201                 strcpy(rs,s);   
1202                 return rs;
1203                 
1204         case AOP_REG:
1205                 //if (dname) 
1206                 //        return aop->aopu.aop_reg[offset]->dname;
1207                 //else
1208                 return aop->aopu.aop_reg[offset]->name;
1209                 
1210         case AOP_CRY:
1211                 //pic14_emitcode(";","%d",__LINE__);
1212                 return aop->aopu.aop_dir;
1213                 
1214         case AOP_ACC:
1215                 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1216                 return "AOP_accumulator_bug";
1217                 
1218         case AOP_LIT:
1219                 sprintf(s, "0x%02x", pic14aopLiteral (aop->aopu.aop_lit, offset));
1220                 rs = Safe_strdup(s);
1221                 return rs;
1222                 
1223         case AOP_STR:
1224                 aop->coff = offset ;
1225                 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1226                         dname)
1227                         return "acc";
1228                 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1229                 
1230                 return aop->aopu.aop_str[offset];
1231                 
1232         case AOP_PCODE:
1233                 {
1234                         pCodeOp *pcop = aop->aopu.pcop;
1235                         DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1236                         if(pcop->name) {
1237                                 if (offset) {
1238                                         DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1239                                         sprintf(s,"(%s+%d)", pcop->name,offset);
1240                                 } else {
1241                                         DEBUGpic14_emitcode(";","%s",pcop->name);
1242                                         sprintf(s,"%s", pcop->name);
1243                                 }
1244                         } else
1245                                 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1246                         
1247                 }
1248                 rs = Safe_calloc(1,strlen(s)+1);
1249                 strcpy(rs,s);   
1250                 return rs;
1251                 
1252   }
1253   
1254   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1255           "aopget got unsupported aop->type");
1256   exit(0);
1257 }
1258
1259
1260 /*-----------------------------------------------------------------*/
1261 /* popGetTempReg - create a new temporary pCodeOp                                  */
1262 /*-----------------------------------------------------------------*/
1263 pCodeOp *popGetTempReg(void)
1264 {
1265         
1266         pCodeOp *pcop;
1267         
1268         pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1269         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1270                 PCOR(pcop)->r->wasUsed=1;
1271                 PCOR(pcop)->r->isFree=0;
1272         }
1273         
1274         return pcop;
1275 }
1276
1277 /*-----------------------------------------------------------------*/
1278 /* popReleaseTempReg - create a new temporary pCodeOp                              */
1279 /*-----------------------------------------------------------------*/
1280 void popReleaseTempReg(pCodeOp *pcop)
1281 {
1282         
1283         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1284                 PCOR(pcop)->r->isFree = 1;
1285         
1286 }
1287 /*-----------------------------------------------------------------*/
1288 /* popGetLabel - create a new pCodeOp of type PO_LABEL                     */
1289 /*-----------------------------------------------------------------*/
1290 pCodeOp *popGetLabel(unsigned int key)
1291 {
1292         
1293         DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1294         
1295         if(key>(unsigned int)max_key)
1296                 max_key = key;
1297         
1298         return newpCodeOpLabel(NULL,key+100+labelOffset);
1299 }
1300
1301 /*-------------------------------------------------------------------*/
1302 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1303 /*-------------------------------------------------------------------*/
1304 pCodeOp *popGetHighLabel(unsigned int key)
1305 {
1306         pCodeOp *pcop;
1307         pcop = popGetLabel(key);
1308         PCOLAB(pcop)->offset = 1;
1309         return pcop;
1310 }
1311
1312 /*-----------------------------------------------------------------*/
1313 /* popGetLit - asm operator to pcode operator conversion                           */
1314 /*-----------------------------------------------------------------*/
1315 pCodeOp *popGetLit(unsigned int lit)
1316 {
1317         
1318         return newpCodeOpLit((unsigned char)lit);
1319 }
1320
1321 /*-----------------------------------------------------------------*/
1322 /* popGetImmd - asm operator to pcode immediate conversion                 */
1323 /*-----------------------------------------------------------------*/
1324 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1325 {
1326         
1327         return newpCodeOpImmd(name, offset,index, 0, is_func);
1328 }
1329
1330 extern set *externs;
1331
1332 /*-----------------------------------------------------------------*/
1333 /* popGetWithString - asm operator to pcode operator conversion                    */
1334 /*-----------------------------------------------------------------*/
1335 pCodeOp *popGetWithString(char *str, int isExtern)
1336 {
1337         pCodeOp *pcop;
1338         
1339         
1340         if(!str) {
1341                 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1342                 exit (1);
1343         }
1344         
1345         pcop = newpCodeOp(str,PO_STR);
1346         PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1347
1348         return pcop;
1349 }
1350
1351 pCodeOp *popGetExternal (char *str)
1352 {
1353         pCodeOp *pcop = popGetWithString (str, 1);
1354         
1355         if (str) {
1356           symbol *sym;
1357           bool found = 0;
1358
1359           for (sym = setFirstItem (externs); !found && sym; sym = setNextItem (externs))
1360           {
1361             if (!strcmp (str, sym->rname))
1362               found = 1;
1363           }
1364           
1365           if (!found)
1366           {
1367             sym = newSymbol(str, 0);
1368             strncpy(sym->rname, str, SDCC_NAME_MAX);
1369             addSet (&externs, sym);
1370           } // if
1371         }
1372         return pcop;
1373 }
1374
1375 /*-----------------------------------------------------------------*/
1376 /* popRegFromString -                                                                                      */
1377 /*-----------------------------------------------------------------*/
1378 pCodeOp *popRegFromString(char *str, int size, int offset)
1379 {
1380         
1381         pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1382         pcop->type = PO_DIR;
1383         
1384         DEBUGpic14_emitcode(";","%d",__LINE__);
1385         
1386         if(!str)
1387                 str = "BAD_STRING";
1388         
1389         pcop->name = Safe_calloc(1,strlen(str)+1);
1390         strcpy(pcop->name,str);
1391         
1392         //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1393         
1394         PCOR(pcop)->r = dirregWithName(pcop->name);
1395         if(PCOR(pcop)->r == NULL) {
1396                 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1397                 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1398                 DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1399         } else {
1400                 DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1401         }
1402         PCOR(pcop)->instance = offset;
1403         
1404         return pcop;
1405 }
1406
1407 /*-----------------------------------------------------------------*/
1408 /*-----------------------------------------------------------------*/
1409 pCodeOp *popRegFromIdx(int rIdx)
1410 {
1411         pCodeOp *pcop;
1412         
1413         DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1414                 __FUNCTION__,__LINE__,rIdx);
1415         
1416         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1417         
1418         PCOR(pcop)->rIdx = rIdx;
1419         PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1420         PCOR(pcop)->r->isFree = 0;
1421         PCOR(pcop)->r->wasUsed = 1;
1422         
1423         pcop->type = PCOR(pcop)->r->pc_type;
1424         
1425         
1426         return pcop;
1427 }
1428
1429 /*-----------------------------------------------------------------*/
1430 /* popGet - asm operator to pcode operator conversion                      */
1431 /*-----------------------------------------------------------------*/
1432 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1433 {
1434         //char *s = buffer ;
1435         //char *rs;
1436         
1437         pCodeOp *pcop;
1438         
1439         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1440         /* offset is greater than
1441         size then zero */
1442
1443         assert (aop);
1444
1445
1446         /* XXX: still needed for BIT operands (AOP_CRY) */
1447         if (offset > (aop->size - 1) &&
1448                 aop->type != AOP_LIT &&
1449                 aop->type != AOP_PCODE)
1450         {
1451                 printf( "%s: (offset[%d] > AOP_SIZE(op)[%d]-1) && AOP_TYPE(op) != AOP_LIT)\n", __FUNCTION__, offset, aop->size);
1452                 return NULL;  //zero;
1453         }
1454         
1455         /* depending on type */
1456         switch (aop->type) {
1457                 
1458         case AOP_R0:
1459         case AOP_R1:
1460         case AOP_DPTR:
1461         case AOP_DPTR2:
1462         case AOP_ACC:
1463                 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1464                 return NULL;
1465                 
1466         case AOP_IMMD:
1467                 DEBUGpic14_emitcode(";","%d",__LINE__);
1468                 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1469                 
1470         case AOP_DIR:
1471                 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1472 #if 0
1473                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1474                 pcop->type = PO_DIR;
1475                 
1476                 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1477                 strcpy(pcop->name,aop->aopu.aop_dir);   
1478                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1479                 if(PCOR(pcop)->r == NULL) {
1480                         //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1481                         PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1482                         DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1483                 } else {
1484                         DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1485                 }
1486                 PCOR(pcop)->instance = offset;
1487                 
1488                 return pcop;
1489 #endif
1490                 
1491         case AOP_REG:
1492                 {
1493                         int rIdx;
1494                         assert (offset < aop->size);
1495                         rIdx = aop->aopu.aop_reg[offset]->rIdx;
1496                         
1497                         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1498                         PCOR(pcop)->rIdx = rIdx;
1499                         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1500                         PCOR(pcop)->r->wasUsed=1;
1501                         PCOR(pcop)->r->isFree=0;
1502                         
1503                         PCOR(pcop)->instance = offset;
1504                         pcop->type = PCOR(pcop)->r->pc_type;
1505                         //rs = aop->aopu.aop_reg[offset]->name;
1506                         DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1507                         return pcop;
1508                 }
1509                 
1510         case AOP_CRY:
1511                 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1512                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1513                 //if(PCOR(pcop)->r == NULL)
1514                 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1515                 return pcop;
1516                 
1517         case AOP_LIT:
1518                 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1519                 
1520         case AOP_STR:
1521                 DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1522                 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1523                 /*
1524                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1525                 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1526                 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1527                 pcop->type = PCOR(pcop)->r->pc_type;
1528                 pcop->name = PCOR(pcop)->r->name;
1529                 
1530                   return pcop;
1531                 */
1532                 
1533         case AOP_PCODE:
1534                 pcop = NULL;
1535                 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1536                         __LINE__, 
1537                         ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1538                 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1539                 switch (aop->aopu.pcop->type)
1540                 {
1541                 case PO_IMMEDIATE:
1542                   pcop = pCodeOpCopy (aop->aopu.pcop);
1543                   /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1544                    * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1545                   PCOI(pcop)->index += offset;
1546                   //PCOI(pcop)->offset = 0;
1547                   break;
1548                 case PO_DIR:
1549                   pcop = pCodeOpCopy (aop->aopu.pcop);
1550                   PCOR(pcop)->instance = offset;
1551                   break;
1552                 default:
1553                   assert ( !"unhandled pCode type" );
1554                   break;
1555                 } // switch
1556                 return pcop;
1557         }
1558         
1559         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1560                 "popGet got unsupported aop->type");
1561         exit(0);
1562 }
1563
1564 /*-----------------------------------------------------------------*/
1565 /* popGetAddr - access the low/high word of a symbol (immediate)   */
1566 /*              (for non-PO_IMMEDIATEs this is the same as popGet) */
1567 /*-----------------------------------------------------------------*/
1568 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1569 {
1570   if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1571   {
1572     pCodeOp *pcop = aop->aopu.pcop;
1573     assert (offset <= GPTRSIZE);
1574
1575     /* special case: index >= 2 should return GPOINTER-style values */
1576     if (offset == 2)
1577     {
1578       pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1579       return pcop;
1580     }
1581     
1582     pcop = pCodeOpCopy (pcop);
1583     /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1584      * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1585     PCOI(pcop)->offset += offset;
1586     PCOI(pcop)->index += index;
1587     //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);
1588     return pcop;
1589   } else {
1590     return popGet (aop, offset + index);
1591   }
1592 }
1593
1594 /*-----------------------------------------------------------------*/
1595 /* aopPut - puts a string for a aop                                                        */
1596 /*-----------------------------------------------------------------*/
1597 void aopPut (asmop *aop, char *s, int offset)
1598 {
1599         char *d = buffer ;
1600         symbol *lbl ;
1601         
1602         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1603         
1604         if (aop->size && offset > ( aop->size - 1)) {
1605                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1606                         "aopPut got offset > aop->size");
1607                 exit(0);
1608         }
1609         
1610         /* will assign value to value */
1611         /* depending on where it is ofcourse */
1612         switch (aop->type) {
1613         case AOP_DIR:
1614                 if (offset) {
1615                         sprintf(d,"(%s + %d)",
1616                                 aop->aopu.aop_dir,offset);
1617                         fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1618                         
1619                 } else
1620                         sprintf(d,"%s",aop->aopu.aop_dir);
1621                 
1622                 if (strcmp(d,s)) {
1623                         DEBUGpic14_emitcode(";","%d",__LINE__);
1624                         if(strcmp(s,"W"))
1625                                 pic14_emitcode("movf","%s,w",s);
1626                         pic14_emitcode("movwf","%s",d);
1627                         
1628                         if(strcmp(s,"W")) {
1629                                 pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1630                                 if(offset >= aop->size) {
1631                                         emitpcode(POC_CLRF,popGet(aop,offset));
1632                                         break;
1633                                 } else {
1634                                         emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1635                                 }
1636                         }
1637                         emitpcode(POC_MOVWF,popGet(aop,offset));
1638                 
1639                 }
1640                 break;
1641                 
1642         case AOP_REG:
1643                 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1644                         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1645                         /*
1646                         if (*s == '@'             ||
1647                         strcmp(s,"r0") == 0 ||
1648                         strcmp(s,"r1") == 0 ||
1649                         strcmp(s,"r2") == 0 ||
1650                         strcmp(s,"r3") == 0 ||
1651                         strcmp(s,"r4") == 0 ||
1652                         strcmp(s,"r5") == 0 ||
1653                         strcmp(s,"r6") == 0 || 
1654                         strcmp(s,"r7") == 0 )
1655                         pic14_emitcode("mov","%s,%s  ; %d",
1656                         aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1657                         else
1658                         */
1659                         
1660                         if(strcmp(s,"W")==0 )
1661                                 pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1662                         
1663                         pic14_emitcode("movwf","%s",
1664                                 aop->aopu.aop_reg[offset]->name);
1665                         
1666                         if(strcmp(s,zero)==0) {
1667                                 emitpcode(POC_CLRF,popGet(aop,offset));
1668                                 
1669                         } else if(strcmp(s,"W")==0) {
1670                                 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1671                                 pcop->type = PO_GPR_REGISTER;
1672                                 
1673                                 PCOR(pcop)->rIdx = -1;
1674                                 PCOR(pcop)->r = NULL;
1675                                 
1676                                 DEBUGpic14_emitcode(";","%d",__LINE__);
1677                                 pcop->name = Safe_strdup(s);
1678                                 emitpcode(POC_MOVFW,pcop);
1679                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1680                         } else if(strcmp(s,one)==0) {
1681                                 emitpcode(POC_CLRF,popGet(aop,offset));
1682                                 emitpcode(POC_INCF,popGet(aop,offset));
1683                         } else {
1684                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1685                         }
1686                 }
1687                 break;
1688                 
1689         case AOP_DPTR:
1690         case AOP_DPTR2:
1691                 
1692                 if (aop->type == AOP_DPTR2)
1693                 {
1694                         genSetDPTR(1);
1695                 }
1696                 
1697                 if (aop->code) {
1698                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1699                                 "aopPut writting to code space");
1700                         exit(0);
1701                 }
1702                 
1703                 while (offset > aop->coff) {
1704                         aop->coff++;
1705                         pic14_emitcode ("inc","dptr");
1706                 }
1707                 
1708                 while (offset < aop->coff) {
1709                         aop->coff-- ;
1710                         pic14_emitcode("lcall","__decdptr");
1711                 }
1712                 
1713                 aop->coff = offset;
1714                 
1715                 /* if not in accumulater */
1716                 MOVA(s);
1717                 
1718                 pic14_emitcode ("movx","@dptr,a");
1719                 
1720                 if (aop->type == AOP_DPTR2)
1721                 {
1722                         genSetDPTR(0);
1723                 }
1724                 break;
1725                 
1726         case AOP_R0:
1727         case AOP_R1:
1728                 while (offset > aop->coff) {
1729                         aop->coff++;
1730                         pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1731                 }
1732                 while (offset < aop->coff) {
1733                         aop->coff-- ;
1734                         pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1735                 }
1736                 aop->coff = offset;
1737                 
1738                 if (aop->paged) {
1739                         MOVA(s);                         
1740                         pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1741                         
1742                 } else
1743                         if (*s == '@') {
1744                                 MOVA(s);
1745                                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1746                         } else
1747                                 if (strcmp(s,"r0") == 0 ||
1748                                         strcmp(s,"r1") == 0 ||
1749                                         strcmp(s,"r2") == 0 ||
1750                                         strcmp(s,"r3") == 0 ||
1751                                         strcmp(s,"r4") == 0 ||
1752                                         strcmp(s,"r5") == 0 ||
1753                                         strcmp(s,"r6") == 0 || 
1754                                         strcmp(s,"r7") == 0 ) {
1755                                         char buffer[10];
1756                                         sprintf(buffer,"a%s",s);
1757                                         pic14_emitcode("mov","@%s,%s",
1758                                                 aop->aopu.aop_ptr->name,buffer);
1759                                 } else
1760                                         pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1761                                 
1762                                 break;
1763                                 
1764         case AOP_STK:
1765                 if (strcmp(s,"a") == 0)
1766                         pic14_emitcode("push","acc");
1767                 else
1768                         pic14_emitcode("push","%s",s);
1769                 
1770                 break;
1771                 
1772         case AOP_CRY:
1773                 /* if bit variable */
1774                 if (!aop->aopu.aop_dir) {
1775                         pic14_emitcode("clr","a");
1776                         pic14_emitcode("rlc","a");
1777                 } else {
1778                         if (s == zero) 
1779                                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1780                         else
1781                                 if (s == one)
1782                                         pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1783                                 else
1784                                         if (!strcmp(s,"c"))
1785                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1786                                         else {
1787                                                 lbl = newiTempLabel(NULL);
1788                                                 
1789                                                 if (strcmp(s,"a")) {
1790                                                         MOVA(s);
1791                                                 }
1792                                                 pic14_emitcode("clr","c");
1793                                                 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1794                                                 pic14_emitcode("cpl","c");
1795                                                 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1796                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1797                                         }
1798                 }
1799                 break;
1800                 
1801         case AOP_STR:
1802                 aop->coff = offset;
1803                 if (strcmp(aop->aopu.aop_str[offset],s))
1804                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1805                 break;
1806                 
1807         case AOP_ACC:
1808                 aop->coff = offset;
1809                 if (!offset && (strcmp(s,"acc") == 0))
1810                         break;
1811                 
1812                 if (strcmp(aop->aopu.aop_str[offset],s))
1813                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1814                 break;
1815                 
1816         default :
1817                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1818                         "aopPut got unsupported aop->type");
1819                 exit(0);
1820         }
1821         
1822 }
1823
1824 /*-----------------------------------------------------------------*/
1825 /* mov2w_op - generate either a MOVLW or MOVFW based operand type  */
1826 /*-----------------------------------------------------------------*/
1827 static void mov2w_op (operand *op, int offset)
1828 {
1829         assert (op);
1830         FENTRY;
1831
1832         /* for PO_IMMEDIATEs: use address or value? */
1833         if (op_isLitLike (op))
1834         {
1835                 /* access address of op */
1836                 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1837                 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1838                 {
1839                         if (offset == GPTRSIZE-1)
1840                                 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1841                         else
1842                                 emitpcode (POC_MOVLW, popGetLit (0));
1843                 }
1844                 else
1845                         emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1846         } else {
1847                 /* access value stored in op */
1848                 mov2w (AOP(op), offset);
1849         }
1850 }
1851
1852
1853 /*-----------------------------------------------------------------*/
1854 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1855 /*-----------------------------------------------------------------*/
1856 void mov2w (asmop *aop, int offset)
1857 {
1858         
1859         if(!aop)
1860                 return;
1861         
1862         DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1863         
1864         if ( aop_isLitLike (aop) )
1865                 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1866         else
1867                 emitpcode(POC_MOVFW,popGet(aop,offset));
1868         
1869 }
1870
1871 static void movwf (asmop *op, int offset)
1872 {
1873         emitpcode (POC_MOVWF, popGet(op, offset));
1874 }
1875
1876 static pCodeOp *get_argument_pcop (int idx)
1877 {
1878         assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1879         return popRegFromIdx (Gstack_base_addr - (idx - 1));
1880 }
1881
1882 static pCodeOp *get_return_val_pcop (int offset)
1883 {
1884         assert (offset > 0 && "the most significant byte is returned via WREG");
1885         return popRegFromIdx (Gstack_base_addr - (offset - 1));
1886 }
1887
1888 static void pass_argument (operand *op, int offset, int idx)
1889 {
1890         if (op)
1891                 mov2w_op (op, offset);
1892         if (idx != 0)
1893                 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1894 }
1895
1896 static void get_returnvalue (operand *op, int offset, int idx)
1897 {
1898         if (idx != 0)
1899                 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1900         movwf(AOP(op), offset);
1901 }
1902
1903 static void call_libraryfunc (char *name)
1904 {
1905   /* library code might reside in different page... */
1906   emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1907   /* call the library function */
1908   emitpcode (POC_CALL, popGetExternal (name));
1909   /* might return from different page... */
1910   emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1911 }
1912 #if 0
1913 /*-----------------------------------------------------------------*/
1914 /* reAdjustPreg - points a register back to where it should        */
1915 /*-----------------------------------------------------------------*/
1916 static void reAdjustPreg (asmop *aop)
1917 {
1918         int size ;
1919         
1920         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1921         aop->coff = 0;
1922         if ((size = aop->size) <= 1)
1923                 return ;
1924         size-- ;
1925         switch (aop->type) {
1926         case AOP_R0 :
1927         case AOP_R1 :
1928                 while (size--)
1929                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1930                 break;                  
1931         case AOP_DPTR :
1932         case AOP_DPTR2:
1933                 if (aop->type == AOP_DPTR2)
1934                 {
1935                         genSetDPTR(1);
1936                 } 
1937                 while (size--)
1938                 {
1939                         pic14_emitcode("lcall","__decdptr");
1940                 }
1941                 
1942                 if (aop->type == AOP_DPTR2)
1943                 {
1944                         genSetDPTR(0);
1945                 }
1946                 break;
1947                 
1948         }
1949         
1950 }
1951 #endif
1952
1953
1954 #if 0
1955 /*-----------------------------------------------------------------*/
1956 /* opIsGptr: returns non-zero if the passed operand is             */
1957 /* a generic pointer type.                                         */
1958 /*-----------------------------------------------------------------*/ 
1959 static int opIsGptr(operand *op)
1960 {
1961         sym_link *type = operandType(op);
1962         
1963         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1964         if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1965         {
1966                 return 1;
1967         }
1968         return 0;          
1969 }
1970 #endif
1971
1972 /*-----------------------------------------------------------------*/
1973 /* pic14_getDataSize - get the operand data size                   */
1974 /*-----------------------------------------------------------------*/
1975 int pic14_getDataSize(operand *op)
1976 {
1977         int size;
1978         
1979         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1980         
1981 #if 0
1982         size = getSize(OP_SYM_ETYPE(op));
1983         return size;
1984         //return AOP_SIZE(op);
1985         
1986         // tsd- in the pic port, the genptr size is 1, so this code here
1987         // fails. ( in the 8051 port, the size was 4).
1988 #else
1989         size = AOP_SIZE(op);
1990         if (IS_GENPTR(OP_SYM_TYPE(op)))
1991         {
1992                 sym_link *type = operandType(op);
1993                 if (IS_GENPTR(type))
1994                 {
1995                         /* generic pointer; arithmetic operations
1996                         * should ignore the high byte (pointer type).
1997                         */
1998                         size--;
1999                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2000                 }
2001         }
2002         return size;
2003 #endif
2004 }
2005
2006 /*-----------------------------------------------------------------*/
2007 /* pic14_outAcc - output Acc                                       */
2008 /*-----------------------------------------------------------------*/
2009 void pic14_outAcc(operand *result)
2010 {
2011         int size,offset;
2012         DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2013         DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
2014         
2015         
2016         size = pic14_getDataSize(result);
2017         if(size){
2018                 emitpcode(POC_MOVWF,popGet(AOP(result),0));
2019                 size--;
2020                 offset = 1;
2021                 /* unsigned or positive */
2022                 while(size--)
2023                         emitpcode(POC_CLRF,popGet(AOP(result),offset++));
2024         }
2025         
2026 }
2027
2028 /*-----------------------------------------------------------------*/
2029 /* pic14_outBitC - output a bit C                                  */
2030 /*-----------------------------------------------------------------*/
2031 void pic14_outBitC(operand *result)
2032 {
2033         
2034         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2035         /* if the result is bit */
2036         if (AOP_TYPE(result) == AOP_CRY) 
2037                 aopPut(AOP(result),"c",0);
2038         else {
2039                 pic14_emitcode("clr","a  ; %d", __LINE__);
2040                 pic14_emitcode("rlc","a");
2041                 pic14_outAcc(result);
2042         }
2043 }
2044
2045 /*-----------------------------------------------------------------*/
2046 /* pic14_toBoolean - emit code for orl a,operator(sizeop)          */
2047 /*-----------------------------------------------------------------*/
2048 void pic14_toBoolean(operand *oper)
2049 {
2050         int size = AOP_SIZE(oper);
2051         int offset = 0;
2052         
2053         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2054
2055         assert (size > 0);
2056
2057         if (size == 1) {
2058                 /* MOVFW does not load the flags... */
2059                 if (AOP_TYPE(oper) == AOP_ACC) {
2060                         emitpcode(POC_IORLW, popGetLit(0));
2061                         offset = 1;
2062                 } else {
2063                         emitpcode(POC_MOVLW, popGetLit(0));
2064                         offset = 0;
2065                 }
2066         } else {
2067                 if ( AOP_TYPE(oper) != AOP_ACC) {
2068                         emitpcode(POC_MOVFW,popGet(AOP(oper),0));
2069                         offset = 1;
2070                 }
2071         }
2072         
2073         while (offset < size) {
2074                 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
2075         }
2076         /* Z is set iff (oper == 0) */
2077 }
2078
2079
2080 /*-----------------------------------------------------------------*/
2081 /* genNot - generate code for ! operation                          */
2082 /*-----------------------------------------------------------------*/
2083 static void genNot (iCode *ic)
2084 {
2085         //symbol *tlbl;
2086         int size;
2087
2088         FENTRY;
2089         
2090         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2091         /* assign asmOps to operand & result */
2092         aopOp (IC_LEFT(ic),ic,FALSE);
2093         aopOp (IC_RESULT(ic),ic,TRUE);
2094         
2095         DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2096         /* if in bit space then a special case */
2097         if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2098                 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2099                         emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2100                         emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2101                 } else {
2102                         emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2103                         emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2104                         emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2105                 }
2106                 goto release;
2107         }
2108         
2109         size = AOP_SIZE(IC_LEFT(ic));
2110         mov2w (AOP(IC_LEFT(ic)),0);
2111         while (--size > 0)
2112         {
2113           if (op_isLitLike (IC_LEFT(ic)))
2114             emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2115           else
2116             emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2117         }
2118         emitpcode(POC_MOVLW, popGetLit (0));
2119         emitSKPNZ;
2120         emitpcode(POC_MOVLW, popGetLit (1));
2121         movwf(AOP(IC_RESULT(ic)), 0);
2122
2123         for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2124         {
2125           emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2126         }
2127         goto release;
2128         
2129 release:        
2130         /* release the aops */
2131         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2132         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2133 }
2134
2135
2136 /*-----------------------------------------------------------------*/
2137 /* genCpl - generate code for complement                                                   */
2138 /*-----------------------------------------------------------------*/
2139 static void genCpl (iCode *ic)
2140 {
2141         operand *left, *result;
2142         int size, offset=0;  
2143         
2144         FENTRY;
2145         
2146         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2147         aopOp((left = IC_LEFT(ic)),ic,FALSE);
2148         aopOp((result=IC_RESULT(ic)),ic,TRUE);
2149         
2150         /* if both are in bit space then 
2151         a special case */
2152         if (AOP_TYPE(result) == AOP_CRY &&
2153                 AOP_TYPE(left) == AOP_CRY ) { 
2154                 
2155                 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir); 
2156                 pic14_emitcode("cpl","c"); 
2157                 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir); 
2158                 goto release; 
2159         } 
2160         
2161         size = AOP_SIZE(result);
2162         if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2163         while (size--) {
2164                 
2165                 if(AOP_TYPE(left) == AOP_ACC) 
2166                         emitpcode(POC_XORLW, popGetLit(0xff));
2167                 else
2168                         emitpcode(POC_COMFW,popGet(AOP(left),offset));
2169                 
2170                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2171                 offset++;
2172         }
2173         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2174         
2175         
2176 release:
2177         /* release the aops */
2178         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2179         freeAsmop(result,NULL,ic,TRUE);
2180 }
2181
2182 /*-----------------------------------------------------------------*/
2183 /* genUminusFloat - unary minus for floating points                        */
2184 /*-----------------------------------------------------------------*/
2185 static void genUminusFloat(operand *op,operand *result)
2186 {
2187         int size ,offset =0 ;
2188         char *l;
2189         
2190         FENTRY;
2191
2192         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2193         /* for this we just need to flip the 
2194         first it then copy the rest in place */
2195         size = AOP_SIZE(op) - 1;
2196         l = aopGet(AOP(op),3,FALSE,FALSE);
2197         
2198         MOVA(l);          
2199         
2200         pic14_emitcode("cpl","acc.7");
2201         aopPut(AOP(result),"a",3);      
2202         
2203         while(size--) {
2204                 aopPut(AOP(result),
2205                         aopGet(AOP(op),offset,FALSE,FALSE),
2206                         offset);
2207                 offset++;
2208         }                
2209 }
2210
2211 /*-----------------------------------------------------------------*/
2212 /* genUminus - unary minus code generation                                                 */
2213 /*-----------------------------------------------------------------*/
2214 static void genUminus (iCode *ic)
2215 {
2216         int size, i;
2217         sym_link *optype, *rtype;
2218         
2219         FENTRY;
2220         
2221         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2222         /* assign asmops */
2223         aopOp(IC_LEFT(ic),ic,FALSE);
2224         aopOp(IC_RESULT(ic),ic,TRUE);
2225         
2226         /* if both in bit space then special
2227         case */
2228         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2229                 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2230                 
2231                 emitpcode(POC_BCF,       popGet(AOP(IC_RESULT(ic)),0));
2232                 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2233                 emitpcode(POC_BSF,       popGet(AOP(IC_RESULT(ic)),0));
2234                 
2235                 goto release; 
2236         } 
2237         
2238         optype = operandType(IC_LEFT(ic));
2239         rtype = operandType(IC_RESULT(ic));
2240         
2241         /* if float then do float stuff */
2242         if (IS_FLOAT(optype)) {
2243                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2244                 goto release;
2245         }
2246         
2247         /* otherwise subtract from zero by taking the 2's complement */
2248         size = AOP_SIZE(IC_LEFT(ic));
2249         
2250         for(i=0; i<size; i++) {
2251                 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2252                         emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
2253                 else {
2254                         emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2255                         emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2256                 }
2257         }
2258         
2259         emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
2260         for(i=1; i<size; i++) {
2261                 emitSKPNZ;
2262                 emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
2263         }
2264         
2265 release:
2266         /* release the aops */
2267         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2268         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);  
2269 }
2270
2271 /*-----------------------------------------------------------------*/
2272 /* saveRegisters - will look for a call and save the registers     */
2273 /*-----------------------------------------------------------------*/
2274 static void saveRegisters(iCode *lic) 
2275 {
2276         int i;
2277         iCode *ic;
2278         bitVect *rsave;
2279         sym_link *dtype;
2280         
2281         FENTRY;
2282
2283         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2284         /* look for call */
2285         for (ic = lic ; ic ; ic = ic->next) 
2286                 if (ic->op == CALL || ic->op == PCALL)
2287                         break;
2288                 
2289                 if (!ic) {
2290                         fprintf(stderr,"found parameter push with no function call\n");
2291                         return ;
2292                 }
2293                 
2294                 /* if the registers have been saved already then
2295                 do nothing */
2296                 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2297                         return ;
2298                 
2299                         /* find the registers in use at this time 
2300                 and push them away to safety */
2301                 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2302                         ic->rUsed);
2303                 
2304                 ic->regsSaved = 1;
2305                 if (options.useXstack) {
2306                         if (bitVectBitValue(rsave,R0_IDX))
2307                                 pic14_emitcode("mov","b,r0");
2308                         pic14_emitcode("mov","r0,%s",spname);
2309                         for (i = 0 ; i < pic14_nRegs ; i++) {
2310                                 if (bitVectBitValue(rsave,i)) {
2311                                         if (i == R0_IDX)
2312                                                 pic14_emitcode("mov","a,b");
2313                                         else
2314                                                 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2315                                         pic14_emitcode("movx","@r0,a");
2316                                         pic14_emitcode("inc","r0");
2317                                 }
2318                         }
2319                         pic14_emitcode("mov","%s,r0",spname);
2320                         if (bitVectBitValue(rsave,R0_IDX))
2321                                 pic14_emitcode("mov","r0,b");     
2322                 }// else
2323                 //for (i = 0 ; i < pic14_nRegs ; i++) {
2324                 //        if (bitVectBitValue(rsave,i))
2325                 //      pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2326                 //}
2327                 
2328                 dtype = operandType(IC_LEFT(ic));
2329                 if (currFunc && dtype && 
2330                         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2331                         IFFUNC_ISISR(currFunc->type) &&
2332                         !ic->bankSaved) 
2333                         
2334                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2335                 
2336 }
2337 /*-----------------------------------------------------------------*/
2338 /* unsaveRegisters - pop the pushed registers                                      */
2339 /*-----------------------------------------------------------------*/
2340 static void unsaveRegisters (iCode *ic)
2341 {
2342         int i;
2343         bitVect *rsave;
2344         
2345         FENTRY;
2346
2347         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2348         /* find the registers in use at this time 
2349         and push them away to safety */
2350         rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2351                 ic->rUsed);
2352         
2353         if (options.useXstack) {
2354                 pic14_emitcode("mov","r0,%s",spname); 
2355                 for (i =  pic14_nRegs ; i >= 0 ; i--) {
2356                         if (bitVectBitValue(rsave,i)) {
2357                                 pic14_emitcode("dec","r0");
2358                                 pic14_emitcode("movx","a,@r0");
2359                                 if (i == R0_IDX)
2360                                         pic14_emitcode("mov","b,a");
2361                                 else
2362                                         pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2363                         }       
2364                         
2365                 }
2366                 pic14_emitcode("mov","%s,r0",spname);
2367                 if (bitVectBitValue(rsave,R0_IDX))
2368                         pic14_emitcode("mov","r0,b");
2369         } //else
2370         //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2371         //      if (bitVectBitValue(rsave,i))
2372         //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2373         //}
2374         
2375 }  
2376
2377
2378 /*-----------------------------------------------------------------*/
2379 /* pushSide -                            */
2380 /*-----------------------------------------------------------------*/
2381 static void pushSide(operand * oper, int size)
2382 {
2383 #if 0
2384         int offset = 0;
2385         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2386         while (size--) {
2387                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2388                 if (AOP_TYPE(oper) != AOP_REG &&
2389                         AOP_TYPE(oper) != AOP_DIR &&
2390                         strcmp(l,"a") ) {
2391                         pic14_emitcode("mov","a,%s",l);
2392                         pic14_emitcode("push","acc");
2393                 } else
2394                         pic14_emitcode("push","%s",l);
2395         }
2396 #endif
2397 }
2398
2399 /*-----------------------------------------------------------------*/
2400 /* assignResultValue -                           */
2401 /*-----------------------------------------------------------------*/
2402 static void assignResultValue(operand * oper)
2403 {
2404         int size = AOP_SIZE(oper);
2405         int offset = 0;
2406         
2407         FENTRY;
2408
2409         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2410         
2411         DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2412         
2413         /* assign MSB first (passed via WREG) */
2414         while (size--) {
2415                 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2416                 GpsuedoStkPtr++;
2417         }
2418 }
2419
2420
2421 /*-----------------------------------------------------------------*/
2422 /* genIpush - genrate code for pushing this gets a little complex  */
2423 /*-----------------------------------------------------------------*/
2424 static void genIpush (iCode *ic)
2425 {
2426         FENTRY;
2427         
2428         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2429 #if 0
2430         int size, offset = 0 ;
2431         char *l;
2432         
2433         
2434         /* if this is not a parm push : ie. it is spill push 
2435         and spill push is always done on the local stack */
2436         if (!ic->parmPush) {
2437                 
2438                 /* and the item is spilt then do nothing */
2439                 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2440                         return ;
2441                 
2442                 aopOp(IC_LEFT(ic),ic,FALSE);
2443                 size = AOP_SIZE(IC_LEFT(ic));
2444                 /* push it on the stack */
2445                 while(size--) {
2446                         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2447                         if (*l == '#') {
2448                                 MOVA(l);
2449                                 l = "acc";
2450                         }
2451                         pic14_emitcode("push","%s",l);
2452                 }
2453                 return ;                
2454         }
2455         
2456         /* this is a paramter push: in this case we call
2457         the routine to find the call and save those
2458         registers that need to be saved */   
2459         saveRegisters(ic);
2460         
2461         /* then do the push */
2462         aopOp(IC_LEFT(ic),ic,FALSE);
2463         
2464         
2465         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2466         size = AOP_SIZE(IC_LEFT(ic));
2467         
2468         while (size--) {
2469                 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2470                 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2471                         AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2472                         strcmp(l,"a") ) {
2473                         pic14_emitcode("mov","a,%s",l);
2474                         pic14_emitcode("push","acc");
2475                 } else
2476                         pic14_emitcode("push","%s",l);
2477         }         
2478         
2479         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2480 #endif
2481 }
2482
2483 /*-----------------------------------------------------------------*/
2484 /* genIpop - recover the registers: can happen only for spilling   */
2485 /*-----------------------------------------------------------------*/
2486 static void genIpop (iCode *ic)
2487 {
2488         FENTRY;
2489
2490         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2491         assert (!"genIpop -- unimplemented");
2492 #if 0
2493         int size,offset ;
2494         
2495         
2496         /* if the temp was not pushed then */
2497         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2498                 return ;
2499         
2500         aopOp(IC_LEFT(ic),ic,FALSE);
2501         size = AOP_SIZE(IC_LEFT(ic));
2502         offset = (size-1);
2503         while (size--) 
2504                 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2505                 FALSE,TRUE));
2506         
2507         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2508 #endif
2509 }
2510
2511 /*-----------------------------------------------------------------*/
2512 /* unsaverbank - restores the resgister bank from stack                    */
2513 /*-----------------------------------------------------------------*/
2514 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2515 {
2516         FENTRY;
2517
2518         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2519 #if 0
2520         int i;
2521         asmop *aop ;
2522         regs *r = NULL;
2523         
2524         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2525         if (popPsw) {
2526                 if (options.useXstack) {
2527                         aop = newAsmop(0);
2528                         r = getFreePtr(ic,&aop,FALSE);
2529                         
2530                         
2531                         pic14_emitcode("mov","%s,_spx",r->name);
2532                         pic14_emitcode("movx","a,@%s",r->name);
2533                         pic14_emitcode("mov","psw,a");
2534                         pic14_emitcode("dec","%s",r->name);
2535                         
2536                 }else
2537                         pic14_emitcode ("pop","psw");
2538         }
2539         
2540         for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2541                 if (options.useXstack) {           
2542                         pic14_emitcode("movx","a,@%s",r->name);
2543                         //pic14_emitcode("mov","(%s+%d),a",
2544                         //         regspic14[i].base,8*bank+regspic14[i].offset);
2545                         pic14_emitcode("dec","%s",r->name);
2546                         
2547                 } else 
2548                         pic14_emitcode("pop",""); //"(%s+%d)",
2549                 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2550         }
2551         
2552         if (options.useXstack) {
2553                 
2554                 pic14_emitcode("mov","_spx,%s",r->name);
2555                 freeAsmop(NULL,aop,ic,TRUE);
2556                 
2557         }
2558 #endif 
2559 }
2560
2561 /*-----------------------------------------------------------------*/
2562 /* saverbank - saves an entire register bank on the stack                  */
2563 /*-----------------------------------------------------------------*/
2564 static void saverbank (int bank, iCode *ic, bool pushPsw)
2565 {
2566         FENTRY;
2567
2568         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2569 #if 0
2570         int i;
2571         asmop *aop ;
2572         regs *r = NULL;
2573         
2574         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2575         if (options.useXstack) {
2576                 
2577                 aop = newAsmop(0);
2578                 r = getFreePtr(ic,&aop,FALSE);  
2579                 pic14_emitcode("mov","%s,_spx",r->name);
2580                 
2581         }
2582         
2583         for (i = 0 ; i < pic14_nRegs ;i++) {
2584                 if (options.useXstack) {
2585                         pic14_emitcode("inc","%s",r->name);
2586                         //pic14_emitcode("mov","a,(%s+%d)",
2587                         //               regspic14[i].base,8*bank+regspic14[i].offset);
2588                         pic14_emitcode("movx","@%s,a",r->name);                 
2589                 } else 
2590                         pic14_emitcode("push","");// "(%s+%d)",
2591                 //regspic14[i].base,8*bank+regspic14[i].offset);
2592         }
2593         
2594         if (pushPsw) {
2595                 if (options.useXstack) {
2596                         pic14_emitcode("mov","a,psw");
2597                         pic14_emitcode("movx","@%s,a",r->name); 
2598                         pic14_emitcode("inc","%s",r->name);
2599                         pic14_emitcode("mov","_spx,%s",r->name);                 
2600                         freeAsmop (NULL,aop,ic,TRUE);
2601                         
2602                 } else
2603                         pic14_emitcode("push","psw");
2604                 
2605                 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2606         }
2607         ic->bankSaved = 1;
2608 #endif
2609 }
2610
2611 /*-----------------------------------------------------------------*/
2612 /* genCall - generates a call statement                                                    */
2613 /*-----------------------------------------------------------------*/
2614 static void genCall (iCode *ic)
2615 {
2616         sym_link *dtype;         
2617         symbol *sym;
2618         char *name;
2619         int isExtern;
2620         
2621         FENTRY;
2622
2623         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2624         
2625         /* if caller saves & we have not saved then */
2626         if (!ic->regsSaved)
2627                 saveRegisters(ic);
2628         
2629                 /* if we are calling a function that is not using
2630                 the same register bank then we need to save the
2631         destination registers on the stack */
2632         dtype = operandType(IC_LEFT(ic));
2633         if (currFunc && dtype && 
2634                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2635                 IFFUNC_ISISR(currFunc->type) &&
2636                 !ic->bankSaved) 
2637                 
2638                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2639         
2640         /* if send set is not empty the assign */
2641         if (_G.sendSet) {
2642                 iCode *sic;
2643                 /* For the Pic port, there is no data stack.
2644                 * So parameters passed to functions are stored
2645                 * in registers. (The pCode optimizer will get
2646                 * rid of most of these :).
2647                 */
2648                 int psuedoStkPtr=-1;
2649                 int firstTimeThruLoop = 1;
2650                 
2651                 _G.sendSet = reverseSet(_G.sendSet);
2652                 
2653                 /* First figure how many parameters are getting passed */
2654                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2655                 sic = setNextItem(_G.sendSet)) {
2656                         
2657                         aopOp(IC_LEFT(sic),sic,FALSE);
2658                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2659                         freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2660                 }
2661                 
2662                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2663                 sic = setNextItem(_G.sendSet)) {
2664                         int size, offset = 0;
2665                         
2666                         aopOp(IC_LEFT(sic),sic,FALSE);
2667                         size = AOP_SIZE(IC_LEFT(sic));
2668                         
2669                         while (size--) {
2670                                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2671                                         AopType(AOP_TYPE(IC_LEFT(sic))));
2672                                 
2673                                 if(!firstTimeThruLoop) {
2674                                         /* If this is not the first time we've been through the loop
2675                                         * then we need to save the parameter in a temporary
2676                                         * register. The last byte of the last parameter is
2677                                         * passed in W. */
2678                                         emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2679                                         
2680                                 }
2681                                 firstTimeThruLoop=0;
2682                                 
2683                                 mov2w_op (IC_LEFT(sic),  offset);
2684                                 offset++;
2685                         }
2686                         freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2687                 }
2688                 _G.sendSet = NULL;
2689         }
2690         /* make the call */
2691         sym = OP_SYMBOL(IC_LEFT(ic));
2692         name = sym->rname[0] ? sym->rname : sym->name;
2693         isExtern = IS_EXTERN(sym->etype);
2694         if (isExtern) {
2695                 emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2696         }
2697         emitpcode(POC_CALL,popGetWithString(name,isExtern));
2698         if (isExtern) {
2699                 emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel to restore PCLATH before next goto or call instruction */
2700         }
2701         GpsuedoStkPtr=0;
2702         /* if we need assign a result value */
2703         if ((IS_ITEMP(IC_RESULT(ic)) && 
2704                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2705                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2706                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2707                 
2708                 _G.accInUse++;
2709                 aopOp(IC_RESULT(ic),ic,FALSE);
2710                 _G.accInUse--;
2711                 
2712                 assignResultValue(IC_RESULT(ic));
2713                 
2714                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2715                         AopType(AOP_TYPE(IC_RESULT(ic))));
2716                 
2717                 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2718         }
2719         
2720         /* if register bank was saved then pop them */
2721         if (ic->bankSaved)
2722                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2723         
2724         /* if we hade saved some registers then unsave them */
2725         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2726                 unsaveRegisters (ic);
2727         
2728         
2729 }
2730
2731 /*-----------------------------------------------------------------*/
2732 /* genPcall - generates a call by pointer statement                        */
2733 /*-----------------------------------------------------------------*/
2734 static void genPcall (iCode *ic)
2735 {
2736         sym_link *dtype;
2737         symbol *albl = newiTempLabel(NULL);
2738         symbol *blbl = newiTempLabel(NULL);
2739         PIC_OPCODE poc;
2740         pCodeOp *pcop;
2741         operand *left;
2742         
2743         FENTRY;
2744
2745         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2746         /* if caller saves & we have not saved then */
2747         if (!ic->regsSaved)
2748                 saveRegisters(ic);
2749         
2750                 /* if we are calling a function that is not using
2751                 the same register bank then we need to save the
2752         destination registers on the stack */
2753         dtype = operandType(IC_LEFT(ic));
2754         if (currFunc && dtype && 
2755                 IFFUNC_ISISR(currFunc->type) &&
2756                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2757                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2758         
2759         left = IC_LEFT(ic);
2760         aopOp(left,ic,FALSE);
2761         DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2762         
2763         poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2764         
2765         pushSide(IC_LEFT(ic), FPTRSIZE);
2766         
2767         /* if send set is not empty, assign parameters */
2768         if (_G.sendSet) {
2769                 
2770                 DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2771                 /* no way to pass args - W always gets used to make the call */
2772         }
2773         /* first idea - factor out a common helper function and call it.
2774         But don't know how to get it generated only once in its own block
2775         
2776         if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2777                 char *rname;
2778                 char *buffer;
2779                 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2780                 DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2781                 buffer = Safe_calloc(1,strlen(rname)+16);
2782                 sprintf(buffer, "%s_goto_helper", rname);
2783                 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2784                 free(buffer);
2785         }
2786         */
2787         emitpcode(POC_CALL,popGetLabel(albl->key));
2788         pcop = popGetLabel(blbl->key);
2789         emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2790         emitpcode(POC_GOTO,pcop);
2791         emitpLabel(albl->key);
2792         
2793         emitpcode(poc,popGetAddr(AOP(left),1,0));
2794         emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2795         emitpcode(poc,popGetAddr(AOP(left),0,0));
2796         emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2797         
2798         emitpLabel(blbl->key);
2799         
2800         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2801         
2802         /* if we need to assign a result value */
2803         if ((IS_ITEMP(IC_RESULT(ic)) &&
2804                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2805                 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2806                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2807                 
2808                 _G.accInUse++;
2809                 aopOp(IC_RESULT(ic),ic,FALSE);
2810                 _G.accInUse--;
2811
2812                 GpsuedoStkPtr = 0;
2813                 
2814                 assignResultValue(IC_RESULT(ic));
2815                 
2816                 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2817         }
2818         
2819         /* if register bank was saved then unsave them */
2820         if (currFunc && dtype && 
2821                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2822                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2823         
2824                 /* if we hade saved some registers then
2825         unsave them */
2826         if (ic->regsSaved)
2827                 unsaveRegisters (ic);
2828         
2829 }
2830
2831 /*-----------------------------------------------------------------*/
2832 /* resultRemat - result  is rematerializable                                       */
2833 /*-----------------------------------------------------------------*/
2834 static int resultRemat (iCode *ic)
2835 {
2836         //      DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2837         FENTRY;
2838
2839         if (SKIP_IC(ic) || ic->op == IFX)
2840                 return 0;
2841         
2842         if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2843                 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2844                 if (sym->remat && !POINTER_SET(ic)) 
2845                         return 1;
2846         }
2847         
2848         return 0;
2849 }
2850
2851 #if defined(__BORLANDC__) || defined(_MSC_VER)
2852 #define STRCASECMP stricmp
2853 #else
2854 #define STRCASECMP strcasecmp
2855 #endif
2856
2857 #if 0
2858 /*-----------------------------------------------------------------*/
2859 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2860 /*-----------------------------------------------------------------*/
2861 static bool inExcludeList(char *s)
2862 {
2863         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2864         int i =0;
2865         
2866         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2867         if (options.excludeRegs[i] &&
2868                 STRCASECMP(options.excludeRegs[i],"none") == 0)
2869                 return FALSE ;
2870         
2871         for ( i = 0 ; options.excludeRegs[i]; i++) {
2872                 if (options.excludeRegs[i] &&
2873                         STRCASECMP(s,options.excludeRegs[i]) == 0)
2874                         return TRUE;
2875         }
2876         return FALSE ;
2877 }
2878 #endif
2879
2880 /*-----------------------------------------------------------------*/
2881 /* genFunction - generated code for function entry                                 */
2882 /*-----------------------------------------------------------------*/
2883 static void genFunction (iCode *ic)
2884 {
2885         symbol *sym;
2886         sym_link *ftype;
2887         
2888         FENTRY;
2889
2890         DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2891         
2892         labelOffset += (max_key+4);
2893         max_key=0;
2894         GpsuedoStkPtr=0;
2895         _G.nRegsSaved = 0;
2896         /* create the function header */
2897         pic14_emitcode(";","-----------------------------------------");
2898         pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2899         pic14_emitcode(";","-----------------------------------------");
2900         
2901         /* prevent this symbol from being emitted as 'extern' */
2902         pic14_stringInSet(sym->rname, &pic14_localFunctions, 1);
2903
2904         pic14_emitcode("","%s:",sym->rname);
2905         addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2906         
2907         ftype = operandType(IC_LEFT(ic));
2908         
2909         /* if critical function then turn interrupts off */
2910         if (IFFUNC_ISCRITICAL(ftype))
2911                 pic14_emitcode("clr","ea");
2912         
2913                 /* here we need to generate the equates for the
2914         register bank if required */
2915 #if 0
2916         if (FUNC_REGBANK(ftype) != rbank) {
2917                 int i ;
2918                 
2919                 rbank = FUNC_REGBANK(ftype);
2920                 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2921                         if (strcmp(regspic14[i].base,"0") == 0)
2922                                 pic14_emitcode("","%s = 0x%02x",
2923                                 regspic14[i].dname,
2924                                 8*rbank+regspic14[i].offset);
2925                         else
2926                                 pic14_emitcode ("","%s = %s + 0x%02x",
2927                                 regspic14[i].dname,
2928                                 regspic14[i].base,
2929                                 8*rbank+regspic14[i].offset);
2930                 }
2931         }
2932 #endif
2933         
2934         /* if this is an interrupt service routine */
2935         if (IFFUNC_ISISR(sym->type)) {
2936         /*  already done in pic14createInterruptVect() - delete me
2937         addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2938         emitpcodeNULLop(POC_NOP);
2939         emitpcodeNULLop(POC_NOP);
2940         emitpcodeNULLop(POC_NOP);
2941                 */
2942                 emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2943                 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2944                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2945                 emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2946                 emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2947                 emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2948                 emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2949                 
2950                 pBlockConvert2ISR(pb);
2951                 pic14_hasInterrupt = 1;
2952 #if 0  
2953                 if (!inExcludeList("acc"))              
2954                         pic14_emitcode ("push","acc");  
2955                 if (!inExcludeList("b"))
2956                         pic14_emitcode ("push","b");
2957                 if (!inExcludeList("dpl"))
2958                         pic14_emitcode ("push","dpl");
2959                 if (!inExcludeList("dph"))
2960                         pic14_emitcode ("push","dph");
2961                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2962                 {
2963                         pic14_emitcode ("push", "dpx");
2964                         /* Make sure we're using standard DPTR */
2965                         pic14_emitcode ("push", "dps");
2966                         pic14_emitcode ("mov", "dps, #0x00");
2967                         if (options.stack10bit)
2968                         { 
2969                                 /* This ISR could conceivably use DPTR2. Better save it. */
2970                                 pic14_emitcode ("push", "dpl1");
2971                                 pic14_emitcode ("push", "dph1");
2972                                 pic14_emitcode ("push", "dpx1");
2973                         }
2974                 }
2975                 /* if this isr has no bank i.e. is going to
2976                 run with bank 0 , then we need to save more
2977                 registers :-) */
2978                 if (!FUNC_REGBANK(sym->type)) {
2979                         
2980                 /* if this function does not call any other
2981                 function then we can be economical and
2982                         save only those registers that are used */
2983                         if (! IFFUNC_HASFCALL(sym->type)) {
2984                                 int i;
2985                                 
2986                                 /* if any registers used */
2987                                 if (sym->regsUsed) {
2988                                         /* save the registers used */
2989                                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2990                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2991                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2992                                                         pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);               
2993                                         }
2994                                 }
2995                                 
2996                         } else {
2997                         /* this function has    a function call cannot
2998                         determines register usage so we will have the
2999                                 entire bank */
3000                                 saverbank(0,ic,FALSE);
3001                         }       
3002                 }
3003 #endif
3004         } else {
3005         /* if callee-save to be used for this function
3006                 then save the registers being used in this function */
3007                 if (IFFUNC_CALLEESAVES(sym->type)) {
3008                         int i;
3009                         
3010                         /* if any registers used */
3011                         if (sym->regsUsed) {
3012                                 /* save the registers used */
3013                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3014                                         if (bitVectBitValue(sym->regsUsed,i) ||
3015                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
3016                                                 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
3017                                                 _G.nRegsSaved++;
3018                                         }
3019                                 }
3020                         }
3021                 }
3022         }
3023         
3024         /* set the register bank to the desired value */
3025         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
3026                 pic14_emitcode("push","psw");
3027                 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);       
3028         }
3029         
3030         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3031                 
3032                 if (options.useXstack) {
3033                         pic14_emitcode("mov","r0,%s",spname);
3034                         pic14_emitcode("mov","a,_bp");
3035                         pic14_emitcode("movx","@r0,a");
3036                         pic14_emitcode("inc","%s",spname);
3037                 }
3038                 else
3039                 {
3040                         /* set up the stack */
3041                         pic14_emitcode ("push","_bp");   /* save the callers stack      */
3042                 }
3043                 pic14_emitcode ("mov","_bp,%s",spname);
3044         }
3045         
3046         /* adjust the stack for the function */
3047         if (sym->stack) {
3048                 
3049                 int i = sym->stack;
3050                 if (i > 256 ) 
3051                         werror(W_STACK_OVERFLOW,sym->name);
3052                 
3053                 if (i > 3 && sym->recvSize < 4) {                
3054                         
3055                         pic14_emitcode ("mov","a,sp");
3056                         pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3057                         pic14_emitcode ("mov","sp,a");
3058                         
3059                 }
3060                 else
3061                         while(i--)
3062                                 pic14_emitcode("inc","sp");
3063         }
3064         
3065         if (sym->xstack) {
3066                 
3067                 pic14_emitcode ("mov","a,_spx");
3068                 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3069                 pic14_emitcode ("mov","_spx,a");
3070         }
3071         
3072 }
3073
3074 /*-----------------------------------------------------------------*/
3075 /* genEndFunction - generates epilogue for functions                       */
3076 /*-----------------------------------------------------------------*/
3077 static void genEndFunction (iCode *ic)
3078 {
3079         symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3080         
3081         FENTRY;
3082
3083         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3084         
3085         if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3086         {
3087                 pic14_emitcode ("mov","%s,_bp",spname);
3088         }
3089         
3090         /* if use external stack but some variables were
3091         added to the local stack then decrement the
3092         local stack */
3093         if (options.useXstack && sym->stack) {    
3094                 pic14_emitcode("mov","a,sp");
3095                 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3096                 pic14_emitcode("mov","sp,a");
3097         }
3098         
3099         
3100         if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3101                 if (options.useXstack) {
3102                         pic14_emitcode("mov","r0,%s",spname);
3103                         pic14_emitcode("movx","a,@r0");
3104                         pic14_emitcode("mov","_bp,a");
3105                         pic14_emitcode("dec","%s",spname);
3106                 }
3107                 else
3108                 {
3109                         pic14_emitcode ("pop","_bp");
3110                 }
3111         }
3112         
3113         /* restore the register bank    */        
3114         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3115                 pic14_emitcode ("pop","psw");
3116         
3117         if (IFFUNC_ISISR(sym->type)) {
3118                 
3119                 /* now we need to restore the registers */
3120                 /* if this isr has no bank i.e. is going to
3121                 run with bank 0 , then we need to save more
3122 registers :-) */
3123                 if (!FUNC_REGBANK(sym->type)) {
3124                         
3125                 /* if this function does not call any other
3126                 function then we can be economical and
3127                         save only those registers that are used */
3128                         if (! IFFUNC_HASFCALL(sym->type)) {
3129                                 int i;
3130                                 
3131                                 /* if any registers used */
3132                                 if (sym->regsUsed) {
3133                                         /* save the registers used */
3134                                         for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3135                                                 if (bitVectBitValue(sym->regsUsed,i) ||
3136                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3137                                                         pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3138                                         }
3139                                 }
3140                                 
3141                         } else {
3142                         /* this function has    a function call cannot
3143                         determines register usage so we will have the
3144                                 entire bank */
3145                                 unsaverbank(0,ic,FALSE);
3146                         }       
3147                 }
3148 #if 0
3149                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3150                 {
3151                         if (options.stack10bit)
3152                         {
3153                                 pic14_emitcode ("pop", "dpx1");
3154                                 pic14_emitcode ("pop", "dph1");
3155                                 pic14_emitcode ("pop", "dpl1");
3156                         } 
3157                         pic14_emitcode ("pop", "dps");
3158                         pic14_emitcode ("pop", "dpx");
3159                 }
3160                 if (!inExcludeList("dph"))
3161                         pic14_emitcode ("pop","dph");
3162                 if (!inExcludeList("dpl"))
3163                         pic14_emitcode ("pop","dpl");
3164                 if (!inExcludeList("b"))
3165                         pic14_emitcode ("pop","b");
3166                 if (!inExcludeList("acc"))
3167                         pic14_emitcode ("pop","acc");
3168                 
3169                 if (IFFUNC_ISCRITICAL(sym->type))
3170                         pic14_emitcode("setb","ea");
3171 #endif
3172                 
3173                 /* if debug then send end of function */
3174                 /*      if (options.debug && currFunc) { */
3175                 if (currFunc) {
3176                         debugFile->writeEndFunction (currFunc, ic, 1);
3177                 }
3178                 
3179                 pic14_emitcode ("reti","");
3180                 emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
3181                 emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
3182                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
3183                 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3184                 emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
3185                 emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
3186                 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3187                 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3188                 emitpcodeNULLop(POC_RETFIE);
3189         }
3190         else {
3191                 if (IFFUNC_ISCRITICAL(sym->type))
3192                         pic14_emitcode("setb","ea");
3193                 
3194                 if (IFFUNC_CALLEESAVES(sym->type)) {
3195                         int i;
3196                         
3197                         /* if any registers used */
3198                         if (sym->regsUsed) {
3199                                 /* save the registers used */
3200                                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3201                                         if (bitVectBitValue(sym->regsUsed,i) ||
3202                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3203                                                 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3204                                 }
3205                         }
3206                         
3207                 }
3208                 
3209                 /* if debug then send end of function */
3210                 if (currFunc) {
3211                         debugFile->writeEndFunction (currFunc, ic, 1);
3212                 }
3213                 
3214                 pic14_emitcode ("return","");
3215                 emitpcodeNULLop(POC_RETURN);
3216                 
3217                 /* Mark the end of a function */
3218                 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3219         }
3220         
3221 }
3222
3223 /*-----------------------------------------------------------------*/
3224 /* genRet - generate code for return statement                                     */
3225 /*-----------------------------------------------------------------*/
3226 static void genRet (iCode *ic)
3227 {
3228         int size,offset = 0;
3229         
3230         FENTRY;
3231
3232         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3233         /* if we have no return value then
3234         just generate the "ret" */
3235         if (!IC_LEFT(ic)) 
3236                 goto jumpret;           
3237         
3238                 /* we have something to return then
3239         move the return value into place */
3240         aopOp(IC_LEFT(ic),ic,FALSE);
3241         size = AOP_SIZE(IC_LEFT(ic));
3242
3243         for (offset = 0; offset < size; offset++)
3244         {
3245                 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3246         }
3247         
3248         freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3249         
3250 jumpret:
3251         /* generate a jump to the return label
3252         if the next is not the return statement */
3253         if (!(ic->next && ic->next->op == LABEL &&
3254                 IC_LABEL(ic->next) == returnLabel)) {
3255                 
3256                 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3257         }
3258         
3259 }
3260
3261 /*-----------------------------------------------------------------*/
3262 /* genLabel - generates a label                                                                    */
3263 /*-----------------------------------------------------------------*/
3264 static void genLabel (iCode *ic)
3265 {
3266         FENTRY;
3267
3268         /* special case never generate */
3269         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3270         if (IC_LABEL(ic) == entryLabel)
3271                 return ;
3272         
3273         emitpLabel(IC_LABEL(ic)->key);
3274         pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3275 }
3276
3277 /*-----------------------------------------------------------------*/
3278 /* genGoto - generates a goto                                                                      */
3279 /*-----------------------------------------------------------------*/
3280 //tsd
3281 static void genGoto (iCode *ic)
3282 {
3283         FENTRY;
3284
3285         emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3286         pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3287 }
3288
3289
3290 /*-----------------------------------------------------------------*/
3291 /* genMultbits :- multiplication of bits                                                   */
3292 /*-----------------------------------------------------------------*/
3293 static void genMultbits (operand *left, 
3294                                                  operand *right, 
3295                                                  operand *result)
3296 {
3297         FENTRY;
3298         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3299         
3300         if(!pic14_sameRegs(AOP(result),AOP(right)))
3301                 emitpcode(POC_BSF,      popGet(AOP(result),0));
3302         
3303         emitpcode(POC_BTFSC,popGet(AOP(right),0));
3304         emitpcode(POC_BTFSS,popGet(AOP(left),0));
3305         emitpcode(POC_BCF,  popGet(AOP(result),0));
3306         
3307 }
3308
3309
3310 /*-----------------------------------------------------------------*/
3311 /* genMultOneByte : 8 bit multiplication & division                        */
3312 /*-----------------------------------------------------------------*/
3313 static void genMultOneByte (operand *left,
3314                                                         operand *right,
3315                                                         operand *result)
3316 {
3317         char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3318         
3319         // symbol *lbl ;
3320         int size,offset,i;
3321         
3322         
3323         FENTRY;
3324         
3325         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3326         DEBUGpic14_AopType(__LINE__,left,right,result);
3327         DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3328         
3329         /* (if two literals, the value is computed before) */
3330         /* if one literal, literal on the right */
3331         if (AOP_TYPE(left) == AOP_LIT){
3332                 operand *t = right;
3333                 right = left;
3334                 left = t;
3335         }
3336
3337         assert (AOP_SIZE(left) == AOP_SIZE(right));
3338         
3339         size = min(AOP_SIZE(result),AOP_SIZE(left));
3340         offset = Gstack_base_addr - (2*size - 1);
3341
3342         /* pass right operand as argument */
3343         for (i=0; i < size; i++)
3344         {
3345                 mov2w (AOP(right), i);
3346                 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3347         } // for
3348         
3349         /* pass left operand as argument */
3350         for (i=0; i < size; i++)
3351         {
3352                 mov2w (AOP(left), i);
3353                 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3354         } // for
3355         assert (offset == Gstack_base_addr);
3356         
3357         /* call library routine */
3358         assert (size > 0 && size <= 4);
3359         call_libraryfunc (func[size]);
3360         
3361         /* assign result */
3362         movwf (AOP(result), size-1);
3363         for (i=0; i < size - 1; i++)
3364         {
3365                 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3366                 movwf (AOP(result), size - 2 - i);
3367         } // for
3368
3369         /* now (zero-/sign) extend the result to its size */
3370         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3371 }
3372
3373 /*-----------------------------------------------------------------*/
3374 /* genMult - generates code for multiplication                                     */
3375 /*-----------------------------------------------------------------*/
3376 static void genMult (iCode *ic)
3377 {
3378         operand *left = IC_LEFT(ic);
3379         operand *right = IC_RIGHT(ic);
3380         operand *result= IC_RESULT(ic); 
3381         
3382         FENTRY;
3383
3384         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3385         /* assign the amsops */
3386         aopOp (left,ic,FALSE);
3387         aopOp (right,ic,FALSE);
3388         aopOp (result,ic,TRUE);
3389         
3390         DEBUGpic14_AopType(__LINE__,left,right,result);
3391         
3392         /* special cases first */
3393         /* both are bits */
3394         if (AOP_TYPE(left) == AOP_CRY &&
3395                 AOP_TYPE(right)== AOP_CRY) {
3396                 genMultbits(left,right,result);
3397                 goto release ;
3398         }
3399         
3400         /* if both are of size == 1 */
3401         if (AOP_SIZE(left) == 1 &&
3402                 AOP_SIZE(right) == 1 ) {
3403                 genMultOneByte(left,right,result);
3404                 goto release ;
3405         }
3406         
3407         /* should have been converted to function call */
3408         assert(0) ;
3409         
3410 release :
3411         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3412         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3413         freeAsmop(result,NULL,ic,TRUE); 
3414 }
3415
3416 /*-----------------------------------------------------------------*/
3417 /* genDivbits :- division of bits                                                                  */
3418 /*-----------------------------------------------------------------*/
3419 static void genDivbits (operand *left, 
3420                                                 operand *right, 
3421                                                 operand *result)
3422 {
3423         
3424         char *l;
3425         
3426         FENTRY;
3427
3428         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3429         /* the result must be bit */      
3430         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3431         l = aopGet(AOP(left),0,FALSE,FALSE);
3432         
3433         MOVA(l);          
3434         
3435         pic14_emitcode("div","ab");
3436         pic14_emitcode("rrc","a");
3437         aopPut(AOP(result),"c",0);
3438 }
3439
3440 /*-----------------------------------------------------------------*/
3441 /* genDivOneByte : 8 bit division                                                                  */
3442 /*-----------------------------------------------------------------*/
3443 static void genDivOneByte (operand *left,
3444                                                    operand *right,
3445                                                    operand *result)
3446 {
3447         int size;
3448         
3449         FENTRY;
3450         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3451         
3452         assert (AOP_SIZE(result) == 1);
3453         assert (AOP_SIZE(right) == 1);
3454         assert (AOP_SIZE(left) == 1);
3455
3456         size = min(AOP_SIZE(result),AOP_SIZE(left));
3457
3458         if (AOP_TYPE(right) == AOP_LIT)
3459         {
3460                 /* XXX: might add specialized code */
3461         }
3462
3463         if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3464         {
3465                 /* unsigned division */
3466         #if 1
3467                 mov2w(AOP(right),0);
3468                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3469                 mov2w(AOP(left),0);
3470                 call_libraryfunc("__divuchar");
3471                 movwf(AOP(result),0);
3472         #else
3473                 pCodeOp *temp;
3474                 symbol *lbl;
3475
3476                 temp = popGetTempReg();
3477                 lbl = newiTempLabel(NULL);
3478                 
3479                 /* XXX: improve this naive approach:
3480                    [result] = [a] / [b]
3481                         ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3482
3483                    In PIC assembler:
3484                    movf  left,W
3485                    movwf temp           // temp <-- left
3486                    movf  right,W        // W <-- right
3487                    clrf  result
3488                    label1:
3489                    incf  result
3490                    subwf temp,F         // temp <-- temp - W
3491                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if temp < W
3492                    goto  label1
3493                    decf result          // we just subtract once too often
3494                  */
3495
3496                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3497                 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3498                 
3499                 mov2w(AOP(left),0);
3500                 emitpcode(POC_MOVWF, temp);
3501                 mov2w(AOP(right),0);
3502                 emitpcode(POC_CLRF, popGet(AOP(result),0));
3503
3504                 emitpLabel(lbl->key);
3505                 emitpcode(POC_INCF, popGet(AOP(result),0));
3506                 emitpcode(POC_SUBWF, temp);
3507                 emitSKPNC;
3508                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3509                 emitpcode(POC_DECF, popGet(AOP(result),0));
3510         #endif
3511         }
3512         else
3513         {
3514                 /* signed division */
3515                 mov2w(AOP(right),0);
3516                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3517                 mov2w(AOP(left),0);
3518                 call_libraryfunc("__divschar");
3519                 movwf(AOP(result),0);
3520         }
3521
3522         /* now performed the signed/unsigned division -- extend result */
3523         addSign(result, 1, !SPEC_USIGN(operandType(result)));
3524 }
3525
3526 /*-----------------------------------------------------------------*/
3527 /* genDiv - generates code for division                            */
3528 /*-----------------------------------------------------------------*/
3529 static void genDiv (iCode *ic)
3530 {
3531         operand *left = IC_LEFT(ic);
3532         operand *right = IC_RIGHT(ic);
3533         operand *result= IC_RESULT(ic); 
3534         
3535         FENTRY;
3536         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3537         /* assign the amsops */
3538         aopOp (left,ic,FALSE);
3539         aopOp (right,ic,FALSE);
3540         aopOp (result,ic,TRUE);
3541         
3542         /* special cases first */
3543         /* both are bits */
3544         if (AOP_TYPE(left) == AOP_CRY &&
3545                 AOP_TYPE(right)== AOP_CRY) {
3546                 genDivbits(left,right,result);
3547                 goto release ;
3548         }
3549         
3550         /* if both are of size == 1 */
3551         if (AOP_SIZE(left) == 1 &&
3552                 AOP_SIZE(right) == 1 ) {
3553                 genDivOneByte(left,right,result);
3554                 goto release ;
3555         }
3556         
3557         /* should have been converted to function call */
3558         assert(0);
3559 release :
3560         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3561         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3562         freeAsmop(result,NULL,ic,TRUE); 
3563 }
3564
3565 /*-----------------------------------------------------------------*/
3566 /* genModbits :- modulus of bits                                                                   */
3567 /*-----------------------------------------------------------------*/
3568 static void genModbits (operand *left, 
3569                                                 operand *right, 
3570                                                 operand *result)
3571 {
3572         
3573         char *l;
3574         
3575         FENTRY;
3576         /* the result must be bit */      
3577         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3578         l = aopGet(AOP(left),0,FALSE,FALSE);
3579         
3580         MOVA(l);
3581         
3582         pic14_emitcode("div","ab");
3583         pic14_emitcode("mov","a,b");
3584         pic14_emitcode("rrc","a");
3585         aopPut(AOP(result),"c",0);
3586 }
3587
3588 /*-----------------------------------------------------------------*/
3589 /* genModOneByte : 8 bit modulus                                                                   */
3590 /*-----------------------------------------------------------------*/
3591 static void genModOneByte (operand *left,
3592                                                    operand *right,
3593                                                    operand *result)
3594 {
3595         int size;
3596         
3597         FENTRY;
3598         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3599         
3600         assert (AOP_SIZE(result) == 1);
3601         assert (AOP_SIZE(right) == 1);
3602         assert (AOP_SIZE(left) == 1);
3603
3604         size = min(AOP_SIZE(result),AOP_SIZE(left));
3605
3606         if (AOP_TYPE(right) == AOP_LIT)
3607         {
3608                 /* XXX: might add specialized code */
3609         }
3610
3611         if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3612         {
3613                 /* unsigned division */
3614         #if 1
3615                 mov2w(AOP(right),0);
3616                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3617                 mov2w(AOP(left),0);
3618                 call_libraryfunc("__moduchar");
3619                 movwf(AOP(result),0);
3620         #else
3621                 pCodeOp *temp;
3622                 symbol *lbl;
3623
3624                 lbl = newiTempLabel(NULL);
3625                 
3626                 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3627
3628                 /* XXX: improve this naive approach:
3629                    [result] = [a] % [b]
3630                         ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3631
3632                    In PIC assembler:
3633                    movf  left,W
3634                    movwf result         // result <-- left
3635                    movf  right,W        // W <-- right
3636                    label1:
3637                    subwf result,F       // result <-- result - W
3638                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if result < W
3639                    goto  label1
3640                    addwf result, F      // we just subtract once too often
3641                  */
3642
3643                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3644                 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3645                 
3646                 if (!pic14_sameRegs(AOP(left), AOP(result)))
3647                 {
3648                         mov2w(AOP(left),0);
3649                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
3650                 }
3651                 mov2w(AOP(right),0);
3652
3653                 emitpLabel(lbl->key);
3654                 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3655                 emitSKPNC;
3656                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3657                 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3658         #endif
3659         }
3660         else
3661         {
3662                 /* signed division */
3663                 mov2w(AOP(right),0);
3664                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3665                 mov2w(AOP(left),0);
3666                 call_libraryfunc("__modschar");
3667                 movwf(AOP(result),0);
3668         }
3669
3670         /* now we performed the signed/unsigned modulus -- extend result */
3671         addSign(result, 1, !SPEC_USIGN(operandType(result)));
3672 }
3673
3674 /*-----------------------------------------------------------------*/
3675 /* genMod - generates code for division                                                    */
3676 /*-----------------------------------------------------------------*/
3677 static void genMod (iCode *ic)
3678 {
3679         operand *left = IC_LEFT(ic);
3680         operand *right = IC_RIGHT(ic);
3681         operand *result= IC_RESULT(ic);  
3682         
3683         FENTRY;
3684         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3685         /* assign the amsops */
3686         aopOp (left,ic,FALSE);
3687         aopOp (right,ic,FALSE);
3688         aopOp (result,ic,TRUE);
3689         
3690         /* special cases first */
3691         /* both are bits */
3692         if (AOP_TYPE(left) == AOP_CRY &&
3693                 AOP_TYPE(right)== AOP_CRY) {
3694                 genModbits(left,right,result);
3695                 goto release ;
3696         }
3697         
3698         /* if both are of size == 1 */
3699         if (AOP_SIZE(left) == 1 &&
3700                 AOP_SIZE(right) == 1 ) {
3701                 genModOneByte(left,right,result);
3702                 goto release ;
3703         }
3704         
3705         /* should have been converted to function call */
3706         assert(0);
3707         
3708 release :
3709         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3710         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3711         freeAsmop(result,NULL,ic,TRUE); 
3712 }
3713
3714 /*-----------------------------------------------------------------*/
3715 /* genIfxJump :- will create a jump depending on the ifx                   */
3716 /*-----------------------------------------------------------------*/
3717 /*
3718 note: May need to add parameter to indicate when a variable is in bit space.
3719 */
3720 static void genIfxJump (iCode *ic, char *jval)
3721 {
3722         
3723         FENTRY;
3724         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3725         /* if true label then we jump if condition
3726         supplied is true */
3727         if ( IC_TRUE(ic) ) {
3728                 
3729                 if(strcmp(jval,"a") == 0)
3730                         emitSKPZ;
3731                 else if (strcmp(jval,"c") == 0)
3732                         emitSKPC;
3733                 else {
3734                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3735                         emitpcode(POC_BTFSC,    newpCodeOpBit(jval,-1,1));
3736                 }
3737                 
3738                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3739                 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3740                 
3741         }
3742         else {
3743                 /* false label is present */
3744                 if(strcmp(jval,"a") == 0)
3745                         emitSKPNZ;
3746                 else if (strcmp(jval,"c") == 0)
3747                         emitSKPNC;
3748                 else {
3749                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3750                         emitpcode(POC_BTFSS,    newpCodeOpBit(jval,-1,1));
3751                 }
3752                 
3753                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3754                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3755                 
3756         }
3757         
3758         
3759         /* mark the icode as generated */
3760         ic->generated = 1;
3761 }
3762
3763 #if 0
3764 /*-----------------------------------------------------------------*/
3765 /* genSkip                                                                                                                 */
3766 /*-----------------------------------------------------------------*/
3767 static void genSkip(iCode *ifx,int status_bit)
3768 {
3769         FENTRY;
3770         if(!ifx)
3771                 return;
3772         
3773         if ( IC_TRUE(ifx) ) {
3774                 switch(status_bit) {
3775                 case 'z':
3776                         emitSKPNZ;
3777                         break;
3778                         
3779                 case 'c':
3780                         emitSKPNC;
3781                         break;
3782                         
3783                 case 'd':
3784                         emitSKPDC;
3785                         break;
3786                         
3787                 }
3788                 
3789                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3790                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3791                 
3792         } else {
3793                 
3794                 switch(status_bit) {
3795                         
3796                 case 'z':
3797                         emitSKPZ;
3798                         break;
3799                         
3800                 case 'c':
3801                         emitSKPC;
3802                         break;
3803                         
3804                 case 'd':
3805                         emitSKPDC;
3806                         break;
3807                 }
3808                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3809                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3810                 
3811         }
3812         
3813 }
3814 #endif
3815
3816 /*-----------------------------------------------------------------*/
3817 /* genSkipc                                                                                                        */
3818 /*-----------------------------------------------------------------*/
3819 static void genSkipc(resolvedIfx *rifx)
3820 {
3821         FENTRY;
3822         if(!rifx)
3823                 return;
3824         
3825         if(rifx->condition)
3826                 emitSKPNC;
3827         else
3828                 emitSKPC;
3829         
3830         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3831         emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3832         rifx->generated = 1;
3833 }
3834
3835 #if 0
3836 /*-----------------------------------------------------------------*/
3837 /* genSkipz2                                                                                                       */
3838 /*-----------------------------------------------------------------*/
3839 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3840 {
3841         FENTRY;
3842         if(!rifx)
3843                 return;
3844         
3845         if( (rifx->condition ^ invert_condition) & 1)
3846                 emitSKPZ;
3847         else
3848                 emitSKPNZ;
3849         
3850         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3851         rifx->generated = 1;
3852 }
3853 #endif
3854
3855 #if 0
3856 /*-----------------------------------------------------------------*/
3857 /* genSkipz                                                        */
3858 /*-----------------------------------------------------------------*/
3859 static void genSkipz(iCode *ifx, int condition)
3860 {
3861         FENTRY;
3862         assert (ifx != NULL);
3863         
3864         if(condition)
3865                 emitSKPNZ;
3866         else
3867                 emitSKPZ;
3868         
3869         if ( IC_TRUE(ifx) )
3870                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3871         else
3872                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3873         
3874         if ( IC_TRUE(ifx) )
3875                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3876         else
3877                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3878         
3879 }
3880 #endif
3881
3882 #if 0
3883 /*-----------------------------------------------------------------*/
3884 /* genSkipCond                                                     */
3885 /*-----------------------------------------------------------------*/
3886 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3887 {
3888         FENTRY;
3889         if(!rifx)
3890                 return;
3891         
3892         if(rifx->condition)
3893                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3894         else
3895                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3896         
3897         
3898         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3899         rifx->generated = 1;
3900 }
3901 #endif
3902
3903 #if 0
3904 /*-----------------------------------------------------------------*/
3905 /* genChkZeroes :- greater or less than comparison                 */
3906 /*     For each byte in a literal that is zero, inclusive or the   */
3907 /*     the corresponding byte in the operand with W                */
3908 /*     returns true if any of the bytes are zero                   */
3909 /*-----------------------------------------------------------------*/
3910 static int genChkZeroes(operand *op, int lit,  int size)
3911 {
3912         
3913         int i;
3914         int flag =1;
3915         
3916         while(size--) {
3917                 i = (lit >> (size*8)) & 0xff;
3918                 
3919                 if(i==0) {
3920                         if(flag) 
3921                                 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3922                         else
3923                                 emitpcode(POC_IORFW, popGet(AOP(op),size));
3924                         flag = 0;
3925                 }
3926         }
3927         
3928         return (flag==0);
3929 }
3930 #endif
3931
3932
3933 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3934 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
3935 #define DEBUGpc           emitpComment
3936
3937 /*-----------------------------------------------------------------*/
3938 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
3939 /*                  aop (if it's NOT a literal) or from lit (if    */
3940 /*                  aop is a literal)                              */
3941 /*-----------------------------------------------------------------*/
3942 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3943   if (aop->type == AOP_LIT) {
3944     emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3945   } else {
3946     emitpcode (POC_MOVFW, popGet (aop, offset));
3947   }
3948 }
3949
3950 /* genCmp performs a left < right comparison, stores
3951  * the outcome in result (if != NULL) and generates
3952  * control flow code for the ifx (if != NULL).
3953  *
3954  * This version leaves in sequences like
3955  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3956  * which should be optmized by the peephole
3957  * optimizer - RN 2005-01-01 */
3958 static void genCmp (operand *left,operand *right,
3959                     operand *result, iCode *ifx, int sign)
3960 {
3961   resolvedIfx rIfx;
3962   int size;
3963   int offs;
3964   symbol *templbl;
3965   operand *dummy;
3966   unsigned long lit;
3967   unsigned long mask;
3968   int performedLt;
3969   int invert_result = 0;
3970
3971   FENTRY;
3972   
3973   assert (AOP_SIZE(left) == AOP_SIZE(right));
3974   assert (left && right);
3975
3976   size = AOP_SIZE(right) - 1;
3977   mask = (0x100UL << (size*8)) - 1;
3978   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3979   performedLt = 1;
3980   templbl = NULL;
3981   lit = 0;
3982   
3983   resolveIfx (&rIfx, ifx);
3984
3985   /**********************************************************************
3986    * handle bits - bit compares are promoted to int compares seemingly! *
3987    **********************************************************************/
3988 #if 0
3989   // THIS IS COMPLETELY UNTESTED!
3990   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3991     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3992     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3993     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3994
3995     emitSETC;
3996     // 1 < {0,1} is false --> clear C by skipping the next instruction
3997     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3998     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3999     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4000     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4001     emitCLRC; // only skipped for left=0 && right=1
4002
4003     goto correct_result_in_carry;
4004   } // if
4005 #endif
4006
4007   /*************************************************
4008    * make sure that left is register (or the like) *
4009    *************************************************/
4010   if (!isAOP_REGlike(left)) {
4011     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4012     assert (isAOP_LIT(left));
4013     assert (isAOP_REGlike(right));
4014     // swap left and right
4015     // left < right <==> right > left <==> (right >= left + 1)
4016     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4017
4018     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4019       // MAXVALUE < right? always false
4020       if (performedLt) emitCLRC; else emitSETC;
4021       goto correct_result_in_carry;
4022     } // if
4023
4024     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4025     // that's why we handled it above.
4026     lit++;
4027
4028     dummy = left;
4029     left = right;
4030     right = dummy;
4031
4032     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4033   } else if (isAOP_LIT(right)) {
4034     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4035   } // if
4036
4037   assert (isAOP_REGlike(left)); // left must be register or the like
4038   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4039
4040   /*************************************************
4041    * special cases go here                         *
4042    *************************************************/
4043
4044   if (isAOP_LIT(right)) {
4045     if (!sign) {
4046       // unsigned comparison to a literal
4047       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4048       if (lit == 0) {
4049         // unsigned left < 0? always false
4050         if (performedLt) emitCLRC; else emitSETC;
4051         goto correct_result_in_carry;
4052       }
4053     } else {
4054       // signed comparison to a literal
4055       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4056       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4057         // signed left < 0x80000000? always false
4058         if (performedLt) emitCLRC; else emitSETC;
4059         goto correct_result_in_carry;
4060       } else if (lit == 0) {
4061         // compare left < 0; set CARRY if SIGNBIT(left) is set
4062         if (performedLt) emitSETC; else emitCLRC;
4063         emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
4064         if (performedLt) emitCLRC; else emitSETC;
4065         goto correct_result_in_carry;
4066       }
4067     } // if (!sign)
4068   } // right is literal
4069
4070   /*************************************************
4071    * perform a general case comparison             *
4072    * make sure we get CARRY==1 <==> left >= right  *
4073    *************************************************/
4074   // compare most significant bytes
4075   //DEBUGpc ("comparing bytes at offset %d", size);
4076   if (!sign) {
4077     // unsigned comparison
4078     pic14_mov2w_regOrLit (AOP(right), lit, size);
4079     emitpcode (POC_SUBFW, popGet (AOP(left), size));
4080   } else {
4081     // signed comparison
4082     // (add 2^n to both operands then perform an unsigned comparison)
4083     if (isAOP_LIT(right)) {
4084       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4085       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4086
4087       if (litbyte == 0x80) {
4088         // left >= 0x80 -- always true, but more bytes to come
4089         mov2w (AOP(left), size);
4090         emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
4091         emitSETC;
4092       } else {
4093         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4094         mov2w (AOP(left), size);
4095         emitpcode (POC_ADDLW, popGetLit (0x80));
4096         emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4097       } // if
4098     } else {
4099       pCodeOp *pctemp = popGetTempReg();
4100       mov2w (AOP(left), size);
4101       emitpcode (POC_ADDLW, popGetLit (0x80));
4102       emitpcode (POC_MOVWF, pctemp);
4103       mov2w (AOP(right), size);
4104       emitpcode (POC_ADDLW, popGetLit (0x80));
4105       emitpcode (POC_SUBFW, pctemp);
4106       popReleaseTempReg(pctemp);
4107     }
4108   } // if (!sign)
4109
4110   // compare remaining bytes (treat as unsigned case from above)
4111   templbl = newiTempLabel ( NULL );
4112   offs = size;
4113   while (offs--) {
4114     //DEBUGpc ("comparing bytes at offset %d", offs);
4115     emitSKPZ;
4116     emitpcode (POC_GOTO, popGetLabel (templbl->key));
4117     pic14_mov2w_regOrLit (AOP(right), lit, offs);
4118     emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4119   } // while (offs)
4120   emitpLabel (templbl->key);
4121   goto result_in_carry;
4122
4123 result_in_carry:
4124   
4125   /****************************************************
4126    * now CARRY contains the result of the comparison: *
4127    * SUBWF sets CARRY iff                             *
4128    * F-W >= 0 <==> F >= W <==> !(F < W)               *
4129    * (F=left, W=right)                                *
4130    ****************************************************/
4131
4132   if (performedLt) {
4133     invert_result = 1;
4134     // value will be used in the following genSkipc()
4135     rIfx.condition ^= 1;
4136   } // if
4137
4138 correct_result_in_carry:
4139
4140   // assign result to variable (if neccessary)
4141   if (result && AOP_TYPE(result) != AOP_CRY) {
4142     //DEBUGpc ("assign result");
4143     size = AOP_SIZE(result);
4144     while (size--) {
4145       emitpcode (POC_CLRF, popGet (AOP(result), size));
4146     } // while
4147     if (invert_result) {
4148       emitSKPC;
4149       emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4150     } else {
4151       emitpcode (POC_RLF, popGet (AOP(result), 0));
4152     }
4153   } // if (result)
4154
4155   // perform conditional jump
4156   if (ifx) {
4157     //DEBUGpc ("generate control flow");
4158     genSkipc (&rIfx);
4159     ifx->generated = 1;
4160   } // if
4161 }
4162
4163
4164 #if 0
4165 /* OLD VERSION -- BUGGY, DO NOT USE */
4166
4167 /*-----------------------------------------------------------------*/
4168 /* genCmp :- greater or less than comparison                       */
4169 /*-----------------------------------------------------------------*/
4170 static void genCmp (operand *left,operand *right,
4171                                         operand *result, iCode *ifx, int sign)
4172 {
4173         int size; //, offset = 0 ;
4174         unsigned long lit = 0L,i = 0;
4175         resolvedIfx rFalseIfx;
4176         //  resolvedIfx rTrueIfx;
4177         symbol *truelbl;
4178
4179         FENTRY;
4180         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4181         /*
4182         if(ifx) {
4183         DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4184         DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4185         }
4186         */
4187         
4188         resolveIfx(&rFalseIfx,ifx);
4189         truelbl  = newiTempLabel(NULL);
4190         size = max(AOP_SIZE(left),AOP_SIZE(right));
4191         
4192         DEBUGpic14_AopType(__LINE__,left,right,result);
4193         
4194 #define _swapp
4195         
4196         /* if literal is on the right then swap with left */
4197         if ((AOP_TYPE(right) == AOP_LIT)) {
4198                 operand *tmp = right ;
4199                 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4200                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4201 #ifdef _swapp
4202                 
4203                 lit = (lit - 1) & mask;
4204                 right = left;
4205                 left = tmp;
4206                 rFalseIfx.condition ^= 1;
4207 #endif
4208                 
4209         } else if ((AOP_TYPE(left) == AOP_LIT)) {
4210                 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4211         }
4212         
4213         
4214         //if(IC_TRUE(ifx) == NULL)
4215         /* if left & right are bit variables */
4216         if (AOP_TYPE(left) == AOP_CRY &&
4217                 AOP_TYPE(right) == AOP_CRY ) {
4218                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4219                 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4220         } else {
4221         /* subtract right from left if at the
4222         end the carry flag is set then we know that
4223                 left is greater than right */
4224                 
4225                 symbol *lbl  = newiTempLabel(NULL);
4226                 
4227 #ifndef _swapp
4228                 if(AOP_TYPE(right) == AOP_LIT) {
4229                         
4230                         //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4231                         
4232                         DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4233                         
4234                         /* special cases */
4235                         
4236                         if(lit == 0) {
4237                                 
4238                                 if(sign != 0) 
4239                                         genSkipCond(&rFalseIfx,left,size-1,7);
4240                                 else 
4241                                         /* no need to compare to 0...*/
4242                                         /* NOTE: this is a de-generate compare that most certainly 
4243                                         *       creates some dead code. */
4244                                         emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4245                                 
4246                                 if(ifx) ifx->generated = 1;
4247                                 return;
4248                                 
4249                         }
4250                         size--;
4251                         
4252                         if(size == 0) {
4253                                 //i = (lit >> (size*8)) & 0xff;
4254                                 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4255                                 
4256                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4257                                 
4258                                 i = ((0-lit) & 0xff);
4259                                 if(sign) {
4260                                         if( i == 0x81) { 
4261                                         /* lit is 0x7f, all signed chars are less than
4262                                                 * this except for 0x7f itself */
4263                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4264                                                 genSkipz2(&rFalseIfx,0);
4265                                         } else {
4266                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4267                                                 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4268                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4269                                         }
4270                                         
4271                                 } else {
4272                                         if(lit == 1) {
4273                                                 genSkipz2(&rFalseIfx,1);
4274                                         } else {
4275                                                 emitpcode(POC_ADDLW, popGetLit(i));
4276                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4277                                         }
4278                                 }
4279                                 
4280                                 if(ifx) ifx->generated = 1;
4281                                 return;
4282                         }
4283                         
4284                         /* chars are out of the way. now do ints and longs */
4285                         
4286                         
4287                         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4288                         
4289                         /* special cases */
4290                         
4291                         if(sign) {
4292                                 
4293                                 if(lit == 0) {
4294                                         genSkipCond(&rFalseIfx,left,size,7);
4295                                         if(ifx) ifx->generated = 1;
4296                                         return;
4297                                 }
4298                                 
4299                                 if(lit <0x100) {
4300                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4301                                         
4302                                         //rFalseIfx.condition ^= 1;
4303                                         //genSkipCond(&rFalseIfx,left,size,7);
4304                                         //rFalseIfx.condition ^= 1;
4305                                         
4306                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4307                                         if(rFalseIfx.condition)
4308                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4309                                         else
4310                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4311                                         
4312                                         emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4313                                         emitpcode(POC_ADDFW, popGet(AOP(left),0));
4314                                         emitpcode(POC_MOVFW, popGet(AOP(left),1));
4315                                         
4316                                         while(size > 1)
4317                                                 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4318                                         
4319                                         if(rFalseIfx.condition) {
4320                                                 emitSKPZ;
4321                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4322                                                 
4323                                         } else {
4324                                                 emitSKPNZ;
4325                                         }
4326                                         
4327                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4328                                         emitpLabel(truelbl->key);
4329                                         if(ifx) ifx->generated = 1;
4330                                         return;
4331                                         
4332                                 }
4333                                 
4334                                 if(size == 1) {
4335                                         
4336                                         if( (lit & 0xff) == 0) {
4337                                                 /* lower byte is zero */
4338                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4339                                                 i = ((lit >> 8) & 0xff) ^0x80;
4340                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4341                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4342                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4343                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4344                                                 
4345                                                 
4346                                                 if(ifx) ifx->generated = 1;
4347                                                 return;
4348                                                 
4349                                         }
4350                                 } else {
4351                                         /* Special cases for signed longs */
4352                                         if( (lit & 0xffffff) == 0) {
4353                                                 /* lower byte is zero */
4354                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4355                                                 i = ((lit >> 8*3) & 0xff) ^0x80;
4356                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4357                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4358                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4359                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4360                                                 
4361                                                 
4362                                                 if(ifx) ifx->generated = 1;
4363                                                 return;
4364                                                 
4365                                         }
4366                                         
4367                                 }
4368                                 
4369                                 
4370                                 if(lit & (0x80 << (size*8))) {
4371                                         /* lit is negative */
4372                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4373                                         
4374                                         //genSkipCond(&rFalseIfx,left,size,7);
4375                                         
4376                                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4377                                         
4378                                         if(rFalseIfx.condition)
4379                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4380                                         else
4381                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4382                                         
4383                                         
4384                                 } else {
4385                                         /* lit is positive */
4386                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4387                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4388                                         if(rFalseIfx.condition)
4389                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4390                                         else
4391                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4392                                         
4393                                 }
4394                                 
4395                                 /* There are no more special cases, so perform a general compare */
4396                                 
4397                                 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4398                                 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4399                                 
4400                                 while(size--) {
4401                                         
4402                                         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4403                                         emitSKPNZ;
4404                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4405                                 }
4406                                 //rFalseIfx.condition ^= 1;
4407                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4408                                 
4409                                 emitpLabel(truelbl->key);
4410                                 
4411                                 if(ifx) ifx->generated = 1;
4412                                 return;
4413                                 
4414                                 
4415                         }
4416
4417
4418                         /* sign is out of the way. So now do an unsigned compare */
4419                         DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4420
4421
4422                         /* General case - compare to an unsigned literal on the right.*/
4423
4424                         i = (lit >> (size*8)) & 0xff;
4425                         emitpcode(POC_MOVLW, popGetLit(i));
4426                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4427                         while(size--) {
4428                                 i = (lit >> (size*8)) & 0xff;
4429                                 
4430                                 if(i) {
4431                                         emitpcode(POC_MOVLW, popGetLit(i));
4432                                         emitSKPNZ;
4433                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4434                                 } else {
4435                                 /* this byte of the lit is zero, 
4436                                         *if it's not the last then OR in the variable */
4437                                         if(size)
4438                                                 emitpcode(POC_IORFW, popGet(AOP(left),size));
4439                                 }
4440                         }
4441
4442
4443                 emitpLabel(lbl->key);
4444                 //if(emitFinalCheck)
4445                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4446                 if(sign)
4447                         emitpLabel(truelbl->key);
4448
4449                 if(ifx) ifx->generated = 1;
4450                 return;
4451
4452
4453                 }
4454 #endif  // _swapp
4455
4456                 if(AOP_TYPE(left) == AOP_LIT) {
4457                         //symbol *lbl = newiTempLabel(NULL);
4458                         
4459                         //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4460                         
4461                         
4462                         DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4463                         
4464                         /* Special cases */
4465                         if((lit == 0) && (sign == 0)){
4466                                 
4467                                 size--;
4468                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4469                                 while(size) 
4470                                         emitpcode(POC_IORFW, popGet(AOP(right),--size));
4471                                 
4472                                 genSkipz2(&rFalseIfx,0);
4473                                 if(ifx) ifx->generated = 1;
4474                                 return;
4475                         }
4476                         
4477                         if(size==1) {
4478                                 /* Special cases */
4479                                 lit &= 0xff;
4480                                 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4481                                         /* degenerate compare can never be true */
4482                                         if(rFalseIfx.condition == 0)
4483                                                 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4484                                         
4485                                         if(ifx) ifx->generated = 1;
4486                                         return;
4487                                 }
4488                                 
4489                                 if(sign) {
4490                                         /* signed comparisons to a literal byte */
4491                                         
4492                                         int lp1 = (lit+1) & 0xff;
4493                                         
4494                                         DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4495                                         switch (lp1) {
4496                                         case 0:
4497                                                 rFalseIfx.condition ^= 1;
4498                                                 genSkipCond(&rFalseIfx,right,0,7);
4499                                                 break;
4500                                         case 0x7f:
4501                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4502                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4503                                                 genSkipz2(&rFalseIfx,1);
4504                                                 break;
4505                                         default:
4506                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4507                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4508                                                 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4509                                                 rFalseIfx.condition ^= 1;
4510                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4511                                                 break;
4512                                         }
4513                                         if(ifx) ifx->generated = 1;
4514                                 } else {
4515                                         /* unsigned comparisons to a literal byte */
4516                                         
4517                                         switch(lit & 0xff ) {
4518                                         case 0:
4519                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4520                                                 genSkipz2(&rFalseIfx,0);
4521                                                 if(ifx) ifx->generated = 1;
4522                                                 break;
4523                                         case 0x7f:
4524                                                 genSkipCond(&rFalseIfx,right,0,7);
4525                                                 if(ifx) ifx->generated = 1;
4526                                                 break;
4527                                                 
4528                                         default:
4529                                                 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4530                                                 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4531                                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4532                                                 rFalseIfx.condition ^= 1;
4533                                                 if (AOP_TYPE(result) == AOP_CRY) {
4534                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4535                                                         if(ifx) ifx->generated = 1;
4536                                                 } else {
4537                                                         DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4538                                                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4539                                                         emitpcode(POC_RLF, popGet(AOP(result),0));
4540                                                         emitpcode(POC_MOVLW, popGetLit(0x01));
4541                                                         emitpcode(POC_XORWF, popGet(AOP(result),0));
4542                                                 }       
4543                                                 break;
4544                                         }
4545                                 }
4546                                 
4547                                 //goto check_carry;
4548                                 return;
4549                                 
4550                         } else {
4551                                 
4552                                 /* Size is greater than 1 */
4553                                 
4554                                 if(sign) {
4555                                         int lp1 = lit+1;
4556                                         
4557                                         size--;
4558                                         
4559                                         if(lp1 == 0) {
4560                                                 /* this means lit = 0xffffffff, or -1 */
4561                                                 
4562                                                 
4563                                                 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4564                                                 rFalseIfx.condition ^= 1;
4565                                                 genSkipCond(&rFalseIfx,right,size,7);
4566                                                 if(ifx) ifx->generated = 1;
4567                                                 return;
4568                                         }
4569                                         
4570                                         if(lit == 0) {
4571                                                 int s = size;
4572                                                 
4573                                                 if(rFalseIfx.condition) {
4574                                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4575                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4576                                                 }
4577                                                 
4578                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4579                                                 while(size--)
4580                                                         emitpcode(POC_IORFW, popGet(AOP(right),size));
4581                                                 
4582                                                 
4583                                                 emitSKPZ;
4584                                                 if(rFalseIfx.condition) {
4585                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4586                                                         emitpLabel(truelbl->key);
4587                                                 }else {
4588                                                         rFalseIfx.condition ^= 1;
4589                                                         genSkipCond(&rFalseIfx,right,s,7);
4590                                                 }
4591                                                 
4592                                                 if(ifx) ifx->generated = 1;
4593                                                 return;
4594                                         }
4595                                         
4596                                         if((size == 1) &&  (0 == (lp1&0xff))) {
4597                                                 /* lower byte of signed word is zero */
4598                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4599                                                 i = ((lp1 >> 8) & 0xff) ^0x80;
4600                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4601                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4602                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4603                                                 rFalseIfx.condition ^= 1;
4604                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4605                                                 
4606                                                 
4607                                                 if(ifx) ifx->generated = 1;
4608                                                 return;
4609                                         }
4610                                         
4611                                         if(lit & (0x80 << (size*8))) {
4612                                                 /* Lit is less than zero */
4613                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4614                                                 //rFalseIfx.condition ^= 1;
4615                                                 //genSkipCond(&rFalseIfx,left,size,7);
4616                                                 //rFalseIfx.condition ^= 1;
4617                                                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4618                                                 //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4619                                                 
4620                                                 if(rFalseIfx.condition)
4621                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4622                                                 else
4623                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4624                                                 
4625                                                 
4626                                         } else {
4627                                                 /* Lit is greater than or equal to zero */
4628                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4629                                                 //rFalseIfx.condition ^= 1;
4630                                                 //genSkipCond(&rFalseIfx,right,size,7);
4631                                                 //rFalseIfx.condition ^= 1;
4632                                                 
4633                                                 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4634                                                 //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4635                                                 
4636                                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4637                                                 if(rFalseIfx.condition)
4638                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4639                                                 else
4640                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4641                                                 
4642                                         }
4643                                         
4644                                         
4645                                         emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4646                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4647                                         
4648                                         while(size--) {
4649                                                 
4650                                                 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4651                                                 emitSKPNZ;
4652                                                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4653                                         }
4654                                         rFalseIfx.condition ^= 1;
4655                                         //rFalseIfx.condition = 1;
4656                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4657                                         
4658                                         emitpLabel(truelbl->key);
4659                                         
4660                                         if(ifx) ifx->generated = 1;
4661                                         return;
4662                                         // end of if (sign)
4663                                 } else {
4664                                         
4665                                         /* compare word or long to an unsigned literal on the right.*/
4666                                         
4667                                         
4668                                         size--;
4669                                         if(lit < 0xff) {
4670                                                 DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4671                                                 switch (lit) {
4672                                                 case 0:
4673                                                         break; /* handled above */
4674                                                 /*
4675                                                 case 0xff:
4676                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4677                                                         while(size--)
4678                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4679                                                         genSkipz2(&rFalseIfx,0);
4680                                                         break;
4681                                                 */
4682                                                 default:
4683                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4684                                                         while(--size)
4685                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4686                                                         
4687                                                         emitSKPZ;
4688                                                         if(rFalseIfx.condition)
4689                                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4690                                                         else
4691                                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4692                                                         
4693                                                         
4694                                                         emitpcode(POC_MOVLW, popGetLit(lit+1));
4695                                                         emitpcode(POC_SUBFW, popGet(AOP(right),0));
4696                                                         
4697                                                         rFalseIfx.condition ^= 1;
4698                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4699                                                 }
4700                                                 
4701                                                 emitpLabel(truelbl->key);
4702                                                 
4703                                                 if(ifx) ifx->generated = 1;
4704                                                 return;
4705                                         }
4706                                         
4707                                         
4708                                         lit++;
4709                                         DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4710                                         i = (lit >> (size*8)) & 0xff;
4711                                         
4712                                         emitpcode(POC_MOVLW, popGetLit(i));
4713                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4714                                         
4715                                         while(size--) {
4716                                                 i = (lit >> (size*8)) & 0xff;
4717                                                 
4718                                                 if(i) {
4719                                                         emitpcode(POC_MOVLW, popGetLit(i));
4720                                                         emitSKPNZ;
4721                                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4722                                                 } else {
4723                                                 /* this byte of the lit is zero, 
4724                                                         *if it's not the last then OR in the variable */
4725                                                         if(size)
4726                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4727                                                 }
4728                                         }
4729                                         
4730                                         
4731                                         emitpLabel(lbl->key);
4732                                         
4733                                         rFalseIfx.condition ^= 1;
4734                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4735                                 }
4736                                 
4737                                 if(sign)
4738                                         emitpLabel(truelbl->key);
4739                                 if(ifx) ifx->generated = 1;
4740                                 return;
4741                         }
4742                 }
4743                 /* Compare two variables */
4744                 
4745                 DEBUGpic14_emitcode(";sign","%d",sign);
4746                 
4747                 size--;
4748                 if(sign) {
4749                         /* Sigh. thus sucks... */
4750                         if(size) {
4751                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4752                                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4753                                 emitpcode(POC_MOVLW, popGetLit(0x80));
4754                                 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4755                                 emitpcode(POC_XORFW, popGet(AOP(right),size));
4756                                 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4757                         } else {
4758                                 /* Signed char comparison */
4759                                 /* Special thanks to Nikolai Golovchenko for this snippet */
4760                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4761                                 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4762                                 emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4763                                 emitpcode(POC_XORFW, popGet(AOP(left),0));
4764                                 emitpcode(POC_XORFW, popGet(AOP(right),0));
4765                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4766                                 
4767                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4768                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4769                                 
4770                                 if(ifx) ifx->generated = 1;
4771                                 return;
4772                         }
4773                         
4774                 } else {
4775                         
4776                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4777                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4778                 }
4779                 
4780                 
4781                 /* The rest of the bytes of a multi-byte compare */
4782                 while (size) {
4783                         
4784                         emitSKPZ;
4785                         emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4786                         size--;
4787                         
4788                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4789                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4790                         
4791                         
4792                 }
4793                 
4794                 emitpLabel(lbl->key);
4795                 
4796                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4797                 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4798                         (AOP_TYPE(result) == AOP_REG)) {
4799                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4800                         emitpcode(POC_RLF, popGet(AOP(result),0));
4801                 } else {
4802                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4803                 }       
4804                 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4805                 if(ifx) ifx->generated = 1;
4806                 
4807                 return;
4808                 
4809         }
4810         
4811         // check_carry:
4812         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4813                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4814                 pic14_outBitC(result);
4815         } else {
4816                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4817                 /* if the result is used in the next
4818                 ifx conditional branch then generate
4819                 code a little differently */
4820                 if (ifx )
4821                         genIfxJump (ifx,"c");
4822                 else
4823                         pic14_outBitC(result);
4824                 /* leave the result in acc */
4825         }
4826         
4827 }
4828 #endif
4829
4830 /*-----------------------------------------------------------------*/
4831 /* genCmpGt :- greater than comparison                             */
4832 /*-----------------------------------------------------------------*/
4833 static void genCmpGt (iCode *ic, iCode *ifx)
4834 {
4835         operand *left, *right, *result;
4836         sym_link *letype , *retype;
4837         int sign ;
4838         
4839         FENTRY;
4840         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4841         left = IC_LEFT(ic);
4842         right= IC_RIGHT(ic);
4843         result = IC_RESULT(ic);
4844         
4845         letype = getSpec(operandType(left));
4846         retype =getSpec(operandType(right));
4847         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4848         /* assign the amsops */
4849         aopOp (left,ic,FALSE);
4850         aopOp (right,ic,FALSE);
4851         aopOp (result,ic,TRUE);
4852         
4853         genCmp(right, left, result, ifx, sign);
4854         
4855         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4856         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4857         freeAsmop(result,NULL,ic,TRUE); 
4858 }
4859
4860 /*-----------------------------------------------------------------*/
4861 /* genCmpLt - less than comparisons                                */
4862 /*-----------------------------------------------------------------*/
4863 static void genCmpLt (iCode *ic, iCode *ifx)
4864 {
4865         operand *left, *right, *result;
4866         sym_link *letype , *retype;
4867         int sign ;
4868         
4869         FENTRY;
4870         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4871         left = IC_LEFT(ic);
4872         right= IC_RIGHT(ic);
4873         result = IC_RESULT(ic);
4874         
4875         letype = getSpec(operandType(left));
4876         retype =getSpec(operandType(right));
4877         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4878         
4879         /* assign the amsops */
4880         aopOp (left,ic,FALSE);
4881         aopOp (right,ic,FALSE);
4882         aopOp (result,ic,TRUE);
4883         
4884         genCmp(left, right, result, ifx, sign);
4885         
4886         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4887         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4888         freeAsmop(result,NULL,ic,TRUE); 
4889 }
4890
4891 #if 0
4892 /*-----------------------------------------------------------------*/
4893 /* genc16bit2lit - compare a 16 bit value to a literal             */
4894 /*-----------------------------------------------------------------*/
4895 static void genc16bit2lit(operand *op, int lit, int offset)
4896 {
4897         int i;
4898         
4899         FENTRY;
4900         DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4901         if( (lit&0xff) == 0) 
4902                 i=1;
4903         else
4904                 i=0;
4905         
4906         switch( BYTEofLONG(lit,i)) { 
4907         case 0:
4908                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4909                 break;
4910         case 1:
4911                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4912                 break;
4913         case 0xff:
4914                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4915                 break;
4916         default:
4917                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4918                 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4919         }
4920         
4921         i ^= 1;
4922         
4923         switch( BYTEofLONG(lit,i)) { 
4924         case 0:
4925                 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4926                 break;
4927         case 1:
4928                 emitSKPNZ;
4929                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4930                 break;
4931         case 0xff:
4932                 emitSKPNZ;
4933                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4934                 break;
4935         default:
4936                 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4937                 emitSKPNZ;
4938                 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4939                 
4940         }
4941         
4942 }
4943 #endif
4944
4945 #if 0
4946 /*-----------------------------------------------------------------*/
4947 /* gencjneshort - compare and jump if not equal                    */
4948 /*-----------------------------------------------------------------*/
4949 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4950 {
4951         int size = min(AOP_SIZE(left),AOP_SIZE(right));
4952         int offset = 0;
4953         //resolvedIfx rIfx;
4954         symbol *lbl;
4955         
4956         //unsigned long lit = 0L;
4957         FENTRY;
4958         if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4959           emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4960           return;
4961         }
4962         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4963         DEBUGpic14_AopType(__LINE__,left,right,result);
4964         
4965         assert (!pic14_sameRegs (AOP(left), AOP(result)));
4966         assert (!pic14_sameRegs (AOP(right), AOP(result)));
4967         if (AOP_SIZE(result)) {
4968           for (offset = 0; offset < AOP_SIZE(result); offset++)
4969             emitpcode (POC_CLRF, popGet (AOP(result), offset));
4970         }
4971         
4972         assert (AOP_SIZE(left) == AOP_SIZE(right));
4973         //resolveIfx(&rIfx,ifx);
4974         lbl = newiTempLabel (NULL);
4975         while (size--)
4976         {
4977           mov2w (AOP(right),size);
4978           emitpcode (POC_XORFW, popGet (AOP(left), size));
4979           if (size)
4980           {
4981             emitSKPZ;
4982             emitpcode (POC_GOTO, popGetLabel (lbl->key));
4983           }
4984         } // while
4985         emitpLabel (lbl->key);
4986         if (AOP_SIZE(result)) {
4987           emitSKPNZ;
4988           emitpcode (POC_INCF, popGet (AOP(result), 0));
4989         } else {
4990           assert (ifx);
4991           genSkipz (ifx, NULL != IC_TRUE(ifx));
4992           ifx->generated = 1;
4993         }
4994         return;
4995 #if 0   
4996         if(result)
4997         {
4998                 DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4999                 assert (!pic14_sameRegs (AOP(result), AOP(left)));
5000                 assert (!pic14_sameRegs (AOP(result), AOP(right)));
5001                 for (offset=0; offset < AOP_SIZE(result); offset++)
5002                 {
5003                         emitpcode (POC_CLRF, popGet (AOP(result), offset));
5004                 } // for offset
5005         }
5006         
5007         
5008         /* if the left side is a literal or 
5009         if the right is in a pointer register and left 
5010         is not */
5011         if ((AOP_TYPE(left) == AOP_LIT) || 
5012                 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5013                 operand *t = right;
5014                 right = left;
5015                 left = t;
5016         }
5017         if(AOP_TYPE(right) == AOP_LIT)
5018                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5019         
5020         /* if the right side is a literal then anything goes */
5021         if (AOP_TYPE(right) == AOP_LIT &&
5022                 AOP_TYPE(left) != AOP_DIR ) {
5023                 switch(size) {
5024                 case 2:
5025                         genc16bit2lit(left, lit, 0);
5026                         emitSKPNZ;
5027                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
5028                         break;
5029                 default:
5030                         offset = 0;
5031                         while (size--) {
5032                                 if(lit & 0xff) {
5033                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5034                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5035                                 } else {
5036                                         emitpcode(POC_MOVF,popGet(AOP(left),offset));
5037                                 }
5038                                 
5039                                 emitSKPNZ;
5040                                 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5041                                 offset++;
5042                                 lit >>= 8;
5043                         }
5044                         break;
5045                 }
5046         }
5047         
5048         /* if the right side is in a register or in direct space or
5049         if the left is a pointer register & right is not */    
5050         else if (AOP_TYPE(right) == AOP_REG ||
5051                 AOP_TYPE(right) == AOP_DIR || 
5052                 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5053                 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5054                 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5055                 int lbl_key = lbl->key;
5056                 
5057                 if(!result) {
5058                         DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5059                         fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5060                                 __FUNCTION__,__LINE__);
5061                         return;
5062                 }
5063                 
5064                 /*     switch(size) { */
5065                 /*     case 2: */
5066                 /*       genc16bit2lit(left, lit, 0); */
5067                 /*       emitSKPNZ; */
5068                 /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
5069                 /*       break; */
5070                 /*     default: */
5071                 offset = 0;
5072                 while (size--) {
5073                         int emit_skip=1;
5074                         if((AOP_TYPE(left) == AOP_DIR) && 
5075                                 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5076                                 
5077                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5078                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5079                                 
5080                         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5081                                 
5082                                 switch (lit & 0xff) {
5083                                 case 0:
5084                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5085                                         break;
5086                                 case 1:
5087                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5088                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5089                                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
5090                                         emit_skip=0;
5091                                         break;
5092                                 case 0xff:
5093                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5094                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5095                                         //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5096                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5097                                         emit_skip=0;
5098                                         break;
5099                                 default:
5100                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5101                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5102                                 }
5103                                 lit >>= 8;
5104                                 
5105                         } else {
5106                                 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5107                         }
5108                         if(emit_skip) {
5109                                 if(AOP_TYPE(result) == AOP_CRY) {
5110                                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5111                                         if(rIfx.condition)
5112                                                 emitSKPNZ;
5113                                         else
5114                                                 emitSKPZ;
5115                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5116                                 } else {
5117                                         /* fix me. probably need to check result size too */
5118                                         //emitpcode(POC_CLRF,popGet(AOP(result),0));
5119                                         if(rIfx.condition)
5120                                                 emitSKPZ;
5121                                         else
5122                                                 emitSKPNZ;
5123                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5124                                 }
5125                                 if(ifx)
5126                                         ifx->generated=1;
5127                         }
5128                         emit_skip++;
5129                         offset++;
5130                 }
5131                 /*       break; */
5132                 /*     } */
5133         } else if(AOP_TYPE(right) == AOP_REG &&
5134                 AOP_TYPE(left) != AOP_DIR){
5135
5136                 offset = 0;
5137                 while(size--) {
5138                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5139                         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5140                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5141                         if(rIfx.condition)
5142                                 emitSKPNZ;
5143                         else
5144                                 emitSKPZ;
5145                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5146                         offset++;
5147                 }
5148                 
5149         }else{
5150                 /* right is a pointer reg need both a & b */
5151                 offset = 0;
5152                 while(size--) {
5153                         char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5154                         if(strcmp(l,"b"))
5155                                 pic14_emitcode("mov","b,%s",l);
5156                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5157                         pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5158                         offset++;
5159                 }
5160         }
5161         
5162         emitpcode(POC_INCF,popGet(AOP(result),0));
5163         if(!rIfx.condition)
5164                 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5165         
5166         emitpLabel(lbl->key);
5167         
5168         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5169         
5170         if(ifx)
5171                 ifx->generated = 1;
5172 #endif
5173 }
5174 #endif
5175
5176 #if 0
5177 /*-----------------------------------------------------------------*/
5178 /* gencjne - compare and jump if not equal                         */
5179 /*-----------------------------------------------------------------*/
5180 static void gencjne(operand *left, operand *right, iCode *ifx)
5181 {
5182         symbol *tlbl  = newiTempLabel(NULL);
5183         
5184         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5185         gencjneshort(left, right, lbl);
5186         
5187         pic14_emitcode("mov","a,%s",one);
5188         pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5189         pic14_emitcode("","%05d_DS_:",lbl->key+100);
5190         pic14_emitcode("clr","a");
5191         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5192         
5193         emitpLabel(lbl->key);
5194         emitpLabel(tlbl->key);
5195         
5196 }
5197 #endif
5198
5199 /*-----------------------------------------------------------------*/
5200 /* genCmpEq - generates code for equal to                          */
5201 /*-----------------------------------------------------------------*/
5202 static void genCmpEq (iCode *ic, iCode *ifx)
5203 {
5204   operand *left, *right, *result;
5205   int size;
5206   symbol *false_label;
5207
5208   FENTRY;
5209   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5210
5211   if(ifx)
5212     DEBUGpic14_emitcode ("; ifx is non-null","");
5213   else
5214     DEBUGpic14_emitcode ("; ifx is null","");
5215
5216   aopOp((left=IC_LEFT(ic)),ic,FALSE);
5217   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5218   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5219
5220   DEBUGpic14_AopType(__LINE__,left,right,result);
5221
5222   /* if literal, move literal to right */ 
5223   if (op_isLitLike (IC_LEFT(ic))) {
5224     operand *tmp = right ;
5225     right = left;
5226     left = tmp;
5227   }
5228
5229   false_label = NULL;
5230   if (ifx && !IC_TRUE(ifx))
5231   {
5232     assert (IC_FALSE(ifx));
5233     false_label = IC_FALSE(ifx);
5234   }
5235
5236   size = min(AOP_SIZE(left),AOP_SIZE(right));
5237   assert(!pic14_sameRegs(AOP(result),AOP(left)));
5238   assert(!pic14_sameRegs(AOP(result),AOP(right)));
5239
5240   /* assume left != right */
5241   {
5242     int i;
5243     for (i=0; i < AOP_SIZE(result); i++)
5244     {
5245       emitpcode(POC_CLRF, popGet(AOP(result),i));
5246     }
5247   }
5248
5249   if (AOP_TYPE(right) == AOP_LIT)
5250   {
5251     unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5252     int i;
5253     size = AOP_SIZE(left);
5254     assert(!op_isLitLike(left));
5255
5256     switch (lit)
5257     {
5258       case 0:
5259         mov2w(AOP(left), 0);
5260         for (i=1; i < size; i++)
5261           emitpcode(POC_IORFW,popGet(AOP(left),i));
5262         /* now Z is set iff `left == right' */
5263         emitSKPZ;
5264         if (!false_label) false_label = newiTempLabel(NULL);
5265         emitpcode(POC_GOTO, popGetLabel(false_label->key));
5266         break;
5267
5268       default:
5269         for (i=0; i < size; i++)
5270         {
5271           mov2w(AOP(left),i);
5272           emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5273           /* now Z is cleared if `left != right' */
5274           emitSKPZ;
5275           if (!false_label) false_label = newiTempLabel(NULL);
5276           emitpcode(POC_GOTO, popGetLabel(false_label->key));
5277         } // for i
5278         break;
5279     } // switch (lit)
5280   }
5281   else
5282   {
5283     /* right is no literal */
5284     int i;
5285
5286     for (i=0; i < size; i++)
5287     {
5288       mov2w(AOP(right),i);
5289       emitpcode(POC_XORFW,popGet(AOP(left),i));
5290       /* now Z is cleared if `left != right' */
5291       emitSKPZ;
5292       if (!false_label) false_label = newiTempLabel(NULL);
5293       emitpcode(POC_GOTO, popGetLabel(false_label->key));
5294     } // for i
5295   }
5296
5297   /* if we reach here, left == right */
5298
5299   if (AOP_SIZE(result) > 0)
5300   {
5301     emitpcode(POC_INCF, popGet(AOP(result),0));
5302   }
5303
5304   if (ifx && IC_TRUE(ifx))
5305   {
5306     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5307   }
5308
5309   if (false_label && (!ifx || IC_TRUE(ifx)))
5310     emitpLabel(false_label->key);
5311
5312   if (ifx) ifx->generated = 1;
5313
5314   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5315   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5316   freeAsmop(result,NULL,ic,TRUE);
5317 }
5318
5319 /*-----------------------------------------------------------------*/
5320 /* ifxForOp - returns the icode containing the ifx for operand     */
5321 /*-----------------------------------------------------------------*/
5322 static iCode *ifxForOp ( operand *op, iCode *ic )
5323 {
5324         FENTRY;
5325         /* if true symbol then needs to be assigned */
5326         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5327         if (IS_TRUE_SYMOP(op))
5328                 return NULL ;
5329         
5330         /* if this has register type condition and
5331         the next instruction is ifx with the same operand
5332         and live to of the operand is upto the ifx only then */
5333         if (ic->next &&
5334                 ic->next->op == IFX &&
5335                 IC_COND(ic->next)->key == op->key &&
5336                 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5337                 return ic->next;
5338         
5339         if (ic->next &&
5340                 ic->next->op == IFX &&
5341                 IC_COND(ic->next)->key == op->key) {
5342                 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5343                 return ic->next;
5344         }
5345         
5346         DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5347         if (ic->next &&
5348                 ic->next->op == IFX)
5349                 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5350         
5351         if (ic->next &&
5352                 ic->next->op == IFX &&
5353                 IC_COND(ic->next)->key == op->key) {
5354                 DEBUGpic14_emitcode ("; "," key is okay");
5355                 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5356                         OP_SYMBOL(op)->liveTo,
5357                         ic->next->seq);
5358         }
5359         
5360         
5361         return NULL;
5362 }
5363 /*-----------------------------------------------------------------*/
5364 /* genAndOp - for && operation                                     */
5365 /*-----------------------------------------------------------------*/
5366 static void genAndOp (iCode *ic)
5367 {
5368         operand *left,*right, *result;
5369         /*     symbol *tlbl; */
5370         
5371         FENTRY;
5372         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5373         /* note here that && operations that are in an
5374         if statement are taken away by backPatchLabels
5375         only those used in arthmetic operations remain */
5376         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5377         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5378         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5379         
5380         DEBUGpic14_AopType(__LINE__,left,right,result);
5381         
5382         emitpcode(POC_MOVFW,popGet(AOP(left),0));
5383         emitpcode(POC_ANDFW,popGet(AOP(right),0));
5384         emitpcode(POC_MOVWF,popGet(AOP(result),0));
5385         
5386         /* if both are bit variables */
5387         /*     if (AOP_TYPE(left) == AOP_CRY && */
5388         /*         AOP_TYPE(right) == AOP_CRY ) { */
5389         /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5390         /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5391         /*         pic14_outBitC(result); */
5392         /*     } else { */
5393         /*         tlbl = newiTempLabel(NULL); */
5394         /*         pic14_toBoolean(left);     */
5395         /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5396         /*         pic14_toBoolean(right); */
5397         /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5398         /*         pic14_outBitAcc(result); */
5399         /*     } */
5400         
5401         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5402         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5403         freeAsmop(result,NULL,ic,TRUE);
5404 }
5405
5406
5407 /*-----------------------------------------------------------------*/
5408 /* genOrOp - for || operation                                      */
5409 /*-----------------------------------------------------------------*/
5410 /*
5411 tsd pic port -
5412 modified this code, but it doesn't appear to ever get called
5413 */
5414
5415 static void genOrOp (iCode *ic)
5416 {
5417         operand *left,*right, *result;
5418         symbol *tlbl;
5419         int i;
5420         
5421         /* note here that || operations that are in an
5422         if statement are taken away by backPatchLabels
5423         only those used in arthmetic operations remain */
5424         FENTRY;
5425         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5426         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5427         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5428         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5429         
5430         DEBUGpic14_AopType(__LINE__,left,right,result);
5431
5432         for (i=0; i < AOP_SIZE(result); i++)
5433         {
5434                 emitpcode(POC_CLRF, popGet(AOP(result), i));
5435         } // for i
5436
5437         tlbl = newiTempLabel(NULL);
5438         pic14_toBoolean(left);
5439         emitSKPZ;
5440         emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5441         pic14_toBoolean(right);
5442         emitpLabel(tlbl->key);
5443         /* here Z is clear IFF `left || right' */
5444         emitSKPZ;
5445         emitpcode(POC_INCF, popGet(AOP(result), 0));
5446         
5447         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5448         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5449         freeAsmop(result,NULL,ic,TRUE);            
5450 }
5451
5452 /*-----------------------------------------------------------------*/
5453 /* isLiteralBit - test if lit == 2^n                               */
5454 /*-----------------------------------------------------------------*/
5455 static int isLiteralBit(unsigned long lit)
5456 {
5457         unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5458                 0x100L,0x200L,0x400L,0x800L,
5459                 0x1000L,0x2000L,0x4000L,0x8000L,
5460                 0x10000L,0x20000L,0x40000L,0x80000L,
5461                 0x100000L,0x200000L,0x400000L,0x800000L,
5462                 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5463                 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5464         int idx;
5465         
5466         FENTRY;
5467         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5468         for(idx = 0; idx < 32; idx++)
5469                 if(lit == pw[idx])
5470                         return idx+1;
5471                 return 0;
5472 }
5473
5474 /*-----------------------------------------------------------------*/
5475 /* continueIfTrue -                                                */
5476 /*-----------------------------------------------------------------*/
5477 static void continueIfTrue (iCode *ic)
5478 {
5479         FENTRY;
5480         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5481         if(IC_TRUE(ic))
5482                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5483         ic->generated = 1;
5484 }
5485
5486 /*-----------------------------------------------------------------*/
5487 /* jmpIfTrue -                                                     */
5488 /*-----------------------------------------------------------------*/
5489 static void jumpIfTrue (iCode *ic)
5490 {
5491         FENTRY;
5492         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5493         if(!IC_TRUE(ic))
5494                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5495         ic->generated = 1;
5496 }
5497
5498 /*-----------------------------------------------------------------*/
5499 /* jmpTrueOrFalse -                                                */
5500 /*-----------------------------------------------------------------*/
5501 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5502 {
5503         FENTRY;
5504         // ugly but optimized by peephole
5505         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5506         if(IC_TRUE(ic)){
5507                 symbol *nlbl = newiTempLabel(NULL);
5508                 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5509                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5510                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5511                 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5512         }
5513         else{
5514                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5515                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5516         }
5517         ic->generated = 1;
5518 }
5519
5520 /*-----------------------------------------------------------------*/
5521 /* genAnd  - code for and                                          */
5522 /*-----------------------------------------------------------------*/
5523 static void genAnd (iCode *ic, iCode *ifx)
5524 {
5525         operand *left, *right, *result;
5526         int size, offset=0;  
5527         unsigned long lit = 0L;
5528         int bytelit = 0;
5529         resolvedIfx rIfx;
5530         
5531         FENTRY;
5532         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5533         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5534         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5535         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5536         
5537         resolveIfx(&rIfx,ifx);
5538         
5539         /* if left is a literal & right is not then exchange them */
5540         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5541                 AOP_NEEDSACC(left)) {
5542                 operand *tmp = right ;
5543                 right = left;
5544                 left = tmp;
5545         }
5546         
5547         /* if result = right then exchange them */
5548         if(pic14_sameRegs(AOP(result),AOP(right))){
5549                 operand *tmp = right ;
5550                 right = left;
5551                 left = tmp;
5552         }
5553         
5554         /* if right is bit then exchange them */
5555         if (AOP_TYPE(right) == AOP_CRY &&
5556                 AOP_TYPE(left) != AOP_CRY){
5557                 operand *tmp = right ;
5558                 right = left;
5559                 left = tmp;
5560         }
5561         if(AOP_TYPE(right) == AOP_LIT)
5562                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5563         
5564         size = AOP_SIZE(result);
5565         
5566         DEBUGpic14_AopType(__LINE__,left,right,result);
5567         
5568         // if(bit & yy)
5569         // result = bit & yy;
5570         if (AOP_TYPE(left) == AOP_CRY){
5571                 // c = bit & literal;
5572                 if(AOP_TYPE(right) == AOP_LIT){
5573                         if(lit & 1) {
5574                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5575                                         // no change
5576                                         goto release;
5577                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5578                         } else {
5579                                 // bit(result) = 0;
5580                                 if(size && (AOP_TYPE(result) == AOP_CRY)){
5581                                         pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5582                                         goto release;
5583                                 }
5584                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5585                                         jumpIfTrue(ifx);
5586                                         goto release;
5587                                 }
5588                                 pic14_emitcode("clr","c");
5589                         }
5590                 } else {
5591                         if (AOP_TYPE(right) == AOP_CRY){
5592                                 // c = bit & bit;
5593                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5594                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5595                         } else {
5596                                 // c = bit & val;
5597                                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5598                                 // c = lsb
5599                                 pic14_emitcode("rrc","a");
5600                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5601                         }
5602                 }
5603                 // bit = c
5604                 // val = c
5605                 if(size)
5606                         pic14_outBitC(result);
5607                 // if(bit & ...)
5608                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5609                         genIfxJump(ifx, "c");           
5610                 goto release ;
5611         }
5612         
5613         // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5614         // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5615         if((AOP_TYPE(right) == AOP_LIT) &&
5616                 (AOP_TYPE(result) == AOP_CRY) &&
5617                 (AOP_TYPE(left) != AOP_CRY)){
5618                 int posbit = isLiteralBit(lit);
5619                 /* left &  2^n */
5620                 if(posbit){
5621                         posbit--;
5622                         //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5623                         // bit = left & 2^n
5624                         if(size)
5625                                 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5626                         // if(left &  2^n)
5627                         else{
5628                                 if(ifx){
5629                                         int offset = 0;
5630                                         while (posbit > 7) {
5631                                                 posbit -= 8;
5632                                                 offset++;
5633                                         }
5634                                         emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5635                                                 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5636                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5637                                         
5638                                         ifx->generated = 1;
5639                                 }
5640                                 goto release;
5641                         }
5642                 } else {
5643                         symbol *tlbl = newiTempLabel(NULL);
5644                         int sizel = AOP_SIZE(left);
5645                         if(size)
5646                                 pic14_emitcode("setb","c");
5647                         while(sizel--){
5648                                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5649                                         MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5650                                         // byte ==  2^n ?
5651                                         if((posbit = isLiteralBit(bytelit)) != 0)
5652                                                 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5653                                         else{
5654                                                 if(bytelit != 0x0FFL)
5655                                                         pic14_emitcode("anl","a,%s",
5656                                                         aopGet(AOP(right),offset,FALSE,TRUE));
5657                                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5658                                         }
5659                                 }
5660                                 offset++;
5661                         }
5662                         // bit = left & literal
5663                         if(size){
5664                                 pic14_emitcode("clr","c");
5665                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5666                         }
5667                         // if(left & literal)
5668                         else{
5669                                 if(ifx)
5670                                         jmpTrueOrFalse(ifx, tlbl);
5671                                 goto release ;
5672                         }
5673                 }
5674                 pic14_outBitC(result);
5675                 goto release ;
5676         }
5677         
5678         /* if left is same as result */
5679         if(pic14_sameRegs(AOP(result),AOP(left))){
5680                 int know_W = -1;
5681                 for(;size--; offset++,lit>>=8) {
5682                         if(AOP_TYPE(right) == AOP_LIT){
5683                                 switch(lit & 0xff) {
5684                                 case 0x00:
5685                                         /*  and'ing with 0 has clears the result */
5686                                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
5687                                         break;
5688                                 case 0xff:
5689                                         /* and'ing with 0xff is a nop when the result and left are the same */
5690                                         break;
5691                                         
5692                                 default:
5693                                         {
5694                                                 int p = my_powof2( (~lit) & 0xff );
5695                                                 if(p>=0) {
5696                                                         /* only one bit is set in the literal, so use a bcf instruction */
5697                                                         emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5698                                                         
5699                                                 } else {
5700                                                         if(know_W != (int)(lit&0xff))
5701                                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5702                                                         know_W = lit &0xff;
5703                                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5704                                                 }
5705                                         }    
5706                                 }
5707                         } else {
5708                                 if (AOP_TYPE(left) == AOP_ACC) {
5709                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5710                                 } else {        
5711                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5712                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5713                                         
5714                                 }
5715                         }
5716                 }
5717                 
5718         } else {
5719                 // left & result in different registers
5720                 if(AOP_TYPE(result) == AOP_CRY){
5721                         // result = bit
5722                         // if(size), result in bit
5723                         // if(!size && ifx), conditional oper: if(left & right)
5724                         symbol *tlbl = newiTempLabel(NULL);
5725                         int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5726                         if(size)
5727                                 pic14_emitcode("setb","c");
5728                         while(sizer--){
5729                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5730                                 pic14_emitcode("anl","a,%s",
5731                                         aopGet(AOP(left),offset,FALSE,FALSE));
5732                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5733                                 offset++;
5734                         }
5735                         if(size){
5736                                 CLRC;
5737                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5738                                 pic14_outBitC(result);
5739                         } else if(ifx)
5740                                 jmpTrueOrFalse(ifx, tlbl);
5741                 } else {
5742                         for(;(size--);offset++) {
5743                                 // normal case
5744                                 // result = left & right
5745                                 if(AOP_TYPE(right) == AOP_LIT){
5746                                         int t = (lit >> (offset*8)) & 0x0FFL;
5747                                         switch(t) { 
5748                                         case 0x00:
5749                                                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5750                                                 break;
5751                                         case 0xff:
5752                                                 if(AOP_TYPE(left) != AOP_ACC) {
5753                                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5754                                                 }
5755                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5756                                                 break;
5757                                         default:
5758                                                 if(AOP_TYPE(left) == AOP_ACC) {
5759                                                         emitpcode(POC_ANDLW, popGetLit(t));
5760                                                 } else {
5761                                                         emitpcode(POC_MOVLW, popGetLit(t));
5762                                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5763                                                 }
5764                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5765                                         }
5766                                         continue;
5767                                 }
5768                                 
5769                                 if (AOP_TYPE(left) == AOP_ACC) {
5770                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5771                                 } else {
5772                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5773                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5774                                 }
5775                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5776                         }
5777                 }
5778         }
5779         
5780 release :
5781         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5782         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5783         freeAsmop(result,NULL,ic,TRUE);     
5784 }
5785
5786 /*-----------------------------------------------------------------*/
5787 /* genOr  - code for or                                            */
5788 /*-----------------------------------------------------------------*/
5789 static void genOr (iCode *ic, iCode *ifx)
5790 {
5791         operand *left, *right, *result;
5792         int size, offset=0;
5793         unsigned long lit = 0L;
5794         
5795         FENTRY;
5796         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5797         
5798         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5799         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5800         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5801         
5802         DEBUGpic14_AopType(__LINE__,left,right,result);
5803         
5804         /* if left is a literal & right is not then exchange them */
5805         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5806                 AOP_NEEDSACC(left)) {
5807                 operand *tmp = right ;
5808                 right = left;
5809                 left = tmp;
5810         }
5811         
5812         /* if result = right then exchange them */
5813         if(pic14_sameRegs(AOP(result),AOP(right))){
5814                 operand *tmp = right ;
5815                 right = left;
5816                 left = tmp;
5817         }
5818         
5819         /* if right is bit then exchange them */
5820         if (AOP_TYPE(right) == AOP_CRY &&
5821                 AOP_TYPE(left) != AOP_CRY){
5822                 operand *tmp = right ;
5823                 right = left;
5824                 left = tmp;
5825         }
5826         
5827         DEBUGpic14_AopType(__LINE__,left,right,result);
5828         
5829         if(AOP_TYPE(right) == AOP_LIT)
5830                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5831         
5832         size = AOP_SIZE(result);
5833         
5834         // if(bit | yy)
5835         // xx = bit | yy;
5836         if (AOP_TYPE(left) == AOP_CRY){
5837                 if(AOP_TYPE(right) == AOP_LIT){
5838                         // c = bit & literal;
5839                         if(lit){
5840                                 // lit != 0 => result = 1
5841                                 if(AOP_TYPE(result) == AOP_CRY){
5842                                         if(size)
5843                                                 emitpcode(POC_BSF, popGet(AOP(result),0));
5844                                         //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5845                                         //   AOP(result)->aopu.aop_dir,
5846                                         //   AOP(result)->aopu.aop_dir);
5847                                         else if(ifx)
5848                                                 continueIfTrue(ifx);
5849                                         goto release;
5850                                 }
5851                         } else {
5852                                 // lit == 0 => result = left
5853                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5854                                         goto release;
5855                                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5856                         }
5857                 } else {
5858                         if (AOP_TYPE(right) == AOP_CRY){
5859                                 if(pic14_sameRegs(AOP(result),AOP(left))){
5860                                         // c = bit | bit;
5861                                         emitpcode(POC_BCF,   popGet(AOP(result),0));
5862                                         emitpcode(POC_BTFSC, popGet(AOP(right),0));
5863                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5864                                         
5865                                         pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5866                                                 AOP(result)->aopu.aop_dir,
5867                                                 AOP(result)->aopu.aop_dir);
5868                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5869                                                 AOP(right)->aopu.aop_dir,
5870                                                 AOP(right)->aopu.aop_dir);
5871                                         pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5872                                                 AOP(result)->aopu.aop_dir,
5873                                                 AOP(result)->aopu.aop_dir);
5874                                 } else {
5875                                         if( AOP_TYPE(result) == AOP_ACC) {
5876                                                 emitpcode(POC_MOVLW, popGetLit(0));
5877                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5878                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5879                                                 emitpcode(POC_MOVLW, popGetLit(1));
5880                                                 
5881                                         } else {
5882                                                 
5883                                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5884                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5885                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5886                                                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5887                                                 
5888                                                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5889                                                         AOP(result)->aopu.aop_dir,
5890                                                         AOP(result)->aopu.aop_dir);
5891                                                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5892                                                         AOP(right)->aopu.aop_dir,
5893                                                         AOP(right)->aopu.aop_dir);
5894                                                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5895                                                         AOP(left)->aopu.aop_dir,
5896                                                         AOP(left)->aopu.aop_dir);
5897                                                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5898                                                         AOP(result)->aopu.aop_dir,
5899                                                         AOP(result)->aopu.aop_dir);
5900                                         }
5901                                 }
5902                         } else {
5903                                 // c = bit | val;
5904                                 symbol *tlbl = newiTempLabel(NULL);
5905                                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5906                                 
5907                                 
5908                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5909                                 if( AOP_TYPE(right) == AOP_ACC) {
5910                                         emitpcode(POC_IORLW, popGetLit(0));
5911                                         emitSKPNZ;
5912                                         emitpcode(POC_BTFSC, popGet(AOP(left),0));
5913                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5914                                 }
5915                                 
5916                                 
5917                                 
5918                                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5919                                         pic14_emitcode(";XXX setb","c");
5920                                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5921                                         AOP(left)->aopu.aop_dir,tlbl->key+100);
5922                                 pic14_toBoolean(right);
5923                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5924                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5925                                         jmpTrueOrFalse(ifx, tlbl);
5926                                         goto release;
5927                                 } else {
5928                                         CLRC;
5929                                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5930                                 }
5931                         }
5932                 }
5933                 // bit = c
5934                 // val = c
5935                 if(size)
5936                         pic14_outBitC(result);
5937                 // if(bit | ...)
5938                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5939                         genIfxJump(ifx, "c");           
5940                 goto release ;
5941         }
5942
5943         // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5944         // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5945         if((AOP_TYPE(right) == AOP_LIT) &&
5946           (AOP_TYPE(result) == AOP_CRY) &&
5947           (AOP_TYPE(left) != AOP_CRY)){
5948                 if(lit){
5949                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5950                         // result = 1
5951                         if(size)
5952                                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5953                         else 
5954                                 continueIfTrue(ifx);
5955                         goto release;
5956                 } else {
5957                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5958                         // lit = 0, result = boolean(left)
5959                         if(size)
5960                                 pic14_emitcode(";XXX setb","c");
5961                         pic14_toBoolean(right);
5962                         if(size){
5963                                 symbol *tlbl = newiTempLabel(NULL);
5964                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5965                                 CLRC;
5966                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5967                         } else {
5968                                 genIfxJump (ifx,"a");
5969                                 goto release;
5970                         }
5971                 }
5972                 pic14_outBitC(result);
5973                 goto release ;
5974         }
5975
5976         /* if left is same as result */
5977         if(pic14_sameRegs(AOP(result),AOP(left))){
5978                 int know_W = -1;
5979                 for(;size--; offset++,lit>>=8) {
5980                         if(AOP_TYPE(right) == AOP_LIT){
5981                                 if((lit & 0xff) == 0)
5982                                         /*  or'ing with 0 has no effect */
5983                                         continue;
5984                                 else {
5985                                         int p = my_powof2(lit & 0xff);
5986                                         if(p>=0) {
5987                                                 /* only one bit is set in the literal, so use a bsf instruction */
5988                                                 emitpcode(POC_BSF,
5989                                                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5990                                         } else {
5991                                                 if(know_W != (int)(lit & 0xff))
5992                                                         emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5993                                                 know_W = lit & 0xff;
5994                                                 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5995                                         }
5996                                         
5997                                 }
5998                         } else {
5999                                 if (AOP_TYPE(left) == AOP_ACC) {
6000                                         emitpcode(POC_IORFW,  popGet(AOP(right),offset));
6001                                         pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6002                                 } else {        
6003                                         emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
6004                                         emitpcode(POC_IORWF,  popGet(AOP(left),offset));
6005                                         
6006                                         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6007                                         pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
6008                                         
6009                                 }
6010                         }
6011                 }
6012         } else {
6013                 // left & result in different registers
6014                 if(AOP_TYPE(result) == AOP_CRY){
6015                         // result = bit
6016                         // if(size), result in bit
6017                         // if(!size && ifx), conditional oper: if(left | right)
6018                         symbol *tlbl = newiTempLabel(NULL);
6019                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6020                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6021                         
6022                         
6023                         if(size)
6024                                 pic14_emitcode(";XXX setb","c");
6025                         while(sizer--){
6026                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6027                                 pic14_emitcode(";XXX orl","a,%s",
6028                                         aopGet(AOP(left),offset,FALSE,FALSE));
6029                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6030                                 offset++;
6031                         }
6032                         if(size){
6033                                 CLRC;
6034                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6035                                 pic14_outBitC(result);
6036                         } else if(ifx)
6037                                 jmpTrueOrFalse(ifx, tlbl);
6038                 } else for(;(size--);offset++){
6039                         // normal case
6040                         // result = left | right
6041                         if(AOP_TYPE(right) == AOP_LIT){
6042                                 int t = (lit >> (offset*8)) & 0x0FFL;
6043                                 switch(t) { 
6044                                 case 0x00:
6045                                         if (AOP_TYPE(left) != AOP_ACC) {
6046                                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
6047                                         }
6048                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6049                                         
6050                                         break;
6051                                 default:
6052                                         if (AOP_TYPE(left) == AOP_ACC) {
6053                                                 emitpcode(POC_IORLW,  popGetLit(t));
6054                                         } else {
6055                                                 emitpcode(POC_MOVLW,  popGetLit(t));
6056                                                 emitpcode(POC_IORFW,  popGet(AOP(left),offset));
6057                                         }
6058                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));        
6059                                 }
6060                                 continue;
6061                         }
6062                         
6063                         // faster than result <- left, anl result,right
6064                         // and better if result is SFR
6065                         if (AOP_TYPE(left) == AOP_ACC) {
6066                                 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6067                         } else {
6068                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6069                                 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6070                         }
6071                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6072                 }
6073         }
6074
6075 release :
6076         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6077         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6078         freeAsmop(result,NULL,ic,TRUE);     
6079 }
6080
6081 /*-----------------------------------------------------------------*/
6082 /* genXor - code for xclusive or                                   */
6083 /*-----------------------------------------------------------------*/
6084 static void genXor (iCode *ic, iCode *ifx)
6085 {
6086         operand *left, *right, *result;
6087         int size, offset=0;
6088         unsigned long lit = 0L;
6089         
6090         FENTRY;
6091         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6092         
6093         aopOp((left = IC_LEFT(ic)),ic,FALSE);
6094         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6095         aopOp((result=IC_RESULT(ic)),ic,TRUE);
6096         
6097         /* if left is a literal & right is not ||
6098         if left needs acc & right does not */
6099         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6100                 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6101                 operand *tmp = right ;
6102                 right = left;
6103                 left = tmp;
6104         }
6105         
6106         /* if result = right then exchange them */
6107         if(pic14_sameRegs(AOP(result),AOP(right))){
6108                 operand *tmp = right ;
6109                 right = left;
6110                 left = tmp;
6111         }
6112         
6113         /* if right is bit then exchange them */
6114         if (AOP_TYPE(right) == AOP_CRY &&
6115                 AOP_TYPE(left) != AOP_CRY){
6116                 operand *tmp = right ;
6117                 right = left;
6118                 left = tmp;
6119         }
6120         if(AOP_TYPE(right) == AOP_LIT)
6121                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6122         
6123         size = AOP_SIZE(result);
6124         
6125         // if(bit ^ yy)
6126         // xx = bit ^ yy;
6127         if (AOP_TYPE(left) == AOP_CRY){
6128                 if(AOP_TYPE(right) == AOP_LIT){
6129                         // c = bit & literal;
6130                         if(lit>>1){
6131                                 // lit>>1  != 0 => result = 1
6132                                 if(AOP_TYPE(result) == AOP_CRY){
6133                                         if(size)
6134                                         {emitpcode(POC_BSF,  popGet(AOP(result),offset));
6135                                         pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6136                                         else if(ifx)
6137                                                 continueIfTrue(ifx);
6138                                         goto release;
6139                                 }
6140                                 pic14_emitcode("setb","c");
6141                         } else{
6142                                 // lit == (0 or 1)
6143                                 if(lit == 0){
6144                                         // lit == 0, result = left
6145                                         if(size && pic14_sameRegs(AOP(result),AOP(left)))
6146                                                 goto release;
6147                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6148                                 } else{
6149                                         // lit == 1, result = not(left)
6150                                         if(size && pic14_sameRegs(AOP(result),AOP(left))){
6151                                                 emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
6152                                                 emitpcode(POC_XORWF,  popGet(AOP(result),offset));
6153                                                 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6154                                                 goto release;
6155                                         } else {
6156                                                 assert ( !"incomplete genXor" );
6157                                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6158                                                 pic14_emitcode("cpl","c");
6159                                         }
6160                                 }
6161                         }
6162                         
6163                 } else {
6164                         // right != literal
6165                         symbol *tlbl = newiTempLabel(NULL);
6166                         if (AOP_TYPE(right) == AOP_CRY){
6167                                 // c = bit ^ bit;
6168                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6169                         }
6170                         else{
6171                                 int sizer = AOP_SIZE(right);
6172                                 // c = bit ^ val
6173                                 // if val>>1 != 0, result = 1
6174                                 pic14_emitcode("setb","c");
6175                                 while(sizer){
6176                                         MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6177                                         if(sizer == 1)
6178                                                 // test the msb of the lsb
6179                                                 pic14_emitcode("anl","a,#0xfe");
6180                                         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6181                                         sizer--;
6182                                 }
6183                                 // val = (0,1)
6184                                 pic14_emitcode("rrc","a");
6185                         }
6186                         pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6187                         pic14_emitcode("cpl","c");
6188                         pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6189                 }
6190                 // bit = c
6191                 // val = c
6192                 if(size)
6193                         pic14_outBitC(result);
6194                 // if(bit | ...)
6195                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6196                         genIfxJump(ifx, "c");           
6197                 goto release ;
6198         }
6199         
6200         if(pic14_sameRegs(AOP(result),AOP(left))){
6201                 /* if left is same as result */
6202                 for(;size--; offset++) {
6203                         if(AOP_TYPE(right) == AOP_LIT){
6204                                 int t  = (lit >> (offset*8)) & 0x0FFL;
6205                                 if(t == 0x00L)
6206                                         continue;
6207                                 else
6208                                         if (IS_AOP_PREG(left)) {
6209                                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6210                                                 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6211                                                 aopPut(AOP(result),"a",offset);
6212                                         } else {
6213                                                 emitpcode(POC_MOVLW, popGetLit(t));
6214                                                 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6215                                                 pic14_emitcode("xrl","%s,%s",
6216                                                         aopGet(AOP(left),offset,FALSE,TRUE),
6217                                                         aopGet(AOP(right),offset,FALSE,FALSE));
6218                                         }
6219                         } else {
6220                                 if (AOP_TYPE(left) == AOP_ACC)
6221                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6222                                 else {
6223                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6224                                         emitpcode(POC_XORWF,popGet(AOP(left),offset));
6225                                         /*
6226                                         if (IS_AOP_PREG(left)) {
6227                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6228                                         aopPut(AOP(result),"a",offset);
6229                                         } else
6230                                         pic14_emitcode("xrl","%s,a",
6231                                         aopGet(AOP(left),offset,FALSE,TRUE));
6232                                         */
6233                                 }
6234                         }
6235                 }
6236         } else {
6237                 // left & result in different registers
6238                 if(AOP_TYPE(result) == AOP_CRY){
6239                         // result = bit
6240                         // if(size), result in bit
6241                         // if(!size && ifx), conditional oper: if(left ^ right)
6242                         symbol *tlbl = newiTempLabel(NULL);
6243                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6244                         if(size)
6245                                 pic14_emitcode("setb","c");
6246                         while(sizer--){
6247                                 if((AOP_TYPE(right) == AOP_LIT) &&
6248                                         (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6249                                         MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6250                                 } else {
6251                                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6252                                         pic14_emitcode("xrl","a,%s",
6253                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6254                                 }
6255                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6256                                 offset++;
6257                         }
6258                         if(size){
6259                                 CLRC;
6260                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6261                                 pic14_outBitC(result);
6262                         } else if(ifx)
6263                                 jmpTrueOrFalse(ifx, tlbl);
6264                 } else for(;(size--);offset++){
6265                         // normal case
6266                         // result = left & right
6267                         if(AOP_TYPE(right) == AOP_LIT){
6268                                 int t = (lit >> (offset*8)) & 0x0FFL;
6269                                 switch(t) { 
6270                                 case 0x00:
6271                                         if (AOP_TYPE(left) != AOP_ACC) {
6272                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6273                                         }
6274                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6275                                         pic14_emitcode("movf","%s,w",
6276                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6277                                         pic14_emitcode("movwf","%s",
6278                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6279                                         break;
6280                                 case 0xff:
6281                                         if (AOP_TYPE(left) == AOP_ACC) {
6282                                                 emitpcode(POC_XORLW, popGetLit(t));
6283                                         } else {
6284                                                 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6285                                         }
6286                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6287                                         break;
6288                                 default:
6289                                         if (AOP_TYPE(left) == AOP_ACC) {
6290                                                 emitpcode(POC_XORLW, popGetLit(t));
6291                                         } else {
6292                                                 emitpcode(POC_MOVLW, popGetLit(t));
6293                                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6294                                         }
6295                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6296                                         pic14_emitcode("movlw","0x%x",t);
6297                                         pic14_emitcode("xorwf","%s,w",
6298                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6299                                         pic14_emitcode("movwf","%s",
6300                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6301                                         
6302                                 }
6303                                 continue;
6304                         }
6305                         
6306                         // faster than result <- left, anl result,right
6307                         // and better if result is SFR
6308                         if (AOP_TYPE(left) == AOP_ACC) {
6309                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6310                         } else {
6311                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6312                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6313                         }
6314                         if ( AOP_TYPE(result) != AOP_ACC){
6315                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6316                         }
6317                 }
6318         }
6319         
6320 release :
6321         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6322         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6323         freeAsmop(result,NULL,ic,TRUE);     
6324 }
6325
6326 /*-----------------------------------------------------------------*/
6327 /* genInline - write the inline code out                           */
6328 /*-----------------------------------------------------------------*/
6329 static void genInline (iCode *ic)
6330 {
6331   char *buffer, *bp, *bp1;
6332
6333   FENTRY;
6334   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6335
6336   _G.inLine += (!options.asmpeep);
6337
6338   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6339   strcpy(buffer,IC_INLINE(ic));
6340
6341   /* emit each line as a code */
6342   while (*bp) {
6343     if (*bp == '\n') {
6344       *bp++ = '\0';
6345       
6346       if(*bp1)
6347         addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6348       bp1 = bp;
6349     } else {
6350       if (*bp == ':') {
6351         bp++;
6352         *bp = '\0';
6353         bp++;
6354
6355         /* print label, use this special format with NULL directive
6356          * to denote that the argument should not be indented with tab */
6357         addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6358
6359         bp1 = bp;
6360       } else
6361         bp++;
6362     }
6363   }
6364   if ((bp1 != bp) && *bp1)
6365     addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6366
6367   Safe_free(buffer);
6368
6369   _G.inLine -= (!options.asmpeep);
6370 }
6371
6372 /*-----------------------------------------------------------------*/
6373 /* genRRC - rotate right with carry                                */
6374 /*-----------------------------------------------------------------*/
6375 static void genRRC (iCode *ic)
6376 {
6377         operand *left , *result ;
6378         int size, offset = 0, same;
6379         
6380         FENTRY;
6381         /* rotate right with carry */
6382         left = IC_LEFT(ic);
6383         result=IC_RESULT(ic);
6384         aopOp (left,ic,FALSE);
6385         aopOp (result,ic,FALSE);
6386         
6387         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6388         
6389         same = pic14_sameRegs(AOP(result),AOP(left));
6390         
6391         size = AOP_SIZE(result);    
6392         
6393         /* get the lsb and put it into the carry */
6394         emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6395         
6396         offset = 0 ;
6397         
6398         while(size--) {
6399                 
6400                 if(same) {
6401                         emitpcode(POC_RRF, popGet(AOP(left),offset));
6402                 } else {
6403                         emitpcode(POC_RRFW, popGet(AOP(left),offset));
6404                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6405                 }
6406                 
6407                 offset++;
6408         }
6409         
6410         freeAsmop(left,NULL,ic,TRUE);
6411         freeAsmop(result,NULL,ic,TRUE);
6412 }
6413
6414 /*-----------------------------------------------------------------*/
6415 /* genRLC - generate code for rotate left with carry               */
6416 /*-----------------------------------------------------------------*/
6417 static void genRLC (iCode *ic)
6418 {    
6419         operand *left , *result ;
6420         int size, offset = 0;
6421         int same;
6422         
6423         FENTRY;
6424         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6425         /* rotate right with carry */
6426         left = IC_LEFT(ic);
6427         result=IC_RESULT(ic);
6428         aopOp (left,ic,FALSE);
6429         aopOp (result,ic,FALSE);
6430         
6431         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6432         
6433         same = pic14_sameRegs(AOP(result),AOP(left));
6434         
6435         /* move it to the result */
6436         size = AOP_SIZE(result);    
6437         
6438         /* get the msb and put it into the carry */
6439         emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6440         
6441         offset = 0 ;
6442         
6443         while(size--) {
6444                 
6445                 if(same) {
6446                         emitpcode(POC_RLF, popGet(AOP(left),offset));
6447                 } else {
6448                         emitpcode(POC_RLFW, popGet(AOP(left),offset));
6449                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6450                 }
6451                 
6452                 offset++;
6453         }
6454         
6455         
6456         freeAsmop(left,NULL,ic,TRUE);
6457         freeAsmop(result,NULL,ic,TRUE);
6458 }
6459
6460 /*-----------------------------------------------------------------*/
6461 /* genGetHbit - generates code get highest order bit               */
6462 /*-----------------------------------------------------------------*/
6463 static void genGetHbit (iCode *ic)
6464 {
6465         operand *left, *result;
6466         left = IC_LEFT(ic);
6467         result=IC_RESULT(ic);
6468         aopOp (left,ic,FALSE);
6469         aopOp (result,ic,FALSE);
6470         
6471         FENTRY;
6472         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6473         /* get the highest order byte into a */
6474         MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6475         if(AOP_TYPE(result) == AOP_CRY){
6476                 pic14_emitcode("rlc","a");
6477                 pic14_outBitC(result);
6478         }
6479         else{
6480                 pic14_emitcode("rl","a");
6481                 pic14_emitcode("anl","a,#0x01");
6482                 pic14_outAcc(result);
6483         }
6484         
6485         
6486         freeAsmop(left,NULL,ic,TRUE);
6487         freeAsmop(result,NULL,ic,TRUE);
6488 }
6489
6490 /*-----------------------------------------------------------------*/
6491 /* AccLsh - shift left accumulator by known count                  */
6492 /* MARK: pic14 always rotates through CARRY!                       */
6493 /*-----------------------------------------------------------------*/
6494 static void AccLsh (pCodeOp *pcop,int shCount)
6495 {
6496         FENTRY;
6497         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6498         shCount &= 0x0007;              // shCount : 0..7
6499         switch(shCount){
6500         case 0 :
6501                 return;
6502                 break;
6503         case 1 :
6504                 emitCLRC;
6505                 emitpcode(POC_RLF,pcop);
6506                 return;
6507                 break;
6508         case 2 :
6509                 emitpcode(POC_RLF,pcop);
6510                 emitpcode(POC_RLF,pcop);
6511                 break;
6512         case 3 :
6513                 emitpcode(POC_RLF,pcop);
6514                 emitpcode(POC_RLF,pcop);
6515                 emitpcode(POC_RLF,pcop);
6516                 break;
6517         case 4 :
6518                 emitpcode(POC_SWAPF,pcop);
6519                 break;
6520         case 5 :
6521                 emitpcode(POC_SWAPF,pcop);
6522                 emitpcode(POC_RLF,pcop);
6523                 break;
6524         case 6 :
6525                 emitpcode(POC_SWAPF,pcop);
6526                 emitpcode(POC_RLF,pcop);
6527                 emitpcode(POC_RLF,pcop);
6528                 break;
6529         case 7 :
6530                 emitpcode(POC_RRFW,pcop);
6531                 emitpcode(POC_RRF,pcop);
6532                 break;
6533         }
6534         /* clear invalid bits */
6535         emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6536         emitpcode(POC_ANDWF, pcop);
6537 }
6538
6539 /*-----------------------------------------------------------------*/
6540 /* AccRsh - shift right accumulator by known count                 */
6541 /* MARK: pic14 always rotates through CARRY!                       */
6542 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6543 /*            1: mask out invalid bits (zero-extend)               */
6544 /*            2: sign-extend result (pretty slow)                  */
6545 /*-----------------------------------------------------------------*/
6546 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6547 {
6548         FENTRY;
6549         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6550         shCount &= 0x0007;              // shCount : 0..7
6551         switch(shCount){
6552         case 0 :
6553                 return;
6554                 break;
6555         case 1 :
6556                 /* load sign if needed */
6557                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6558                 else if (mask_mode == 1) emitCLRC;
6559                 emitpcode(POC_RRF,pcop);
6560                 return;
6561                 break;
6562         case 2 :
6563                 /* load sign if needed */
6564                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6565                 emitpcode(POC_RRF,pcop);
6566                 /* load sign if needed */
6567                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6568                 emitpcode(POC_RRF,pcop);
6569                 if (mask_mode == 2) return;
6570                 break;
6571         case 3 :
6572                 /* load sign if needed */
6573                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6574                 emitpcode(POC_RRF,pcop);
6575                 /* load sign if needed */
6576                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6577                 emitpcode(POC_RRF,pcop);
6578                 /* load sign if needed */
6579                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6580                 emitpcode(POC_RRF,pcop);
6581                 if (mask_mode == 2) return;
6582                 break;
6583         case 4 :
6584                 emitpcode(POC_SWAPF,pcop);
6585                 break;
6586         case 5 :
6587                 emitpcode(POC_SWAPF,pcop);
6588                 emitpcode(POC_RRF,pcop);
6589                 break;
6590         case 6 :
6591                 emitpcode(POC_SWAPF,pcop);
6592                 emitpcode(POC_RRF,pcop);
6593                 emitpcode(POC_RRF,pcop);
6594                 break;
6595         case 7 :
6596                 if (mask_mode == 2)
6597                 {
6598                         /* load sign */
6599                         emitpcode(POC_RLFW,pcop);
6600                         emitpcode(POC_CLRF,pcop);
6601                         emitSKPNC;
6602                         emitpcode(POC_COMF,pcop);
6603                         return;
6604                 } else {
6605                         emitpcode(POC_RLFW,pcop);
6606                         emitpcode(POC_RLF,pcop);
6607                 }
6608                 break;
6609         }
6610
6611         if (mask_mode == 0)
6612         {
6613                 /* leave invalid bits undefined */
6614                 return;
6615         }
6616         
6617         /* clear invalid bits -- zero-extend */
6618         emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6619         emitpcode(POC_ANDWF, pcop);
6620
6621         if (mask_mode == 2) {
6622           /* sign-extend */
6623           emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6624           emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6625           emitpcode(POC_IORWF, pcop);
6626         }
6627 }
6628
6629 #if 0
6630 /*-----------------------------------------------------------------*/
6631 /* AccSRsh - signed right shift accumulator by known count                 */
6632 /*-----------------------------------------------------------------*/
6633 static void AccSRsh (int shCount)
6634 {
6635         symbol *tlbl ;
6636         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6637         if(shCount != 0){
6638                 if(shCount == 1){
6639                         pic14_emitcode("mov","c,acc.7");
6640                         pic14_emitcode("rrc","a");
6641                 } else if(shCount == 2){
6642                         pic14_emitcode("mov","c,acc.7");
6643                         pic14_emitcode("rrc","a");
6644                         pic14_emitcode("mov","c,acc.7");
6645                         pic14_emitcode("rrc","a");
6646                 } else {
6647                         tlbl = newiTempLabel(NULL);
6648                         /* rotate right accumulator */
6649                         AccRol(8 - shCount);
6650                         /* and kill the higher order bits */
6651                         pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6652                         pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6653                         pic14_emitcode("orl","a,#0x%02x",
6654                                 (unsigned char)~SRMask[shCount]);
6655                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6656                 }
6657         }
6658 }
6659
6660 /*-----------------------------------------------------------------*/
6661 /* shiftR1Left2Result - shift right one byte from left to result   */
6662 /*-----------------------------------------------------------------*/
6663 static void shiftR1Left2ResultSigned (operand *left, int offl,
6664                                                                           operand *result, int offr,
6665                                                                           int shCount)
6666 {
6667         int same;
6668         
6669         FENTRY;
6670         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6671         
6672         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6673         
6674         switch(shCount) {
6675         case 1:
6676                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6677                 if(same) 
6678                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6679                 else {
6680                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6681                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6682                 }
6683                 
6684                 break;
6685         case 2:
6686                 
6687                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6688                 if(same) 
6689                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6690                 else {
6691                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6692                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6693                 }
6694                 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6695                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6696                 
6697                 break;
6698                 
6699         case 3:
6700                 if(same)
6701                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6702                 else {
6703                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6704                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6705                 }
6706                 
6707                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6708                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6709                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6710                 
6711                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6712                 emitpcode(POC_IORLW, popGetLit(0xe0));
6713                 
6714                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6715                 break;
6716                 
6717         case 4:
6718                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6719                 emitpcode(POC_ANDLW,  popGetLit(0x0f));
6720                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6721                 emitpcode(POC_IORLW,  popGetLit(0xf0));
6722                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6723                 break;
6724         case 5:
6725                 if(same) {
6726                         emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6727                 } else {
6728                         emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6729                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6730                 }
6731                 emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6732                 emitpcode(POC_ANDLW,  popGetLit(0x07));
6733                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6734                 emitpcode(POC_IORLW,  popGetLit(0xf8));
6735                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6736                 break;
6737                 
6738         case 6:
6739                 if(same) {
6740                         emitpcode(POC_MOVLW, popGetLit(0x00));
6741                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6742                         emitpcode(POC_MOVLW, popGetLit(0xfe));
6743                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6744                         emitpcode(POC_IORLW, popGetLit(0x01));
6745                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6746                 } else {
6747                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6748                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6749                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6750                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6751                         emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6752                 }
6753                 break;
6754                 
6755         case 7:
6756                 if(same) {
6757                         emitpcode(POC_MOVLW, popGetLit(0x00));
6758                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6759                         emitpcode(POC_MOVLW, popGetLit(0xff));
6760                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6761                 } else {
6762                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6763                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6764                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6765                 }
6766                 
6767         default:
6768                 break;
6769         }
6770 }
6771
6772 /*-----------------------------------------------------------------*/
6773 /* shiftR1Left2Result - shift right one byte from left to result   */
6774 /*-----------------------------------------------------------------*/
6775 static void shiftR1Left2Result (operand *left, int offl,
6776                                                                 operand *result, int offr,
6777                                                                 int shCount, int sign)
6778 {
6779         int same;
6780         
6781         FENTRY;
6782         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6783         
6784         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6785         
6786         /* Copy the msb into the carry if signed. */
6787         if(sign) {
6788                 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6789                 return;
6790         }
6791         
6792         
6793         
6794         switch(shCount) {
6795         case 1:
6796                 emitCLRC;
6797                 if(same) 
6798                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6799                 else {
6800                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6801                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6802                 }
6803                 break;
6804         case 2:
6805                 emitCLRC;
6806                 if(same) {
6807                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6808                 } else {
6809                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6810                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6811                 }
6812                 emitCLRC;
6813                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6814                 
6815                 break;
6816         case 3:
6817                 if(same)
6818                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6819                 else {
6820                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6821                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6822                 }
6823                 
6824                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6825                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6826                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6827                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6828                 break;
6829                 
6830         case 4:
6831                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6832                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6833                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6834                 break;
6835                 
6836         case 5:
6837                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6838                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6839                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6840                 emitCLRC;
6841                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6842                 
6843                 break;
6844         case 6:
6845                 
6846                 emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6847                 emitpcode(POC_ANDLW, popGetLit(0x80));
6848                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6849                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6850                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6851                 break;
6852                 
6853         case 7:
6854                 
6855                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6856                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6857                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6858                 
6859                 break;
6860                 
6861         default:
6862                 break;
6863         }
6864 }
6865
6866 /*-----------------------------------------------------------------*/
6867 /* shiftL1Left2Result - shift left one byte from left to result    */
6868 /*-----------------------------------------------------------------*/
6869 static void shiftL1Left2Result (operand *left, int offl,
6870                                                                 operand *result, int offr, int shCount)
6871 {
6872         int same;
6873         
6874         //    char *l;
6875         FENTRY;
6876         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6877         
6878         same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6879         DEBUGpic14_emitcode ("; ***","same =  %d",same);
6880         //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6881         //    MOVA(l);
6882         /* shift left accumulator */
6883         //AccLsh(shCount); // don't comment out just yet...
6884         //    aopPut(AOP(result),"a",offr);
6885         
6886         switch(shCount) {
6887         case 1:
6888                 /* Shift left 1 bit position */
6889                 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6890                 if(same) {
6891                         emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6892                 } else {
6893                         emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6894                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6895                 }
6896                 break;
6897         case 2:
6898                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6899                 emitpcode(POC_ANDLW,popGetLit(0x7e));
6900                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6901                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6902                 break;
6903         case 3:
6904                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6905                 emitpcode(POC_ANDLW,popGetLit(0x3e));
6906                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6907                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6908                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6909                 break;
6910         case 4:
6911                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6912                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6913                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6914                 break;
6915         case 5:
6916                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6917                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6918                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6919                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6920                 break;
6921         case 6:
6922                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6923                 emitpcode(POC_ANDLW, popGetLit(0x30));
6924                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6925                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6926                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6927                 break;
6928         case 7:
6929                 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6930                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6931                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6932                 break;
6933                 
6934         default:
6935                 DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6936         }
6937         
6938 }
6939 #endif
6940
6941 /*-----------------------------------------------------------------*/
6942 /* movLeft2Result - move byte from left to result                  */
6943 /*-----------------------------------------------------------------*/
6944 static void movLeft2Result (operand *left, int offl,
6945                                                         operand *result, int offr)
6946 {
6947         char *l;
6948         FENTRY;
6949         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6950         if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6951                 l = aopGet(AOP(left),offl,FALSE,FALSE);
6952                 
6953                 if (*l == '@' && (IS_AOP_PREG(result))) {
6954                         pic14_emitcode("mov","a,%s",l);
6955                         aopPut(AOP(result),"a",offr);
6956                 } else {
6957                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6958                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6959                 }
6960         }
6961 }
6962
6963 /*-----------------------------------------------------------------*/
6964 /* shiftLeft_Left2ResultLit - shift left by known count            */
6965 /*-----------------------------------------------------------------*/
6966
6967 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6968 {
6969         int size, same, offr, i;
6970
6971         size = AOP_SIZE(left);
6972         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6973         
6974         same = pic14_sameRegs (AOP(left), AOP(result));
6975         
6976         offr = shCount / 8;
6977         shCount = shCount & 0x07;
6978
6979         size -= offr;
6980
6981         switch (shCount)
6982         {
6983         case 0: /* takes 0 or 2N cycles (for offr==0) */
6984                 if (!same || offr) {
6985                         for (i=size-1; i >= 0; i--)
6986                                 movLeft2Result (left, i, result, offr + i);
6987                 } // if
6988                 break;
6989                 
6990         case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6991                 if (same && offr) {
6992                         shiftLeft_Left2ResultLit (left, result, 8 * offr);
6993                         shiftLeft_Left2ResultLit (result, result, shCount);
6994                         return; /* prevent clearing result again */
6995                 } else {
6996                         emitCLRC;
6997                         for (i=0; i < size; i++) {
6998                                 if (same && !offr) {
6999                                         emitpcode (POC_RLF, popGet (AOP(left), i));
7000                                 } else {
7001                                         emitpcode (POC_RLFW, popGet (AOP(left), i));
7002                                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7003                                 } // if
7004                         } // for
7005                 } // if (offr)
7006                 break;
7007                 
7008         case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
7009                 /* works in-place/with offr as well */
7010                 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
7011                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7012                 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
7013
7014                 for (i = size - 2; i >= 0; i--)
7015                 {
7016                         emitpcode (POC_SWAPFW, popGet (AOP(left), i));
7017                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7018                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7019                         emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
7020                         emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
7021                 } // for i
7022                 break;
7023                 
7024         case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7025                 /* works in-place/with offr as well */
7026                 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7027                 for (i = size-2; i >= 0; i--) {
7028                         emitpcode (POC_RRFW, popGet (AOP(left), i));
7029                         emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7030                 } // for i
7031                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7032                 emitpcode (POC_RRF, popGet (AOP(result), offr));
7033                 break;
7034         
7035         default:
7036                 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7037                 shiftLeft_Left2ResultLit (result, result, 1);
7038                 return; /* prevent clearing result again */
7039                 break;
7040         } // switch
7041
7042         while (0 < offr--)
7043         {
7044                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7045         } // while
7046 }
7047
7048 /*-----------------------------------------------------------------*/
7049 /* shiftRight_Left2ResultLit - shift right by known count          */
7050 /*-----------------------------------------------------------------*/
7051
7052 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7053 {
7054         int size, same, offr, i;
7055
7056         size = AOP_SIZE(left);
7057         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7058         
7059         same = pic14_sameRegs (AOP(left), AOP(result));
7060         
7061         offr = shCount / 8;
7062         shCount = shCount & 0x07;
7063
7064         size -= offr;
7065
7066         if (size)
7067         {
7068                 switch (shCount)
7069                 {
7070                 case 0: /* takes 0 or 2N cycles (for offr==0) */
7071                         if (!same || offr) {
7072                                 for (i=0; i < size; i++)
7073                                         movLeft2Result (left, i + offr, result, i);
7074                         } // if
7075                         break;
7076                         
7077                 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7078                         emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7079                         if (same && offr) {
7080                                 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7081                                 shiftRight_Left2ResultLit (result, result, shCount, sign);
7082                                 return; /* prevent sign-extending result again */
7083                         } else {
7084                                 emitCLRC;
7085                                 if (sign) {
7086                                         emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7087                                         emitSETC;
7088                                 }
7089                                 for (i = size-1; i >= 0; i--) {
7090                                         if (same && !offr) {
7091                                                 emitpcode (POC_RRF, popGet (AOP(left), i));
7092                                         } else {
7093                                                 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7094                                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7095                                         }
7096                                 } // for i
7097                         } // if (offr)
7098                         break;
7099                         
7100                 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7101                         /* works in-place/with offr as well */
7102                         emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7103                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7104                         emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7105
7106                         for (i = 1; i < size; i++)
7107                         {
7108                                 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7109                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7110                                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7111                                 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7112                                 emitpcode (POC_XORWF, popGet (AOP(result), i));
7113                         } // for i
7114
7115                         if (sign)
7116                         {
7117                                 emitpcode (POC_MOVLW, popGetLit (0xF0));
7118                                 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7119                                 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7120                         } // if
7121                         break;
7122                         
7123                 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7124                         /* works in-place/with offr as well */
7125                         emitpcode (POC_RLFW, popGet (AOP(left), offr));
7126                         for (i = 0; i < size-1; i++) {
7127                                 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7128                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7129                         } // for i
7130                         emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7131                         if (!sign) {
7132                                 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7133                         } else {
7134                                 emitSKPNC;
7135                                 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7136                         }
7137                         break;
7138                 
7139                 default:
7140                         shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7141                         shiftRight_Left2ResultLit (result, result, 1, sign);
7142                         return; /* prevent sign extending result again */
7143                         break;
7144                 } // switch
7145         } // if
7146
7147         addSign (result, size, sign);
7148 }
7149
7150 #if 0
7151 /*-----------------------------------------------------------------*/
7152 /* shiftL2Left2Result - shift left two bytes from left to result   */
7153 /*-----------------------------------------------------------------*/
7154 static void shiftL2Left2Result (operand *left, int offl,
7155                                                                 operand *result, int offr, int shCount)
7156 {
7157         FENTRY;
7158         
7159         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7160         
7161         if(pic14_sameRegs(AOP(result), AOP(left))) {
7162                 switch(shCount) {
7163                 case 0:
7164                         break;
7165                 case 1:
7166                 case 2:
7167                 case 3:
7168                         
7169                         emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7170                         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7171                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7172                         
7173                         while(--shCount) {
7174                                 emitCLRC;
7175                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7176                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7177                         }
7178                         
7179                         break;
7180                 case 4:
7181                 case 5:
7182                         emitpcode(POC_MOVLW, popGetLit(0x0f));
7183                         emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7184                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7185                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7186                         emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7187                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7188                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7189                         if(shCount >=5) {
7190                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7191                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7192                         }
7193                         break;
7194                 case 6:
7195                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7196                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7197                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7198                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7199                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7200                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7201                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7202                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7203                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7204                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7205                         break;
7206                 case 7:
7207                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7208                         emitpcode(POC_RRFW, popGet(AOP(result),offr));
7209                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7210                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7211                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7212                 }
7213                 
7214         } else {
7215                 switch(shCount) {
7216                 case 0:
7217                         break;
7218                 case 1:
7219                 case 2:
7220                 case 3:
7221                 /* note, use a mov/add for the shift since the mov has a
7222                         chance of getting optimized out */
7223                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7224                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7225                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7226                         emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
7227                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7228                         
7229                         while(--shCount) {
7230                                 emitCLRC;
7231                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7232                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7233                         }
7234                         break;
7235                         
7236                 case 4:
7237                 case 5:
7238                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7239                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7240                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7241                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7242                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7243                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7244                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7245                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7246                         
7247                         
7248                         if(shCount == 5) {
7249                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7250                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7251                         }
7252                         break;
7253                 case 6:
7254                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7255                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7256                         emitpcode(POC_RRFW, popGet(AOP(result),offl));
7257                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
7258                         
7259                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7260                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7261                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7262                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7263                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7264                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7265                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7266                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7267                         break;
7268                 case 7:
7269                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7270                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7271                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7272                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7273                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7274                 }
7275         }
7276         
7277 }
7278
7279 /*-----------------------------------------------------------------*/
7280 /* shiftR2Left2Result - shift right two bytes from left to result  */
7281 /*-----------------------------------------------------------------*/
7282 static void shiftR2Left2Result (operand *left, int offl,
7283                                                                 operand *result, int offr,
7284                                                                 int shCount, int sign)
7285 {
7286         int same=0;
7287         
7288         FENTRY;
7289         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7290         same = pic14_sameRegs(AOP(result), AOP(left));
7291         
7292         if(same && ((offl + MSB16) == offr)){
7293                 same=1;
7294                 /* don't crash result[offr] */
7295                 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7296                 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7297         }
7298         /* else {
7299         movLeft2Result(left,offl, result, offr);
7300         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7301         }
7302         */
7303         /* a:x >> shCount (x = lsb(result))*/
7304         /*
7305         if(sign)
7306         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7307         else {
7308         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7309         */
7310         switch(shCount) {
7311         case 0:
7312                 break;
7313         case 1:
7314         case 2:
7315         case 3:
7316                 if(sign)
7317                         emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7318                 else
7319                         emitCLRC;
7320                 
7321                 if(same) {
7322                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7323                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7324                 } else {
7325                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7326                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7327                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7328                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7329                 }
7330                 
7331                 while(--shCount) {
7332                         if(sign)
7333                                 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7334                         else
7335                                 emitCLRC;
7336                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7337                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7338                 }
7339                 break;
7340         case 4:
7341         case 5:
7342                 if(same) {
7343                         
7344                         emitpcode(POC_MOVLW, popGetLit(0xf0));
7345                         emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7346                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7347                         
7348                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7349                         emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7350                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7351                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7352                 } else {
7353                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7354                         emitpcode(POC_ANDLW, popGetLit(0x0f));
7355                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7356                         
7357                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7358                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7359                         emitpcode(POC_ANDLW, popGetLit(0xf0));
7360                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7361                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7362                 }
7363                 
7364                 if(shCount >=5) {
7365                         emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7366                         emitpcode(POC_RRF, popGet(AOP(result),offr));
7367                 }
7368                 
7369                 if(sign) {
7370                         emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7371                         emitpcode(POC_BTFSC, 
7372                                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7373                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7374                 }
7375                 
7376                 break;
7377                 
7378         case 6:
7379                 if(same) {
7380                         
7381                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7382                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7383                         
7384                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7385                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7386                         emitpcode(POC_RLFW, popGet(AOP(result),offr));
7387                         emitpcode(POC_ANDLW,popGetLit(0x03));
7388                         if(sign) {
7389                                 emitpcode(POC_BTFSC, 
7390                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7391                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7392                         }
7393                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7394                         emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7395                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7396                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7397                 } else {
7398                         emitpcode(POC_RLFW, popGet(AOP(left),offl));
7399                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7400                         emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7401                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7402                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7403                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7404                         emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7405                         emitpcode(POC_ANDLW,popGetLit(0x03));
7406                         if(sign) {
7407                                 emitpcode(POC_BTFSC, 
7408                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7409                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7410                         }
7411                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7412                         //emitpcode(POC_RLF,  popGet(AOP(result),offr));
7413                         
7414                         
7415                 }
7416                 
7417                 break;
7418         case 7:
7419                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7420                 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7421                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7422                 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7423                 if(sign) {
7424                         emitSKPNC;
7425                         emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7426                 } else 
7427                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7428   }
7429 }
7430
7431 /*-----------------------------------------------------------------*/
7432 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7433 /*-----------------------------------------------------------------*/
7434 static void shiftLLeftOrResult (operand *left, int offl,
7435                                                                 operand *result, int offr, int shCount)
7436 {
7437         FENTRY;
7438         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7439         
7440         /* shift left accumulator */
7441         AccLsh(left,offl,shCount);
7442         /* or with result */
7443         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7444         assert ( !"broken (modifies left, fails for left==result))" );
7445 }
7446
7447 /*-----------------------------------------------------------------*/
7448 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7449 /*-----------------------------------------------------------------*/
7450 static void shiftRLeftOrResult (operand *left, int offl,
7451                                                                 operand *result, int offr, int shCount)
7452 {
7453         FENTRY;
7454         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7455         
7456         /* shift right accumulator */
7457         AccRsh(left,offl,shCount);
7458         /* or with result */
7459         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7460         assert ( !"broken (modifies left, fails for left==result))" );
7461 }
7462
7463 /*-----------------------------------------------------------------*/
7464 /* genlshOne - left shift a one byte quantity by known count       */
7465 /*-----------------------------------------------------------------*/
7466 static void genlshOne (operand *result, operand *left, int shCount)
7467 {       
7468         FENTRY;
7469         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7470         shiftL1Left2Result(left, LSB, result, LSB, shCount);
7471 }
7472
7473 /*-----------------------------------------------------------------*/
7474 /* genlshTwo - left shift two bytes by known amount != 0           */
7475 /*-----------------------------------------------------------------*/
7476 static void genlshTwo (operand *result,operand *left, int shCount)
7477 {
7478         int size;
7479         
7480         FENTRY;
7481         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7482         size = pic14_getDataSize(result);
7483         
7484         /* if shCount >= 8 */
7485         if (shCount >= 8) {
7486                 shCount -= 8 ;
7487                 
7488                 if (size > 1){
7489                         if (shCount)
7490                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7491                         else 
7492                                 movLeft2Result(left, LSB, result, MSB16);
7493                 }
7494                 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7495         }
7496         
7497         /*  1 <= shCount <= 7 */
7498         else {  
7499                 if(size == 1)
7500                         shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7501                 else 
7502                         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7503         }
7504 }
7505
7506 /*-----------------------------------------------------------------*/
7507 /* shiftLLong - shift left one long from left to result            */
7508 /* offl = LSB or MSB16                                             */
7509 /*-----------------------------------------------------------------*/
7510 static void shiftLLong (operand *left, operand *result, int offr )
7511 {
7512         char *l;
7513         int size = AOP_SIZE(result);
7514         
7515         FENTRY;
7516         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7517         if(size >= LSB+offr){
7518                 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7519                 MOVA(l);
7520                 pic14_emitcode("add","a,acc");
7521                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7522                         size >= MSB16+offr && offr != LSB )
7523                         pic14_emitcode("xch","a,%s",
7524                         aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7525                 else      
7526                         aopPut(AOP(result),"a",LSB+offr);
7527         }
7528         
7529         if(size >= MSB16+offr){
7530                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7531                         l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7532                         MOVA(l);
7533                 }
7534                 pic14_emitcode("rlc","a");
7535                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7536                         size >= MSB24+offr && offr != LSB)
7537                         pic14_emitcode("xch","a,%s",
7538                         aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7539                 else      
7540                         aopPut(AOP(result),"a",MSB16+offr);
7541         }
7542         
7543         if(size >= MSB24+offr){
7544                 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7545                         l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7546                         MOVA(l);
7547                 }
7548                 pic14_emitcode("rlc","a");
7549                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7550                         size >= MSB32+offr && offr != LSB )
7551                         pic14_emitcode("xch","a,%s",
7552                         aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7553                 else      
7554                         aopPut(AOP(result),"a",MSB24+offr);
7555         }
7556         
7557         if(size > MSB32+offr){
7558                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7559                         l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7560                         MOVA(l);  
7561                 }
7562                 pic14_emitcode("rlc","a");
7563                 aopPut(AOP(result),"a",MSB32+offr);
7564         }
7565         if(offr != LSB)
7566                 aopPut(AOP(result),zero,LSB);       
7567 }
7568
7569 /*-----------------------------------------------------------------*/
7570 /* genlshFour - shift four byte by a known amount != 0             */
7571 /*-----------------------------------------------------------------*/
7572 static void genlshFour (operand *result, operand *left, int shCount)
7573 {
7574         int size;
7575         
7576         FENTRY;
7577         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7578         size = AOP_SIZE(result);
7579         
7580         /* if shifting more that 3 bytes */
7581         if (shCount >= 24 ) {
7582                 shCount -= 24;
7583                 if (shCount)
7584                 /* lowest order of left goes to the highest
7585                 order of the destination */
7586                 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7587                 else
7588                         movLeft2Result(left, LSB, result, MSB32);
7589                 aopPut(AOP(result),zero,LSB);
7590                 aopPut(AOP(result),zero,MSB16);
7591                 aopPut(AOP(result),zero,MSB32);
7592                 return;
7593         }
7594         
7595         /* more than two bytes */
7596         else if ( shCount >= 16 ) {
7597                 /* lower order two bytes goes to higher order two bytes */
7598                 shCount -= 16;
7599                 /* if some more remaining */
7600                 if (shCount)
7601                         shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7602                 else {
7603                         movLeft2Result(left, MSB16, result, MSB32);
7604                         movLeft2Result(left, LSB, result, MSB24);
7605                 }
7606                 aopPut(AOP(result),zero,MSB16);
7607                 aopPut(AOP(result),zero,LSB);
7608                 return;
7609         }    
7610         
7611         /* if more than 1 byte */
7612         else if ( shCount >= 8 ) {
7613                 /* lower order three bytes goes to higher order  three bytes */
7614                 shCount -= 8;
7615                 if(size == 2){
7616                         if(shCount)
7617                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7618                         else
7619                                 movLeft2Result(left, LSB, result, MSB16);
7620                 }
7621                 else{   /* size = 4 */
7622                         if(shCount == 0){
7623                                 movLeft2Result(left, MSB24, result, MSB32);
7624                                 movLeft2Result(left, MSB16, result, MSB24);
7625                                 movLeft2Result(left, LSB, result, MSB16);
7626                                 aopPut(AOP(result),zero,LSB);
7627                         }
7628                         else if(shCount == 1)
7629                                 shiftLLong(left, result, MSB16);
7630                         else{
7631                                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7632                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7633                                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7634                                 aopPut(AOP(result),zero,LSB);
7635                         }
7636                 }
7637         }
7638         
7639         /* 1 <= shCount <= 7 */
7640         else if(shCount <= 2){
7641                 shiftLLong(left, result, LSB);
7642                 if(shCount == 2)
7643                         shiftLLong(result, result, LSB);
7644         }
7645         /* 3 <= shCount <= 7, optimize */
7646         else{
7647                 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7648                 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7649                 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7650         }
7651 }
7652 #endif
7653
7654 #if 0
7655 /*-----------------------------------------------------------------*/
7656 /* genLeftShiftLiteral - left shifting by known count              */
7657 /*-----------------------------------------------------------------*/
7658 static void genLeftShiftLiteral (operand *left,
7659                                                                  operand *right,
7660                                                                  operand *result,
7661                                                                  iCode *ic)
7662 {    
7663         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7664         //int size;
7665         
7666         FENTRY;
7667         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7668         freeAsmop(right,NULL,ic,TRUE);
7669         
7670         aopOp(left,ic,FALSE);
7671         aopOp(result,ic,FALSE);
7672
7673         size = getSize(operandType(result));
7674         
7675 #if VIEW_SIZE
7676         pic14_emitcode("; shift left ","result %d, left %d",size,
7677                 AOP_SIZE(left));
7678 #endif
7679         
7680         /* I suppose that the left size >= result size */
7681         if(shCount == 0){
7682                 while(size--){
7683                         movLeft2Result(left, size, result, size);
7684                 }
7685         }
7686         
7687         else if(shCount >= (size * 8))
7688                 while(size--)
7689                         aopPut(AOP(result),zero,size);
7690                 else{
7691                         switch (size) {
7692                         case 1:
7693                                 genlshOne (result,left,shCount);
7694                                 break;
7695                                 
7696                         case 2:
7697                         case 3:
7698                                 genlshTwo (result,left,shCount);
7699                                 break;
7700                                 
7701                         case 4:
7702                                 genlshFour (result,left,shCount);
7703                                 break;
7704                         }
7705                 }
7706                 freeAsmop(left,NULL,ic,TRUE);
7707                 freeAsmop(result,NULL,ic,TRUE);
7708 }
7709 #endif
7710
7711 /*-----------------------------------------------------------------*
7712 * genMultiAsm - repeat assembly instruction for size of register.
7713 * if endian == 1, then the high byte (i.e base address + size of 
7714 * register) is used first else the low byte is used first;
7715 *-----------------------------------------------------------------*/
7716 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7717 {
7718         
7719         int offset = 0;
7720         
7721         FENTRY;
7722         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7723         
7724         if(!reg)
7725                 return;
7726         
7727         if(!endian) {
7728                 endian = 1;
7729         } else {
7730                 endian = -1;
7731                 offset = size-1;
7732         }
7733         
7734         while(size--) {
7735                 emitpcode(poc,    popGet(AOP(reg),offset));
7736                 offset += endian;
7737         }
7738         
7739 }
7740
7741 #if 0
7742 /*-----------------------------------------------------------------*/
7743 /* genLeftShift - generates code for left shifting                 */
7744 /*-----------------------------------------------------------------*/
7745 static void genLeftShift (iCode *ic)
7746 {
7747         operand *left,*right, *result;
7748         int size, offset;
7749         unsigned long lit = 0L;
7750         char *l;
7751         symbol *tlbl , *tlbl1;
7752         pCodeOp *pctemp;
7753         
7754         FENTRY;
7755         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7756         
7757         right = IC_RIGHT(ic);
7758         left  = IC_LEFT(ic);
7759         result = IC_RESULT(ic);
7760         
7761         aopOp(right,ic,FALSE);
7762         aopOp(left,ic,FALSE);
7763         aopOp(result,ic,FALSE);
7764         
7765         
7766         /* if the shift count is known then do it 
7767         as efficiently as possible */
7768         if (AOP_TYPE(right) == AOP_LIT) {
7769                 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7770                 return ;
7771         }
7772         
7773         /* shift count is unknown then we have to form 
7774         a loop get the loop count in B : Note: we take
7775         only the lower order byte since shifting
7776         more that 32 bits make no sense anyway, ( the
7777         largest size of an object can be only 32 bits ) */  
7778         
7779         /* this code fails for RIGHT == RESULT */
7780         assert (!pic14_sameRegs (AOP(right), AOP(result)));
7781         
7782         /* now move the left to the result if they are not the
7783         same */
7784         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7785                 AOP_SIZE(result) > 1) {
7786                 
7787                 size = AOP_SIZE(result);
7788                 offset=0;
7789                 while (size--) {
7790                         l = aopGet(AOP(left),offset,FALSE,TRUE);
7791                         if (*l == '@' && (IS_AOP_PREG(result))) {
7792                                 
7793                                 pic14_emitcode("mov","a,%s",l);
7794                                 aopPut(AOP(result),"a",offset);
7795                         } else {
7796                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7797                                 emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7798                                 //aopPut(AOP(result),l,offset);
7799                         }
7800                         offset++;
7801                 }
7802         }
7803         
7804         if(AOP_TYPE(left) == AOP_LIT)
7805                 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7806
7807         size = AOP_SIZE(result);
7808         
7809         /* if it is only one byte then */
7810         if (size == 1) {
7811                 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7812                         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7813                         emitpcode(POC_ANDLW,  popGetLit(0xf0));
7814                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7815                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7816                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7817                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7818                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7819                         emitpcode(POC_RLFW,   popGet(AOP(result),0));
7820                         emitpcode(POC_ANDLW,  popGetLit(0xfe));
7821                         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7822                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7823                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7824                 } else {
7825                         
7826                         tlbl = newiTempLabel(NULL);
7827                         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7828                                 mov2w (AOP(left), 0);
7829                                 emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7830                         }
7831                         
7832                         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7833                         emitpcode(POC_RRF,    popGet(AOP(result),0));
7834                         emitpLabel(tlbl->key);
7835                         emitpcode(POC_RLF,    popGet(AOP(result),0));
7836                         emitpcode(POC_ADDLW,  popGetLit(1));
7837                         emitSKPC;
7838                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7839                 }
7840                 goto release ;
7841         }
7842         
7843         if (pic14_sameRegs(AOP(left),AOP(result))) {
7844                 
7845                 tlbl = newiTempLabel(NULL);
7846                 emitpcode(POC_COMFW,  popGet(AOP(right),0));
7847                 genMultiAsm(POC_RRF, result, size,1);
7848                 emitpLabel(tlbl->key);
7849                 genMultiAsm(POC_RLF, result, size,0);
7850                 emitpcode(POC_ADDLW,  popGetLit(1));
7851                 emitSKPC;
7852                 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7853                 goto release;
7854         }
7855         
7856         //tlbl = newiTempLabel(NULL);
7857         //offset = 0 ;   
7858         //tlbl1 = newiTempLabel(NULL);
7859         
7860         //reAdjustPreg(AOP(result));    
7861         
7862         //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7863         //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7864         //l = aopGet(AOP(result),offset,FALSE,FALSE);
7865         //MOVA(l);
7866         //pic14_emitcode("add","a,acc");         
7867         //aopPut(AOP(result),"a",offset++);
7868         //while (--size) {
7869         //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7870         //  MOVA(l);
7871         //  pic14_emitcode("rlc","a");         
7872         //  aopPut(AOP(result),"a",offset++);
7873         //}
7874         //reAdjustPreg(AOP(result));
7875         
7876         //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7877         //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7878         
7879         
7880         tlbl = newiTempLabel(NULL);
7881         tlbl1= newiTempLabel(NULL);
7882         
7883         size = AOP_SIZE(result);
7884         offset = 1;
7885         
7886         pctemp = popGetTempReg();  /* grab a temporary working register. */
7887         
7888         emitpcode(POC_MOVFW, popGet(AOP(right),0));
7889         
7890         /* offset should be 0, 1 or 3 */
7891         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7892         emitSKPNZ;
7893         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7894         
7895         emitpcode(POC_MOVWF, pctemp);
7896         
7897         
7898         emitpLabel(tlbl->key);
7899         
7900         emitCLRC;
7901         emitpcode(POC_RLF,  popGet(AOP(result),0));
7902         while(--size)
7903                 emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7904         
7905         emitpcode(POC_DECFSZ,  pctemp);
7906         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7907         emitpLabel(tlbl1->key);
7908         
7909         popReleaseTempReg(pctemp);
7910         
7911         
7912 release:
7913         freeAsmop (right,NULL,ic,TRUE);
7914         freeAsmop(left,NULL,ic,TRUE);
7915         freeAsmop(result,NULL,ic,TRUE);
7916 }
7917 #endif
7918
7919 #if 0
7920 /*-----------------------------------------------------------------*/
7921 /* genrshOne - right shift a one byte quantity by known count      */
7922 /*-----------------------------------------------------------------*/
7923 static void genrshOne (operand *result, operand *left,
7924                                            int shCount, int sign)
7925 {
7926         FENTRY;
7927         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7928         shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7929 }
7930
7931 /*-----------------------------------------------------------------*/
7932 /* genrshTwo - right shift two bytes by known amount != 0          */
7933 /*-----------------------------------------------------------------*/
7934 static void genrshTwo (operand *result,operand *left,
7935                                            int shCount, int sign)
7936 {
7937         FENTRY;
7938         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7939         /* if shCount >= 8 */
7940         if (shCount >= 8) {
7941                 shCount -= 8 ;
7942                 if (shCount)
7943                         shiftR1Left2Result(left, MSB16, result, LSB,
7944                         shCount, sign);
7945                 else
7946                         movLeft2Result(left, MSB16, result, LSB);
7947                 
7948                 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7949                 
7950                 if(sign) {
7951                         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7952                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7953                 }
7954         }
7955         
7956         /*  1 <= shCount <= 7 */
7957         else
7958                 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7959 }
7960
7961 /*-----------------------------------------------------------------*/
7962 /* shiftRLong - shift right one long from left to result           */
7963 /* offl = LSB or MSB16                                             */
7964 /*-----------------------------------------------------------------*/
7965 static void shiftRLong (operand *left, int offl,
7966                                                 operand *result, int sign)
7967 {
7968         int size, same;
7969         
7970         FENTRY;
7971         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7972         
7973         size = AOP_SIZE(left);
7974         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7975         
7976         if (sign)
7977                 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7978         else
7979                 emitCLRC;
7980
7981         assert (offl >= 0 && offl < size);
7982
7983         same = pic14_sameRegs (AOP(left), AOP(result));
7984
7985         /* perform the shift */
7986         while (size--)
7987         {
7988                 if (same && !offl) {
7989                         emitpcode (POC_RRF, popGet (AOP(result), size));
7990                 } else {
7991                         emitpcode (POC_RRFW, popGet (AOP(left), size));
7992                         emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7993                 }
7994         } // while
7995
7996         addSign (result, AOP_SIZE(left) - offl, sign);
7997 }
7998
7999 /*-----------------------------------------------------------------*/
8000 /* genrshFour - shift four byte by a known amount != 0             */
8001 /*-----------------------------------------------------------------*/
8002 static void genrshFour (operand *result, operand *left,
8003                                                 int shCount, int sign)
8004 {
8005         FENTRY;
8006         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8007         /* if shifting more that 3 bytes */
8008         if(shCount >= 24 ) {
8009                 shCount -= 24;
8010                 if(shCount)
8011                         shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8012                 else
8013                         movLeft2Result(left, MSB32, result, LSB);
8014                 
8015                 addSign(result, MSB16, sign);
8016         }
8017         else if(shCount >= 16){
8018                 shCount -= 16;
8019                 if(shCount)
8020                         shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8021                 else{
8022                         movLeft2Result(left, MSB24, result, LSB);
8023                         movLeft2Result(left, MSB32, result, MSB16);
8024                 }
8025                 addSign(result, MSB24, sign);
8026         }
8027         else if(shCount >= 8){
8028                 shCount -= 8;
8029                 if(shCount == 1)
8030                         shiftRLong(left, MSB16, result, sign);
8031                 else if(shCount == 0){
8032                         movLeft2Result(left, MSB16, result, LSB);
8033                         movLeft2Result(left, MSB24, result, MSB16);
8034                         movLeft2Result(left, MSB32, result, MSB24);
8035                         addSign(result, MSB32, sign);
8036                 }
8037                 else{
8038                         shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8039                         shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8040                         /* the last shift is signed */
8041                         shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8042                         addSign(result, MSB32, sign);
8043                 }
8044         }
8045         else{   /* 1 <= shCount <= 7 */
8046                 if(shCount <= 2){
8047                         shiftRLong(left, LSB, result, sign);
8048                         if(shCount == 2)
8049                                 shiftRLong(result, LSB, result, sign);
8050                 }
8051                 else{
8052                         shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8053                         shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8054                         shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8055                 }
8056         }
8057 }
8058
8059 /*-----------------------------------------------------------------*/
8060 /* genRightShiftLiteral - right shifting by known count            */
8061 /*-----------------------------------------------------------------*/
8062 static void genRightShiftLiteral (operand *left,
8063                                                                   operand *right,
8064                                                                   operand *result,
8065                                                                   iCode *ic,
8066                                                                   int sign)
8067 {    
8068         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8069         int lsize,res_size;
8070         
8071         FENTRY;
8072         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8073         freeAsmop(right,NULL,ic,TRUE);
8074         
8075         aopOp(left,ic,FALSE);
8076         aopOp(result,ic,FALSE);
8077         
8078 #if VIEW_SIZE
8079         pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8080                 AOP_SIZE(left));
8081 #endif
8082         
8083         lsize = pic14_getDataSize(left);
8084         res_size = pic14_getDataSize(result);
8085         /* test the LEFT size !!! */
8086         
8087         /* I suppose that the left size >= result size */
8088         if(shCount == 0){
8089                 while(res_size--)
8090                         movLeft2Result(left, res_size, result, res_size);
8091         }
8092         
8093         else if(shCount >= (lsize * 8)){
8094                 
8095                 if(res_size == 1) {
8096                         emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8097                         if(sign) {
8098                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8099                                 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8100                         }
8101                 } else {
8102                         
8103                         if(sign) {
8104                                 emitpcode(POC_MOVLW, popGetLit(0));
8105                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8106                                 emitpcode(POC_MOVLW, popGetLit(0xff));
8107                                 while(res_size--)
8108                                         emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8109                                 
8110                         } else {
8111                                 
8112                                 while(res_size--)
8113                                         emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8114                         }
8115                 }
8116         } else {
8117                 
8118                 switch (res_size) {
8119                 case 1:
8120                         genrshOne (result,left,shCount,sign);
8121                         break;
8122                         
8123                 case 2:
8124                         genrshTwo (result,left,shCount,sign);
8125                         break;
8126                         
8127                 case 4:
8128                         genrshFour (result,left,shCount,sign);
8129                         break;
8130                 default :
8131                         break;
8132                 }
8133                 
8134         }
8135
8136         freeAsmop(left,NULL,ic,TRUE);
8137         freeAsmop(result,NULL,ic,TRUE);
8138 }
8139 #endif
8140
8141 #if 0
8142 /*-----------------------------------------------------------------*/
8143 /* genSignedRightShift - right shift of signed number              */
8144 /*-----------------------------------------------------------------*/
8145 static void genSignedRightShift (iCode *ic)
8146 {
8147         operand *right, *left, *result;
8148         int size, offset;
8149         //  char *l;
8150         symbol *tlbl, *tlbl1 ;
8151         pCodeOp *pctemp;
8152         
8153         //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8154         
8155         /* we do it the hard way put the shift count in b
8156         and loop thru preserving the sign */
8157         FENTRY;
8158         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8159         
8160         right = IC_RIGHT(ic);
8161         left  = IC_LEFT(ic);
8162         result = IC_RESULT(ic);
8163         
8164         aopOp(right,ic,FALSE);  
8165         aopOp(left,ic,FALSE);
8166         aopOp(result,ic,FALSE);
8167         
8168         
8169         if ( AOP_TYPE(right) == AOP_LIT) {
8170                 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8171                 //genRightShiftLiteral (left,right,result,ic,1);
8172                 return ;
8173         }
8174         /* shift count is unknown then we have to form 
8175         a loop get the loop count in B : Note: we take
8176         only the lower order byte since shifting
8177         more that 32 bits make no sense anyway, ( the
8178         largest size of an object can be only 32 bits ) */  
8179         
8180         //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8181         //pic14_emitcode("inc","b");
8182         //freeAsmop (right,NULL,ic,TRUE);
8183         //aopOp(left,ic,FALSE);
8184         //aopOp(result,ic,FALSE);
8185         
8186         /* now move the left to the result if they are not the
8187         same */
8188         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
8189                 AOP_SIZE(result) > 1) {
8190                 
8191                 size = AOP_SIZE(result);
8192                 offset=0;
8193                 while (size--) { 
8194                         /*
8195                         l = aopGet(AOP(left),offset,FALSE,TRUE);
8196                         if (*l == '@' && IS_AOP_PREG(result)) {
8197                                 pic14_emitcode("mov","a,%s",l);
8198                                 aopPut(AOP(result),"a",offset);
8199                         } else
8200                         aopPut(AOP(result),l,offset);
8201                         */
8202                         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
8203                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
8204                         
8205                         offset++;
8206                 }
8207         }
8208         
8209         /* mov the highest order bit to OVR */    
8210         tlbl = newiTempLabel(NULL);
8211         tlbl1= newiTempLabel(NULL);
8212         
8213         size = AOP_SIZE(result);
8214         offset = size - 1;
8215         
8216         pctemp = popGetTempReg();  /* grab a temporary working register. */
8217         
8218         emitpcode(POC_MOVFW, popGet(AOP(right),0));
8219         
8220         /* offset should be 0, 1 or 3 */
8221         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8222         emitSKPNZ;
8223         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
8224         
8225         emitpcode(POC_MOVWF, pctemp);
8226         
8227         
8228         emitpLabel(tlbl->key);
8229         
8230         emitpcode(POC_RLFW,  popGet(AOP(result),offset));
8231         emitpcode(POC_RRF,   popGet(AOP(result),offset));
8232         
8233         while(--size) {
8234                 emitpcode(POC_RRF,   popGet(AOP(result),--offset));
8235         }
8236         
8237         emitpcode(POC_DECFSZ,  pctemp);
8238         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8239         emitpLabel(tlbl1->key);
8240         
8241         popReleaseTempReg(pctemp);
8242 #if 0
8243         size = AOP_SIZE(result);
8244         offset = size - 1;
8245         pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8246         pic14_emitcode("rlc","a");
8247         pic14_emitcode("mov","ov,c");
8248         /* if it is only one byte then */
8249         if (size == 1) {
8250                 l = aopGet(AOP(left),0,FALSE,FALSE);
8251                 MOVA(l);
8252                 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8253                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8254                 pic14_emitcode("mov","c,ov");
8255                 pic14_emitcode("rrc","a");
8256                 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8257                 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8258                 aopPut(AOP(result),"a",0);
8259                 goto release ;
8260         }
8261         
8262         reAdjustPreg(AOP(result));
8263         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8264         pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
8265         pic14_emitcode("mov","c,ov");
8266         while (size--) {
8267                 l = aopGet(AOP(result),offset,FALSE,FALSE);
8268                 MOVA(l);
8269                 pic14_emitcode("rrc","a");         
8270                 aopPut(AOP(result),"a",offset--);
8271         }
8272         reAdjustPreg(AOP(result));
8273         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8274         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8275         
8276 release:
8277 #endif
8278         
8279         freeAsmop(left,NULL,ic,TRUE);
8280         freeAsmop(result,NULL,ic,TRUE);
8281         freeAsmop(right,NULL,ic,TRUE);
8282 }
8283 #endif
8284
8285 /*-----------------------------------------------------------------*/
8286 /* loadSignToC - load the operand's sign bit into CARRY            */
8287 /*-----------------------------------------------------------------*/
8288
8289 static void loadSignToC (operand *op)
8290 {
8291         FENTRY;
8292         assert (op && AOP(op) && AOP_SIZE(op));
8293
8294         emitCLRC;
8295         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8296         emitSETC;
8297 }
8298
8299 /*-----------------------------------------------------------------*/
8300 /* genRightShift - generate code for right shifting                */
8301 /*-----------------------------------------------------------------*/
8302 static void genGenericShift (iCode *ic, int shiftRight)
8303 {
8304         operand *right, *left, *result;
8305         sym_link *retype ;
8306         int size;
8307         symbol *tlbl, *tlbl1, *inverselbl;
8308         
8309         FENTRY;
8310         /* if signed then we do it the hard way preserve the
8311         sign bit moving it inwards */
8312         retype = getSpec(operandType(IC_RESULT(ic)));
8313         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8314         
8315         /* signed & unsigned types are treated the same : i.e. the
8316         signed is NOT propagated inwards : quoting from the
8317         ANSI - standard : "for E1 >> E2, is equivalent to division
8318         by 2**E2 if unsigned or if it has a non-negative value,
8319         otherwise the result is implementation defined ", MY definition
8320         is that the sign does not get propagated */
8321         
8322         right = IC_RIGHT(ic);
8323         left  = IC_LEFT(ic);
8324         result = IC_RESULT(ic);
8325         
8326         aopOp(right,ic,FALSE);
8327         aopOp(left,ic,FALSE);
8328         aopOp(result,ic,FALSE);
8329         
8330         /* if the shift count is known then do it 
8331         as efficiently as possible */
8332         if (AOP_TYPE(right) == AOP_LIT) {
8333                 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8334                 if (lit < 0)
8335                 {
8336                         lit = -lit;
8337                         shiftRight = !shiftRight;
8338                 }
8339                 
8340                 if (shiftRight)
8341                         shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8342                 else
8343                         shiftLeft_Left2ResultLit (left, result, lit);
8344                 //genRightShiftLiteral (left,right,result,ic, 0);
8345                 return ;
8346         }
8347         
8348         /* shift count is unknown then we have to form 
8349         a loop get the loop count in B : Note: we take
8350         only the lower order byte since shifting
8351         more that 32 bits make no sense anyway, ( the
8352         largest size of an object can be only 32 bits ) */  
8353
8354         /* we must not overwrite the shift counter */
8355         assert (!pic14_sameRegs(AOP(right),AOP(result)));
8356         
8357         /* now move the left to the result if they are not the
8358         same */
8359         if (!pic14_sameRegs(AOP(left),AOP(result)))
8360         {
8361                 size = min(AOP_SIZE(result), AOP_SIZE(left));
8362                 while (size--) {
8363                         mov2w(AOP(left), size);
8364                         movwf(AOP(result), size);
8365                 }
8366                 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8367         }
8368         
8369         tlbl = newiTempLabel(NULL);
8370         tlbl1= newiTempLabel(NULL);
8371         inverselbl = NULL;
8372         size = AOP_SIZE(result);
8373
8374         mov2w(AOP(right),0);
8375         if (!SPEC_USIGN(operandType(right)))
8376         {
8377                 inverselbl = newiTempLabel(NULL);
8378                 /* signed shift count -- invert shift direction for c<0 */
8379                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8380                 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8381         } // if
8382         emitpcode(POC_SUBLW, popGetLit(0));     /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8383         /* check for `a = b >> c' with `-c == 0' */
8384         emitSKPNZ;
8385         emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8386         emitpLabel(tlbl->key);
8387         /* propagate the sign bit inwards for SIGNED result */
8388         if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8389         genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8390         emitpcode(POC_ADDLW,  popGetLit(1));    /* clears CARRY (unless W==0 afterwards) */
8391         emitSKPC;
8392         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8393
8394         if (!SPEC_USIGN(operandType(right)))
8395         {
8396                 symbol *inv_loop = newiTempLabel(NULL);
8397
8398                 shiftRight = !shiftRight;       /* invert shift direction */
8399                 
8400                 /* we came here from the code above -- we are done */
8401                 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8402                 
8403                 /* emit code for shifting N<0 steps, count is already in W */
8404                 emitpLabel(inverselbl->key);
8405                 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8406                 emitpLabel(inv_loop->key);
8407                 /* propagate the sign bit inwards for SIGNED result */
8408                 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8409                 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8410                 emitpcode(POC_ADDLW, popGetLit(1));
8411                 emitSKPC;
8412                 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8413         } // if
8414         
8415         emitpLabel(tlbl1->key);
8416         
8417         freeAsmop(left,NULL,ic,TRUE);
8418         freeAsmop (right,NULL,ic,TRUE);
8419         freeAsmop(result,NULL,ic,TRUE);
8420 }
8421
8422 static void genRightShift (iCode *ic)
8423 {
8424         genGenericShift(ic, 1);
8425 }
8426
8427 static void genLeftShift (iCode *ic)
8428 {
8429         genGenericShift(ic, 0);
8430 }
8431
8432 /*-----------------------------------------------------------------*/
8433 /* SetIrp - Set IRP bit                                            */
8434 /*-----------------------------------------------------------------*/
8435 void SetIrp(operand *result) {
8436         FENTRY;
8437         if (AOP_TYPE(result) == AOP_LIT) {
8438                 unsigned lit = (unsigned)operandLitValue(result);
8439                 if (lit&0x100)
8440                         emitSETIRP;
8441                 else
8442                         emitCLRIRP;
8443         } else {
8444                 if (PCOP(AOP(result))->type == PO_LITERAL) {
8445                         int addrs = PCOL(AOP(result))->lit;
8446                         if (addrs & 0x100)
8447                                 emitSETIRP;
8448                         else
8449                                 emitCLRIRP;
8450                 } else {
8451                         emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8452                         if(AOP_SIZE(result) > 1) {
8453                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8454                                 emitSETIRP;
8455                         }
8456                 }
8457         }
8458 }
8459
8460 static void
8461 setup_fsr (operand *ptr)
8462 {
8463   mov2w_op(ptr, 0);
8464   emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8465
8466   /* also setup-up IRP */
8467   SetIrp (ptr);
8468 }
8469
8470 /*-----------------------------------------------------------------*/
8471 /* emitPtrByteGet - emits code to get a byte into WREG from an     */
8472 /*                  arbitrary pointer (__code, __data, generic)    */
8473 /*-----------------------------------------------------------------*/
8474 static void
8475 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8476 {
8477     FENTRY;
8478     switch (p_type)
8479     {
8480     case POINTER:
8481     case FPOINTER:
8482       if (!alreadyAddressed) setup_fsr (src);
8483       emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8484       break;
8485     
8486     case CPOINTER:
8487       assert( AOP_SIZE(src) == 2 );
8488       mov2w_op(src, 0);
8489       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8490       mov2w_op(src, 1);
8491       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8492       emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE));   /* GPOINTER tag for __code space */
8493       call_libraryfunc ("__gptrget1");
8494       break;
8495     
8496     case GPOINTER:
8497       assert( AOP_SIZE(src) == 3 );
8498       mov2w_op(src, 0);
8499       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8500       mov2w_op(src, 1);
8501       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8502       mov2w_op(src, 2);
8503       call_libraryfunc ("__gptrget1");
8504       break;
8505     
8506     default:
8507       assert( !"unhandled pointer type" );
8508       break;
8509     }
8510 }
8511
8512 /*-----------------------------------------------------------------*/
8513 /* emitPtrByteSet - emits code to set a byte from src through a    */
8514 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR).       */
8515 /*-----------------------------------------------------------------*/
8516 static void
8517 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8518 {
8519     FENTRY;
8520     switch (p_type)
8521     {
8522     case POINTER:
8523     case FPOINTER:
8524       if (!alreadyAddressed) setup_fsr (dst);
8525       emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8526       break;
8527     
8528     case CPOINTER:
8529       assert( !"trying to assign to __code pointer" );
8530       break;
8531     
8532     case GPOINTER:
8533       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8534       mov2w_op(dst, 0);
8535       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8536       mov2w_op(dst, 1);
8537       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8538       mov2w_op(dst, 2);
8539       call_libraryfunc ("__gptrput1");
8540       break;
8541
8542     default:
8543       assert( !"unhandled pointer type" );
8544       break;
8545     }
8546 }
8547
8548 /*-----------------------------------------------------------------*/
8549 /* genUnpackBits - generates code for unpacking bits               */
8550 /*-----------------------------------------------------------------*/
8551 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8552 {    
8553   int rsize;            /* result size */
8554   sym_link *etype;      /* bitfield type information */
8555   int blen;             /* bitfield length */
8556   int bstr;             /* bitfield starting bit within byte */
8557
8558   FENTRY;
8559   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8560   etype = getSpec(operandType(result));
8561   rsize = getSize (operandType (result));
8562   blen = SPEC_BLEN (etype);
8563   bstr = SPEC_BSTR (etype);
8564
8565   /* single bit field case */
8566   if (blen == 1) {
8567     if (ifx) { /* that is for an if statement */
8568       pCodeOp *pcop;
8569       resolvedIfx rIfx;
8570       resolveIfx(&rIfx,ifx);
8571       if (ptype == -1) /* direct */
8572         pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8573       else
8574         pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8575       emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8576       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8577       ifx->generated=1;
8578     } else {
8579       int i;
8580       assert (!pic14_sameRegs (AOP(result), AOP(left)));
8581       for (i=0; i < AOP_SIZE(result); i++)
8582         emitpcode (POC_CLRF, popGet (AOP(result), i));
8583
8584       switch (ptype)
8585       {
8586       case -1:
8587         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8588         /* adjust result below */
8589         break;
8590         
8591       case POINTER:
8592       case FPOINTER:
8593       case GPOINTER:
8594       case CPOINTER:
8595         emitPtrByteGet (left, ptype, FALSE);
8596         emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8597         emitSKPZ;
8598         /* adjust result below */
8599         break;
8600         
8601       default:
8602         assert( !"unhandled pointer type" );
8603       } // switch
8604
8605       /* move sign-/zero extended bit to result */
8606       if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8607         emitpcode (POC_INCF, popGet (AOP(result), 0));
8608       } else {
8609         emitpcode (POC_DECF, popGet (AOP(result), 0));
8610       }
8611       addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8612     }
8613     return;
8614   }
8615   else if (blen <= 8 && ((blen + bstr) <= 8))
8616   {
8617     /* blen > 1 */
8618     int i;
8619
8620     for (i=0; i < AOP_SIZE(result); i++)
8621       emitpcode (POC_CLRF, popGet (AOP(result), i));
8622
8623     switch (ptype)
8624     {
8625     case -1:
8626       mov2w(AOP(left), 0);
8627       break;
8628       
8629     case POINTER:
8630     case FPOINTER:
8631     case GPOINTER:
8632     case CPOINTER:
8633       emitPtrByteGet (left, ptype, FALSE);
8634       break;
8635       
8636     default:
8637       assert( !"unhandled pointer type" );
8638     } // switch
8639
8640     if (blen < 8)
8641       emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8642     movwf(AOP(result), 0);
8643     AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8644
8645     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8646     {
8647       /* signed bitfield */
8648       assert (bstr + blen > 0);
8649       emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8650       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8651       emitpcode(POC_IORWF, popGet(AOP(result),0));
8652     }
8653     addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8654     return;
8655   }
8656
8657   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8658 }
8659
8660 #if 1
8661 /*-----------------------------------------------------------------*/
8662 /* genDataPointerGet - generates code when ptr offset is known     */
8663 /*-----------------------------------------------------------------*/
8664 static void genDataPointerGet (operand *left, 
8665         operand *result, 
8666         iCode *ic)
8667 {
8668         int size , offset = 0;
8669                 
8670         FENTRY;
8671         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8672         
8673         
8674         /* optimization - most of the time, left and result are the same
8675         * address, but different types. for the pic code, we could omit
8676         * the following
8677         */
8678         aopOp(result,ic,TRUE);
8679         
8680         if (pic14_sameRegs (AOP(left), AOP(result)))
8681                 return;
8682         
8683         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8684         
8685         //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8686         
8687         size = AOP_SIZE(result);
8688         if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8689         
8690         offset = 0;
8691         while (size--) {
8692                 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8693                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8694                 offset++;
8695         }
8696         
8697         freeAsmop(left,NULL,ic,TRUE);
8698         freeAsmop(result,NULL,ic,TRUE);
8699 }
8700 #endif
8701
8702 /*-----------------------------------------------------------------*/
8703 /* genNearPointerGet - pic14_emitcode for near pointer fetch       */
8704 /*-----------------------------------------------------------------*/
8705 static void genNearPointerGet (operand *left, 
8706                                                            operand *result, 
8707                                                            iCode *ic)
8708 {
8709         asmop *aop = NULL;
8710         sym_link *ltype = operandType(left);
8711         sym_link *rtype = operandType(result);
8712         sym_link *retype= getSpec(rtype);      /* bitfield type information */
8713         int direct = 0;
8714
8715         FENTRY;
8716         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8717         
8718         
8719         aopOp(left,ic,FALSE);
8720         
8721         /* if left is rematerialisable and
8722         result is not bit variable type and
8723         the left is pointer to data space i.e
8724         lower 128 bytes of space */
8725         if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8726                 !IS_BITVAR(retype)         &&
8727                 PIC_IS_DATA_PTR(ltype)) {
8728                 genDataPointerGet (left,result,ic);
8729                 return ;
8730         }
8731         
8732         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8733         aopOp (result,ic,FALSE);
8734         
8735         /* Check if can access directly instead of via a pointer */
8736         if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8737                 && AOP_SIZE(result) == 1)
8738         {
8739                 direct = 1;
8740         }
8741
8742         if (IS_BITFIELD(getSpec(operandType(result)))) 
8743         {
8744                 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8745                 goto release;
8746         }
8747         
8748         /* If the pointer value is not in a the FSR then need to put it in */
8749         /* Must set/reset IRP bit for use with FSR. */
8750         if (!direct)
8751           setup_fsr (left);
8752         
8753 //      sym_link *etype;
8754         /* if bitfield then unpack the bits */
8755         {
8756                 /* we have can just get the values */
8757                 int size = AOP_SIZE(result);
8758                 int offset = 0 ;  
8759                 
8760                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8761                 
8762                 while(size--) {
8763                         if (direct)
8764                                 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8765                         else
8766                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8767                         if (AOP_TYPE(result) == AOP_LIT) {
8768                                 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8769                         } else {
8770                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8771                         }
8772                         if (size && !direct)
8773                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8774                         offset++;
8775                 }
8776         }
8777         
8778         /* now some housekeeping stuff */
8779         if (aop) {
8780                 /* we had to allocate for this iCode */
8781                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8782                 freeAsmop(NULL,aop,ic,TRUE);
8783         } else { 
8784                 /* we did not allocate which means left
8785                 already in a pointer register, then
8786                 if size > 0 && this could be used again
8787                 we have to point it back to where it 
8788                 belongs */
8789                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8790                 if (AOP_SIZE(result) > 1 &&
8791                         !OP_SYMBOL(left)->remat &&
8792                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8793                         ic->depth )) {
8794                         int size = AOP_SIZE(result) - 1;
8795                         while (size--)
8796                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8797                 }
8798         }
8799         
8800 release:
8801         /* done */
8802         freeAsmop(left,NULL,ic,TRUE);
8803         freeAsmop(result,NULL,ic,TRUE);
8804
8805 }
8806
8807 #if 0
8808 /*-----------------------------------------------------------------*/
8809 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8810 /*-----------------------------------------------------------------*/
8811 static void genPagedPointerGet (operand *left, 
8812                                                                 operand *result, 
8813                                                                 iCode *ic)
8814 {
8815         asmop *aop = NULL;
8816         regs *preg = NULL ;
8817         char *rname ;
8818         sym_link *rtype, *retype;    
8819         
8820         FENTRY;
8821         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8822         
8823         rtype = operandType(result);
8824         retype= getSpec(rtype);
8825         
8826         aopOp(left,ic,FALSE);
8827         
8828         /* if the value is already in a pointer register
8829         then don't need anything more */
8830         if (!AOP_INPREG(AOP(left))) {
8831                 /* otherwise get a free pointer register */
8832                 aop = newAsmop(0);
8833                 preg = getFreePtr(ic,&aop,FALSE);
8834                 pic14_emitcode("mov","%s,%s",
8835                         preg->name,
8836                         aopGet(AOP(left),0,FALSE,TRUE));
8837                 rname = preg->name ;
8838         } else
8839                 rname = aopGet(AOP(left),0,FALSE,FALSE);
8840         
8841         freeAsmop(left,NULL,ic,TRUE);
8842         aopOp (result,ic,FALSE);
8843         
8844         /* if bitfield then unpack the bits */
8845         if (IS_BITFIELD(retype)) 
8846                 genUnpackBits (result,left,rname,PPOINTER,0);
8847         else {
8848                 /* we have can just get the values */
8849                 int size = AOP_SIZE(result);
8850                 int offset = 0 ;  
8851                 
8852                 while (size--) {
8853                         
8854                         pic14_emitcode("movx","a,@%s",rname);
8855                         aopPut(AOP(result),"a",offset);
8856                         
8857                         offset++ ;
8858                         
8859                         if (size)
8860                                 pic14_emitcode("inc","%s",rname);
8861                 }
8862         }
8863         
8864         /* now some housekeeping stuff */
8865         if (aop) {
8866                 /* we had to allocate for this iCode */
8867                 freeAsmop(NULL,aop,ic,TRUE);
8868         } else { 
8869         /* we did not allocate which means left
8870         already in a pointer register, then
8871         if size > 0 && this could be used again
8872         we have to point it back to where it 
8873                 belongs */
8874                 if (AOP_SIZE(result) > 1 &&
8875                         !OP_SYMBOL(left)->remat &&
8876                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8877                         ic->depth )) {
8878                         int size = AOP_SIZE(result) - 1;
8879                         while (size--)
8880                                 pic14_emitcode("dec","%s",rname);
8881                 }
8882         }
8883         
8884         /* done */
8885         freeAsmop(result,NULL,ic,TRUE);
8886         
8887         
8888 }
8889
8890 /*-----------------------------------------------------------------*/
8891 /* genFarPointerGet - gget value from far space                    */
8892 /*-----------------------------------------------------------------*/
8893 static void genFarPointerGet (operand *left,
8894                                                           operand *result, iCode *ic)
8895 {
8896         int size, offset ;
8897         sym_link *retype = getSpec(operandType(result));
8898         
8899         FENTRY;
8900         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8901         
8902         aopOp(left,ic,FALSE);
8903         
8904         /* if the operand is already in dptr 
8905         then we do nothing else we move the value to dptr */
8906         if (AOP_TYPE(left) != AOP_STR) {
8907                 /* if this is remateriazable */
8908                 if (AOP_TYPE(left) == AOP_IMMD)
8909                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8910                 else { /* we need to get it byte by byte */
8911                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8912                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8913                         if (options.model == MODEL_FLAT24)
8914                         {
8915                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8916                         }
8917                 }
8918         }
8919         /* so dptr know contains the address */
8920         freeAsmop(left,NULL,ic,TRUE);
8921         aopOp(result,ic,FALSE);
8922         
8923         /* if bit then unpack */
8924         if (IS_BITFIELD(retype)) 
8925                 genUnpackBits(result,left,"dptr",FPOINTER,0);
8926         else {
8927                 size = AOP_SIZE(result);
8928                 offset = 0 ;
8929                 
8930                 while (size--) {
8931                         pic14_emitcode("movx","a,@dptr");
8932                         aopPut(AOP(result),"a",offset++);
8933                         if (size)
8934                                 pic14_emitcode("inc","dptr");
8935                 }
8936         }
8937         
8938         freeAsmop(result,NULL,ic,TRUE);
8939 }
8940 #endif
8941
8942 #if 0
8943 /*-----------------------------------------------------------------*/
8944 /* genCodePointerGet - get value from code space                  */
8945 /*-----------------------------------------------------------------*/
8946 static void genCodePointerGet (operand *left,
8947                                                            operand *result, iCode *ic)
8948 {
8949         int size, offset ;
8950         sym_link *retype = getSpec(operandType(result));
8951         
8952         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8953         
8954         aopOp(left,ic,FALSE);
8955         
8956         /* if the operand is already in dptr 
8957         then we do nothing else we move the value to dptr */
8958         if (AOP_TYPE(left) != AOP_STR) {
8959                 /* if this is remateriazable */
8960                 if (AOP_TYPE(left) == AOP_IMMD)
8961                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8962                 else { /* we need to get it byte by byte */
8963                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8964                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8965                         if (options.model == MODEL_FLAT24)
8966                         {
8967                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8968                         }
8969                 }
8970         }
8971         /* so dptr know contains the address */
8972         freeAsmop(left,NULL,ic,TRUE);
8973         aopOp(result,ic,FALSE);
8974         
8975         /* if bit then unpack */
8976         if (IS_BITFIELD(retype)) 
8977                 genUnpackBits(result,left,"dptr",CPOINTER,0);
8978         else {
8979                 size = AOP_SIZE(result);
8980                 offset = 0 ;
8981                 
8982                 while (size--) {
8983                         pic14_emitcode("clr","a");
8984                         pic14_emitcode("movc","a,@a+dptr");
8985                         aopPut(AOP(result),"a",offset++);
8986                         if (size)
8987                                 pic14_emitcode("inc","dptr");
8988                 }
8989         }
8990         
8991         freeAsmop(result,NULL,ic,TRUE);
8992 }
8993 #endif
8994 /*-----------------------------------------------------------------*/
8995 /* genGenPointerGet - gget value from generic pointer space        */
8996 /*-----------------------------------------------------------------*/
8997 static void genGenPointerGet (operand *left,
8998                                                           operand *result, iCode *ic)
8999 {
9000         FENTRY;
9001         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9002         aopOp(left,ic,FALSE);
9003         aopOp(result,ic,FALSE);
9004         
9005         
9006         DEBUGpic14_AopType(__LINE__,left,NULL,result);
9007
9008         if (IS_BITFIELD(getSpec(operandType(result))))
9009         {
9010           genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
9011           return;
9012         }
9013
9014         {
9015           /* emit call to __gptrget */
9016           char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
9017           int size = AOP_SIZE(result);
9018           int idx = 0;
9019
9020           assert (size > 0 && size <= 4);
9021
9022           /* pass arguments */
9023           assert (AOP_SIZE(left) == 3);
9024           mov2w(AOP(left), 0);
9025           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9026           mov2w(AOP(left), 1);
9027           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9028           mov2w(AOP(left), 2);
9029           call_libraryfunc (func[size]);
9030           
9031           /* save result */
9032           movwf (AOP(result), --size);
9033           while (size--) {
9034             emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
9035             movwf (AOP(result), size);
9036           } // while
9037         }
9038         
9039         freeAsmop(left,NULL,ic,TRUE);
9040         freeAsmop(result,NULL,ic,TRUE);
9041         
9042 }
9043
9044 /*-----------------------------------------------------------------*/
9045 /* genConstPointerGet - get value from const generic pointer space */
9046 /*-----------------------------------------------------------------*/
9047 static void genConstPointerGet (operand *left,
9048                                                                 operand *result, iCode *ic)
9049 {
9050         //sym_link *retype = getSpec(operandType(result));
9051         #if 0
9052         symbol *albl, *blbl;//, *clbl;
9053         pCodeOp *pcop;
9054         #endif
9055         PIC_OPCODE poc;
9056         int i, size, lit;
9057         
9058         FENTRY;
9059         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9060         aopOp(left,ic,FALSE);
9061         aopOp(result,ic,FALSE);
9062         
9063         size = AOP_SIZE(result);
9064         
9065         DEBUGpic14_AopType(__LINE__,left,NULL,result);
9066         
9067         DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9068
9069         lit = op_isLitLike (left);
9070         poc = lit ? POC_MOVLW : POC_MOVFW;
9071
9072         if (IS_BITFIELD(getSpec(operandType(result))))
9073         {
9074                 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9075                 goto release;
9076         }
9077
9078         {
9079                 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9080                 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9081                 assert (size > 0 && size <= 4);
9082                 
9083                 mov2w_op(left, 0);
9084                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9085                 mov2w_op(left, 1);
9086                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9087                 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9088                 call_libraryfunc (func[size]);
9089
9090                 movwf(AOP(result),size-1);
9091                 for (i = 1; i < size; i++)
9092                 {
9093                         emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9094                         movwf(AOP(result),size - 1 - i);
9095                 } // for
9096         }
9097         
9098 release:
9099         freeAsmop(left,NULL,ic,TRUE);
9100         freeAsmop(result,NULL,ic,TRUE);
9101         
9102 }
9103 /*-----------------------------------------------------------------*/
9104 /* genPointerGet - generate code for pointer get                   */
9105 /*-----------------------------------------------------------------*/
9106 static void genPointerGet (iCode *ic)
9107 {
9108         operand *left, *result ;
9109         sym_link *type, *etype;
9110         int p_type = -1;
9111         
9112         FENTRY;
9113         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9114         
9115         left = IC_LEFT(ic);
9116         result = IC_RESULT(ic) ;
9117         
9118         /* depending on the type of pointer we need to
9119         move it to the correct pointer register */
9120         type = operandType(left);
9121         etype = getSpec(type);
9122         
9123         if (IS_PTR_CONST(type))
9124                 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9125         
9126         /* if left is of type of pointer then it is simple */
9127         if (IS_PTR(type) && !IS_FUNC(type->next)) 
9128                 p_type = DCL_TYPE(type);
9129         else {
9130                 /* we have to go by the storage class */
9131                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9132                 
9133                 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9134                 
9135                 if (SPEC_OCLS(etype)->codesp ) {
9136                         DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9137                         //p_type = CPOINTER ; 
9138                 }
9139                 else
9140                         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9141                                 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9142                         /*p_type = FPOINTER ;*/ 
9143                         else
9144                                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9145                                         DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9146                                 /*        p_type = PPOINTER; */
9147                                 else
9148                                         if (SPEC_OCLS(etype) == idata )
9149                                                 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9150                                         /*      p_type = IPOINTER; */
9151                                         else
9152                                                 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9153                                         /*      p_type = POINTER ; */
9154         }
9155         
9156         /* now that we have the pointer type we assign
9157         the pointer values */
9158         switch (p_type) {
9159                 
9160         case POINTER: 
9161         case FPOINTER:
9162         //case IPOINTER:
9163                 genNearPointerGet (left,result,ic);
9164                 break;
9165 /*
9166         case PPOINTER:
9167                 genPagedPointerGet(left,result,ic);
9168                 break;
9169                 
9170         case FPOINTER:
9171                 genFarPointerGet (left,result,ic);
9172                 break;
9173 */              
9174         case CPOINTER:
9175                 genConstPointerGet (left,result,ic);
9176                 break;
9177                 
9178         case GPOINTER:
9179                 genGenPointerGet (left,result,ic);
9180                 break;
9181         default:
9182                 assert ( !"unhandled pointer type" );
9183                 break;
9184         }
9185         
9186 }
9187
9188 /*-----------------------------------------------------------------*/
9189 /* genPackBits - generates code for packed bit storage             */
9190 /*-----------------------------------------------------------------*/
9191 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9192 {
9193   int blen;             /* bitfield length */
9194   int bstr;             /* bitfield starting bit within byte */
9195   int litval;           /* source literal value (if AOP_LIT) */
9196   unsigned char mask;   /* bitmask within current byte */
9197
9198   FENTRY;
9199   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9200
9201   blen = SPEC_BLEN (etype);
9202   bstr = SPEC_BSTR (etype);
9203
9204   /* If the bitfield length is less than a byte and does not cross byte boundaries */
9205   if ((blen <= 8) && ((bstr + blen) <= 8))
9206   {
9207     mask = ((unsigned char) (0xFF << (blen + bstr)) |
9208             (unsigned char) (0xFF >> (8 - bstr)));
9209
9210     if (AOP_TYPE (right) == AOP_LIT)
9211     {
9212       /* Case with a bitfield length <8 and literal source */
9213       int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9214       if (blen == 1) {
9215         pCodeOp *pcop;
9216         
9217         switch (p_type)
9218         {
9219         case -1:
9220           if (AOP(result)->type == AOP_PCODE)
9221             pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9222           else
9223             pcop = popGet(AOP(result),0);
9224           emitpcode(lit?POC_BSF:POC_BCF,pcop);
9225           break;
9226         
9227         case POINTER:
9228         case FPOINTER:
9229           setup_fsr (result);
9230           emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9231           break;
9232         
9233         case CPOINTER:
9234           assert( !"trying to assign to bitfield via pointer to __code space" );
9235           break;
9236         
9237         case GPOINTER:
9238           emitPtrByteGet(result, p_type, FALSE);
9239           if (lit) {
9240             emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9241           } else {
9242             emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9243           }
9244           emitPtrByteSet(result, p_type, TRUE);
9245           break;
9246         
9247         default:
9248           assert( !"unhandled pointer type" );
9249           break;
9250         } // switch (p_type)
9251       } else {
9252         /* blen > 1 */
9253         litval = lit << bstr;
9254         litval &= (~mask) & 0x00ff;
9255         
9256         switch (p_type)
9257         {
9258         case -1:
9259           mov2w (AOP(result), 0);
9260           if ((litval|mask) != 0x00ff)
9261             emitpcode(POC_ANDLW, popGetLit (mask));
9262           if (litval != 0x00)
9263             emitpcode(POC_IORLW, popGetLit (litval));
9264           movwf (AOP(result), 0);
9265           break;
9266         
9267         case POINTER:
9268         case FPOINTER:
9269         case GPOINTER:
9270           emitPtrByteGet(result, p_type, FALSE);
9271           if ((litval|mask) != 0x00ff)
9272             emitpcode(POC_ANDLW, popGetLit (mask));
9273           if (litval != 0x00)
9274             emitpcode(POC_IORLW, popGetLit (litval));
9275           emitPtrByteSet(result, p_type, TRUE);
9276           break;
9277         
9278         case CPOINTER:
9279           assert( !"trying to assign to bitfield via pointer to __code space" );
9280           break;
9281         
9282         default:
9283           assert( !"unhandled pointer type" );
9284           break;
9285         } // switch
9286       } // if (blen > 1)
9287     }
9288     else
9289     {
9290       /* right is no literal */
9291       if (blen==1) {
9292         switch (p_type)
9293         {
9294         case -1:
9295           /* Note more efficient code, of pre clearing bit then only setting it if required,
9296            * can only be done if it is known that the result is not a SFR */
9297           emitpcode(POC_RRFW,popGet(AOP(right),0));
9298           emitSKPC;
9299           emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9300           emitSKPNC;
9301           emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9302           break;
9303         
9304         case POINTER:
9305         case FPOINTER:
9306         case GPOINTER:
9307           emitPtrByteGet (result, p_type, FALSE);
9308           emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9309           emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9310           emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9311           emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9312           emitPtrByteSet (result, p_type, TRUE);
9313           break;
9314         
9315         case CPOINTER:
9316           assert( !"trying to assign to bitfield via pointer to __code space" );
9317           break;
9318         
9319         default:
9320           assert( !"unhandled pointer type" );
9321           break;
9322         } // switch
9323         return;
9324       } else {
9325         /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9326         pCodeOp *temp = popGetTempReg ();
9327
9328         mov2w (AOP(right), 0);
9329         if (blen < 8) {
9330           emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9331         }
9332         emitpcode(POC_MOVWF, temp);
9333         if (bstr) {
9334           AccLsh (temp, bstr);
9335         }
9336         
9337         switch (p_type)
9338         {
9339         case -1:
9340           mov2w (AOP(result), 0);
9341           emitpcode(POC_ANDLW, popGetLit (mask));
9342           emitpcode(POC_IORFW, temp);
9343           movwf (AOP(result), 0);
9344           break;
9345         
9346         case POINTER:
9347         case FPOINTER:
9348         case GPOINTER:
9349           emitPtrByteGet (result, p_type, FALSE);
9350           emitpcode(POC_ANDLW, popGetLit (mask));
9351           emitpcode(POC_IORFW, temp);
9352           emitPtrByteSet (result, p_type, TRUE);
9353           break;
9354         
9355         case CPOINTER:
9356           assert( !"trying to assign to bitfield via pointer to __code space" );
9357           break;
9358         
9359         default:
9360           assert( !"unhandled pointer type" );
9361           break;
9362         } // switch
9363
9364         popReleaseTempReg (temp);
9365       } // if (blen > 1)
9366     } // if (AOP(right)->type != AOP_LIT)
9367     return;
9368   } // if (blen <= 8 && ((blen + bstr) <= 8))
9369
9370   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9371 }
9372
9373 /*-----------------------------------------------------------------*/
9374 /* genDataPointerSet - remat pointer to data space                 */
9375 /*-----------------------------------------------------------------*/
9376 static void genDataPointerSet(operand *right,
9377         operand *result,
9378         iCode *ic)
9379 {
9380         int size, offset = 0 ;
9381         int ressize;
9382         
9383         FENTRY;
9384         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9385         aopOp(right,ic,FALSE);
9386         aopOp(result,ic,FALSE);
9387         
9388         assert (IS_SYMOP(result));
9389         assert (IS_PTR(OP_SYM_TYPE(result)));
9390         
9391         if (AOP_TYPE(right) == AOP_LIT)
9392           size = 4;
9393         else
9394           size = AOP_SIZE(right);
9395         ressize = getSize(OP_SYM_ETYPE(result));
9396         if (size > ressize) size = ressize;
9397         //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9398         
9399         //assert( !"what's going on here?" );
9400
9401         /*
9402         if ( AOP_TYPE(result) == AOP_PCODE) {
9403         fprintf(stderr,"genDataPointerSet   %s, %d\n",
9404         AOP(result)->aopu.pcop->name,
9405         PCOI(AOP(result)->aopu.pcop)->offset);
9406         }
9407         */
9408         
9409         // tsd, was l+1 - the underline `_' prefix was being stripped
9410         while (size--) {
9411                 emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
9412                 
9413                 if (AOP_TYPE(right) == AOP_LIT) {
9414                         unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
9415                         //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9416                         if(lit&0xff) {
9417                                 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9418                                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9419                         } else {
9420                                 emitpcode(POC_CLRF, popGet(AOP(result), offset));
9421                         }
9422                 } else {
9423                         //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9424                         emitpcode(POC_MOVFW, popGet(AOP(right), offset));
9425                         emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9426                 }
9427                 
9428                 offset++;
9429         }
9430         
9431         freeAsmop(right,NULL,ic,TRUE);
9432         freeAsmop(result,NULL,ic,TRUE);
9433 }
9434
9435 /*-----------------------------------------------------------------*/
9436 /* genNearPointerSet - pic14_emitcode for near pointer put         */
9437 /*-----------------------------------------------------------------*/
9438 static void genNearPointerSet (operand *right,
9439                                                            operand *result, 
9440                                                            iCode *ic)
9441 {
9442         asmop *aop = NULL;
9443         sym_link *ptype = operandType(result);
9444         sym_link *retype = getSpec(operandType(right));
9445         sym_link *letype = getSpec(ptype);
9446         int direct = 0;
9447         
9448         
9449         FENTRY;
9450         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9451         aopOp(result,ic,FALSE);
9452         
9453 #if 1
9454         /* if the result is rematerializable &
9455         in data space & not a bit variable */
9456         //if (AOP_TYPE(result) == AOP_IMMD &&
9457         if (AOP_TYPE(result) == AOP_PCODE &&
9458                 PIC_IS_DATA_PTR(ptype) &&
9459                 !IS_BITVAR (retype) &&
9460                 !IS_BITVAR (letype)) {
9461                 genDataPointerSet (right,result,ic);
9462                 freeAsmop(result,NULL,ic,TRUE);
9463                 return;
9464         }
9465 #endif
9466
9467         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9468         aopOp(right,ic,FALSE);
9469         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9470         
9471         /* Check if can access directly instead of via a pointer */
9472         if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9473                 direct = 1;
9474         }
9475         
9476         if (IS_BITFIELD (letype))
9477         {
9478           genPackBits (letype, result, right, direct?-1:POINTER);
9479           return;
9480         }
9481         
9482         /* If the pointer value is not in a the FSR then need to put it in */
9483         /* Must set/reset IRP bit for use with FSR. */
9484         /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9485         if (!direct)
9486                 setup_fsr (result);
9487
9488         {
9489                 /* we have can just get the values */
9490                 int size = AOP_SIZE(right);
9491                 int offset = 0 ;    
9492                 
9493                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9494                 while (size--) {
9495                         char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9496                         if (*l == '@' ) {
9497                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9498                         } else {
9499                                 if (AOP_TYPE(right) == AOP_LIT) {
9500                                         emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9501                                 } else {
9502                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9503                                 }
9504                                 if (direct)
9505                                         emitpcode(POC_MOVWF,popGet(AOP(result),0));
9506                                 else
9507                                         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9508                         }
9509                         if (size && !direct)
9510                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9511                         offset++;
9512                 }
9513         }
9514         
9515         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9516         /* now some housekeeping stuff */
9517         if (aop) {
9518                 /* we had to allocate for this iCode */
9519                 freeAsmop(NULL,aop,ic,TRUE);
9520         } else { 
9521                 /* we did not allocate which means left
9522                 already in a pointer register, then
9523                 if size > 0 && this could be used again
9524                 we have to point it back to where it 
9525                 belongs */
9526                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9527                 if (AOP_SIZE(right) > 1 &&
9528                         !OP_SYMBOL(result)->remat &&
9529                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9530                         ic->depth )) {
9531                         int size = AOP_SIZE(right) - 1;
9532                         while (size--)
9533                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9534                 }
9535         }
9536         
9537         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9538         /* done */
9539
9540         freeAsmop(right,NULL,ic,TRUE);
9541         freeAsmop(result,NULL,ic,TRUE);
9542 }
9543
9544 #if 0
9545 /*-----------------------------------------------------------------*/
9546 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
9547 /*-----------------------------------------------------------------*/
9548 static void genPagedPointerSet (operand *right,
9549                                                                 operand *result, 
9550                                                                 iCode *ic)
9551 {
9552         asmop *aop = NULL;
9553         regs *preg = NULL ;
9554         char *rname , *l;
9555         sym_link *retype;
9556         
9557         FENTRY;
9558         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9559         
9560         retype= getSpec(operandType(right));
9561         
9562         aopOp(result,ic,FALSE);
9563         
9564         /* if the value is already in a pointer register
9565         then don't need anything more */
9566         if (!AOP_INPREG(AOP(result))) {
9567                 /* otherwise get a free pointer register */
9568                 aop = newAsmop(0);
9569                 preg = getFreePtr(ic,&aop,FALSE);
9570                 pic14_emitcode("mov","%s,%s",
9571                         preg->name,
9572                         aopGet(AOP(result),0,FALSE,TRUE));
9573                 rname = preg->name ;
9574         } else
9575                 rname = aopGet(AOP(result),0,FALSE,FALSE);
9576         
9577         freeAsmop(result,NULL,ic,TRUE);
9578         aopOp (right,ic,FALSE);
9579         
9580         /* if bitfield then unpack the bits */
9581         if (IS_BITFIELD(retype)) 
9582                 genPackBits (retype,result,right,rname,PPOINTER);
9583         else {
9584                 /* we have can just get the values */
9585                 int size = AOP_SIZE(right);
9586                 int offset = 0 ;  
9587                 
9588                 while (size--) {
9589                         l = aopGet(AOP(right),offset,FALSE,TRUE);
9590                         
9591                         MOVA(l);
9592                         pic14_emitcode("movx","@%s,a",rname);
9593                         
9594                         if (size)
9595                                 pic14_emitcode("inc","%s",rname);
9596                         
9597                         offset++;
9598                 }
9599         }
9600         
9601         /* now some housekeeping stuff */
9602         if (aop) {
9603                 /* we had to allocate for this iCode */
9604                 freeAsmop(NULL,aop,ic,TRUE);
9605         } else { 
9606         /* we did not allocate which means left
9607         already in a pointer register, then
9608         if size > 0 && this could be used again
9609         we have to point it back to where it 
9610                 belongs */
9611                 if (AOP_SIZE(right) > 1 &&
9612                         !OP_SYMBOL(result)->remat &&
9613                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9614                         ic->depth )) {
9615                         int size = AOP_SIZE(right) - 1;
9616                         while (size--)
9617                                 pic14_emitcode("dec","%s",rname);
9618                 }
9619         }
9620         
9621         /* done */
9622         freeAsmop(right,NULL,ic,TRUE);
9623         
9624         
9625 }
9626
9627 /*-----------------------------------------------------------------*/
9628 /* genFarPointerSet - set value from far space                     */
9629 /*-----------------------------------------------------------------*/
9630 static void genFarPointerSet (operand *right,
9631                                                           operand *result, iCode *ic)
9632 {
9633         int size, offset ;
9634         sym_link *retype = getSpec(operandType(right));
9635         
9636         FENTRY;
9637         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9638         aopOp(result,ic,FALSE);
9639         
9640         /* if the operand is already in dptr 
9641         then we do nothing else we move the value to dptr */
9642         if (AOP_TYPE(result) != AOP_STR) {
9643                 /* if this is remateriazable */
9644                 if (AOP_TYPE(result) == AOP_IMMD)
9645                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9646                 else { /* we need to get it byte by byte */
9647                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9648                         pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9649                         if (options.model == MODEL_FLAT24)
9650                         {
9651                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9652                         }
9653                 }
9654         }
9655         /* so dptr know contains the address */
9656         freeAsmop(result,NULL,ic,TRUE);
9657         aopOp(right,ic,FALSE);
9658         
9659         /* if bit then unpack */
9660         if (IS_BITFIELD(retype)) 
9661                 genPackBits(retype,result,right,"dptr",FPOINTER);
9662         else {
9663                 size = AOP_SIZE(right);
9664                 offset = 0 ;
9665                 
9666                 while (size--) {
9667                         char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9668                         MOVA(l);
9669                         pic14_emitcode("movx","@dptr,a");
9670                         if (size)
9671                                 pic14_emitcode("inc","dptr");
9672                 }
9673         }
9674         
9675         freeAsmop(right,NULL,ic,TRUE);
9676 }
9677 #endif
9678
9679 /*-----------------------------------------------------------------*/
9680 /* genGenPointerSet - set value from generic pointer space         */
9681 /*-----------------------------------------------------------------*/
9682 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9683 {
9684         sym_link *retype = getSpec(operandType(result));
9685         
9686         FENTRY;
9687         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9688         aopOp(right,ic,FALSE);
9689         aopOp(result,ic,FALSE);
9690
9691         
9692         DEBUGpic14_AopType(__LINE__,right,NULL,result);
9693
9694         if (IS_BITFIELD(retype))
9695         {
9696           genPackBits (retype, result, right, GPOINTER);
9697           return;
9698         }
9699
9700         {
9701           /* emit call to __gptrput */
9702           char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9703           int size = AOP_SIZE(right);
9704           int idx = 0;
9705
9706           assert (size == getSize(OP_SYM_ETYPE(result)));
9707           assert (size > 0 && size <= 4);
9708
9709           /* pass arguments */
9710           /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9711           {
9712             int off = size;
9713             idx = 2;
9714             while (off--)
9715             {
9716               mov2w_op (right, off);
9717               emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9718             }
9719             idx = 0;
9720           }
9721           /* - address */
9722           assert (AOP_SIZE(result) == 3);
9723           mov2w(AOP(result), 0);
9724           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9725           mov2w(AOP(result), 1);
9726           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9727           mov2w(AOP(result), 2);
9728           call_libraryfunc (func[size]);
9729         }
9730         
9731         freeAsmop(right,NULL,ic,TRUE);
9732         freeAsmop(result,NULL,ic,TRUE);
9733 }
9734
9735 /*-----------------------------------------------------------------*/
9736 /* genPointerSet - stores the value into a pointer location        */
9737 /*-----------------------------------------------------------------*/
9738 static void genPointerSet (iCode *ic)
9739 {    
9740         operand *right, *result ;
9741         sym_link *type, *etype;
9742         int p_type;
9743         
9744         FENTRY;
9745         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9746         
9747         right = IC_RIGHT(ic);
9748         result = IC_RESULT(ic) ;
9749         
9750         /* depending on the type of pointer we need to
9751         move it to the correct pointer register */
9752         type = operandType(result);
9753         etype = getSpec(type);
9754         /* if left is of type of pointer then it is simple */
9755         if (IS_PTR(type) && !IS_FUNC(type->next)) {
9756                 p_type = DCL_TYPE(type);
9757         }
9758         else {
9759                 /* we have to go by the storage class */
9760                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9761                 
9762                 /*  if (SPEC_OCLS(etype)->codesp ) { */
9763                 /*      p_type = CPOINTER ;  */
9764                 /*  } */
9765                 /*  else */
9766                 /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9767                 /*    p_type = FPOINTER ; */
9768                 /*      else */
9769                 /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9770                 /*        p_type = PPOINTER ; */
9771                 /*    else */
9772                 /*        if (SPEC_OCLS(etype) == idata ) */
9773                 /*      p_type = IPOINTER ; */
9774                 /*        else */
9775                 /*      p_type = POINTER ; */
9776         }
9777         
9778         /* now that we have the pointer type we assign
9779         the pointer values */
9780         switch (p_type) {
9781                 
9782         case POINTER:
9783         case FPOINTER:
9784         //case IPOINTER:
9785                 genNearPointerSet (right,result,ic);
9786                 break;
9787 /*
9788         case PPOINTER:
9789                 genPagedPointerSet (right,result,ic);
9790                 break;
9791                 
9792         case FPOINTER:
9793                 genFarPointerSet (right,result,ic);
9794                 break;
9795 */
9796         case GPOINTER:
9797                 genGenPointerSet (right,result,ic);
9798                 break;
9799                 
9800         default:
9801                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9802                         "genPointerSet: illegal pointer type");
9803         }
9804 }
9805
9806 /*-----------------------------------------------------------------*/
9807 /* genIfx - generate code for Ifx statement                        */
9808 /*-----------------------------------------------------------------*/
9809 static void genIfx (iCode *ic, iCode *popIc)
9810 {
9811         operand *cond = IC_COND(ic);
9812         int isbit =0;
9813         
9814         FENTRY;
9815         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9816         
9817         aopOp(cond,ic,FALSE);
9818         
9819         /* get the value into acc */
9820         if (AOP_TYPE(cond) != AOP_CRY)
9821                 pic14_toBoolean(cond);
9822         else
9823                 isbit = 1;
9824         
9825         /* if there was something to be popped then do it */
9826         if (popIc)
9827                 genIpop(popIc);
9828         
9829         if (isbit)
9830         {
9831                 /* This assumes that CARRY is set iff cond is true */
9832                 if (IC_TRUE(ic))
9833                 {
9834                         assert (!IC_FALSE(ic));
9835                         emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9836                         //emitSKPNC;
9837                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9838                 } else {
9839                         assert (IC_FALSE(ic));
9840                         emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9841                         //emitSKPC;
9842                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9843                 }
9844                 if (0)
9845                 {
9846                         static int hasWarned = 0;
9847                         if (!hasWarned)
9848                         {
9849                                 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9850                                 hasWarned = 1;
9851                         }
9852                 }
9853         }
9854         else
9855         {
9856                 /* now Z is set iff !cond */
9857                 if (IC_TRUE(ic))
9858                 {
9859                         assert (!IC_FALSE(ic));
9860                         emitSKPZ;
9861                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9862                 } else {
9863                         emitSKPNZ;
9864                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9865                 }
9866         }
9867         
9868         ic->generated = 1;
9869         
9870         /* the result is now in the accumulator */
9871         freeAsmop(cond,NULL,ic,TRUE);
9872 }
9873
9874 /*-----------------------------------------------------------------*/
9875 /* genAddrOf - generates code for address of                       */
9876 /*-----------------------------------------------------------------*/
9877 static void genAddrOf (iCode *ic)
9878 {
9879         operand *right, *result, *left;
9880         int size, offset ;
9881         
9882         FENTRY;
9883         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9884         
9885         
9886         //aopOp(IC_RESULT(ic),ic,FALSE);
9887         
9888         aopOp((left=IC_LEFT(ic)),ic,FALSE);
9889         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9890         aopOp((result=IC_RESULT(ic)),ic,TRUE);
9891         
9892         DEBUGpic14_AopType(__LINE__,left,right,result);
9893         assert (IS_SYMOP (left));
9894         
9895         /* sanity check: generic pointers to code space are not yet supported,
9896          * pionters to codespace must not be assigned addresses of __data values. */
9897  #if 0
9898         fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9899         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)));
9900         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)));
9901         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)));
9902         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)));
9903 #endif
9904
9905         if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9906           fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9907                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9908                 OP_SYMBOL(left)->name);
9909         } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9910           fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9911                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9912                 OP_SYMBOL(left)->name);
9913         }
9914         
9915         size = AOP_SIZE(IC_RESULT(ic));
9916         if (IS_GENPTR(OP_SYM_TYPE(result))) {
9917                 /* strip tag */
9918                 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9919         }
9920         offset = 0;
9921         
9922         while (size--) {
9923                 /* fixing bug #863624, reported from (errolv) */
9924                 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9925                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9926                 
9927 #if 0
9928                 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9929                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9930 #endif
9931                 offset++;
9932         }
9933
9934         if (IS_GENPTR(OP_SYM_TYPE(result)))
9935         {
9936                 /* provide correct tag */
9937                 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9938                 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9939                 movwf (AOP(result), 2);
9940         }
9941         
9942         freeAsmop(left,NULL,ic,FALSE);
9943         freeAsmop(result,NULL,ic,TRUE);
9944         
9945 }
9946
9947 #if 0
9948 /*-----------------------------------------------------------------*/
9949 /* genFarFarAssign - assignment when both are in far space         */
9950 /*-----------------------------------------------------------------*/
9951 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9952 {
9953         int size = AOP_SIZE(right);
9954         int offset = 0;
9955         char *l ;
9956         /* first push the right side on to the stack */
9957         while (size--) {
9958                 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9959                 MOVA(l);
9960                 pic14_emitcode ("push","acc");
9961         }
9962         
9963         freeAsmop(right,NULL,ic,FALSE);
9964         /* now assign DPTR to result */
9965         aopOp(result,ic,FALSE);
9966         size = AOP_SIZE(result);
9967         while (size--) {
9968                 pic14_emitcode ("pop","acc");
9969                 aopPut(AOP(result),"a",--offset);
9970         }
9971         freeAsmop(result,NULL,ic,FALSE);
9972         
9973 }
9974 #endif
9975
9976 /*-----------------------------------------------------------------*/
9977 /* genAssign - generate code for assignment                        */
9978 /*-----------------------------------------------------------------*/
9979 static void genAssign (iCode *ic)
9980 {
9981         operand *result, *right;
9982         int size, offset,know_W;
9983         unsigned long lit = 0L;
9984         
9985         result = IC_RESULT(ic);
9986         right  = IC_RIGHT(ic) ;
9987         
9988         FENTRY;
9989         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9990         
9991         /* if they are the same */
9992         if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9993                 return ;
9994         
9995         aopOp(right,ic,FALSE);
9996         aopOp(result,ic,TRUE);
9997         
9998         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9999         
10000         /* if they are the same registers */
10001         if (pic14_sameRegs(AOP(right),AOP(result)))
10002                 goto release;
10003
10004         /* special case: assign from __code */
10005         if (!IS_ITEMP(right)                            /* --> iTemps never reside in __code */
10006                 && IS_SYMOP (right)                     /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
10007                 && !IS_FUNC(OP_SYM_TYPE(right))         /* --> we would want its address instead of the first instruction */
10008                 && !IS_CODEPTR(OP_SYM_TYPE(right))      /* --> get symbols address instread */
10009                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
10010         {
10011           emitpComment ("genAssign from CODESPACE");
10012           genConstPointerGet (right, result, ic);
10013           goto release;
10014         }
10015         
10016         /* just for symmetry reasons... */
10017         if (!IS_ITEMP(result)
10018                 && IS_SYMOP (result)
10019                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
10020         {
10021           assert ( !"cannot write to CODESPACE" );
10022         }
10023
10024         /* if the result is a bit */
10025         if (AOP_TYPE(result) == AOP_CRY) {
10026                 
10027         /* if the right size is a literal then
10028                 we know what the value is */
10029                 if (AOP_TYPE(right) == AOP_LIT) {
10030                         
10031                         emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10032                                 popGet(AOP(result),0));
10033                         
10034                         if (((int) operandLitValue(right))) 
10035                                 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10036                                 AOP(result)->aopu.aop_dir,
10037                                 AOP(result)->aopu.aop_dir);
10038                         else
10039                                 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10040                                 AOP(result)->aopu.aop_dir,
10041                                 AOP(result)->aopu.aop_dir);
10042                         goto release;
10043                 }
10044                 
10045                 /* the right is also a bit variable */
10046                 if (AOP_TYPE(right) == AOP_CRY) {
10047                         emitpcode(POC_BCF,    popGet(AOP(result),0));
10048                         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10049                         emitpcode(POC_BSF,    popGet(AOP(result),0));
10050                         
10051                         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10052                                 AOP(result)->aopu.aop_dir,
10053                                 AOP(result)->aopu.aop_dir);
10054                         pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10055                                 AOP(right)->aopu.aop_dir,
10056                                 AOP(right)->aopu.aop_dir);
10057                         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10058                                 AOP(result)->aopu.aop_dir,
10059                                 AOP(result)->aopu.aop_dir);
10060                         goto release ;
10061                 }
10062                 
10063                 /* we need to or */
10064                 emitpcode(POC_BCF,    popGet(AOP(result),0));
10065                 pic14_toBoolean(right);
10066                 emitSKPZ;
10067                 emitpcode(POC_BSF,    popGet(AOP(result),0));
10068                 //aopPut(AOP(result),"a",0);
10069                 goto release ;
10070         }
10071         
10072         /* bit variables done */
10073         /* general case */
10074         size = AOP_SIZE(result);
10075         offset = 0 ;
10076         if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10077                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10078                 if(aopIdx(AOP(result),0) == 4) {
10079                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10080                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10081                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10082                         goto release;
10083                 } else
10084                         DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10085         }
10086         
10087         know_W=-1;
10088         while (size--) {
10089         
10090                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10091                 if(AOP_TYPE(right) == AOP_LIT) {
10092                         lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
10093                         if(lit&0xff) {
10094                                 if(know_W != (int)(lit&0xff))
10095                                         emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10096                                 know_W = lit&0xff;
10097                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10098                         } else
10099                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10100                         
10101                 } else if (AOP_TYPE(right) == AOP_CRY) {
10102                         emitpcode(POC_CLRF, popGet(AOP(result),offset));
10103                         if(offset == 0) {
10104                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10105                                 emitpcode(POC_INCF, popGet(AOP(result),0));
10106                         }
10107                 } else {
10108                         mov2w_op (right, offset);
10109                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10110                 }
10111                 
10112                 offset++;
10113         }
10114         
10115         
10116 release:
10117         freeAsmop (right,NULL,ic,FALSE);
10118         freeAsmop (result,NULL,ic,TRUE);
10119 }   
10120
10121 /*-----------------------------------------------------------------*/
10122 /* genJumpTab - genrates code for jump table                       */
10123 /*-----------------------------------------------------------------*/
10124 static void genJumpTab (iCode *ic)
10125 {
10126         symbol *jtab;
10127         char *l;
10128         
10129         FENTRY;
10130         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10131         
10132         aopOp(IC_JTCOND(ic),ic,FALSE);
10133         /* get the condition into accumulator */
10134         l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10135         MOVA(l);
10136         /* multiply by three */
10137         pic14_emitcode("add","a,acc");
10138         pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10139         
10140         jtab = newiTempLabel(NULL);
10141         pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10142         pic14_emitcode("jmp","@a+dptr");
10143         pic14_emitcode("","%05d_DS_:",jtab->key+100);
10144         
10145         emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10146         emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10147         emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10148         emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10149         emitSKPNC;
10150         emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10151         emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10152         emitpLabel(jtab->key);
10153         
10154         freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10155         
10156         /* now generate the jump labels */
10157         for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10158         jtab = setNextItem(IC_JTLABELS(ic))) {
10159                 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10160                 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10161                 
10162         }
10163         
10164 }
10165
10166 /*-----------------------------------------------------------------*/
10167 /* genMixedOperation - gen code for operators between mixed types  */
10168 /*-----------------------------------------------------------------*/
10169 /*
10170 TSD - Written for the PIC port - but this unfortunately is buggy.
10171 This routine is good in that it is able to efficiently promote 
10172 types to different (larger) sizes. Unfortunately, the temporary
10173 variables that are optimized out by this routine are sometimes
10174 used in other places. So until I know how to really parse the 
10175 iCode tree, I'm going to not be using this routine :(.
10176 */
10177 static int genMixedOperation (iCode *ic)
10178 {
10179         FENTRY;
10180 #if 0
10181         operand *result = IC_RESULT(ic);
10182         sym_link *ctype = operandType(IC_LEFT(ic));
10183         operand *right = IC_RIGHT(ic);
10184         int ret = 0;
10185         int big,small;
10186         int offset;
10187         
10188         iCode *nextic;
10189         operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10190         
10191         pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10192         
10193         nextic = ic->next;
10194         if(!nextic)
10195                 return 0;
10196         
10197         nextright = IC_RIGHT(nextic);
10198         nextleft  = IC_LEFT(nextic);
10199         nextresult = IC_RESULT(nextic);
10200         
10201         aopOp(right,ic,FALSE);
10202         aopOp(result,ic,FALSE);
10203         aopOp(nextright,  nextic, FALSE);
10204         aopOp(nextleft,   nextic, FALSE);
10205         aopOp(nextresult, nextic, FALSE);
10206         
10207         if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10208                 
10209                 operand *t = right;
10210                 right = nextright;
10211                 nextright = t; 
10212                 
10213                 pic14_emitcode(";remove right +","");
10214                 
10215         } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10216         /*
10217         operand *t = right;
10218         right = nextleft;
10219         nextleft = t; 
10220                 */
10221                 pic14_emitcode(";remove left +","");
10222         } else
10223                 return 0;
10224         
10225         big = AOP_SIZE(nextleft);
10226         small = AOP_SIZE(nextright);
10227         
10228         switch(nextic->op) {
10229                 
10230         case '+':
10231                 pic14_emitcode(";optimize a +","");
10232                 /* if unsigned or not an integral type */
10233                 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10234                         pic14_emitcode(";add a bit to something","");
10235                 } else {
10236                         
10237                         pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10238                         
10239                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10240                                 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10241                                 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10242                         } else
10243                                 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10244                         
10245                         offset = 0;
10246                         while(--big) {
10247                                 
10248                                 offset++;
10249                                 
10250                                 if(--small) {
10251                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10252                                                 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10253                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10254                                         }
10255                                         
10256                                         pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10257                                         emitSKPNC;
10258                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10259                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10260                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10261                                         pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10262                                         pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10263                                         
10264                                 } else {
10265                                         pic14_emitcode("rlf","known_zero,w");
10266                                         
10267                                         /*
10268                                         if right is signed
10269                                         btfsc  right,7
10270                                         addlw ff
10271                                         */
10272                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10273                                                 pic14_emitcode("addwf","%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                                         } else {
10276                                                 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10277                                         }
10278                                 }
10279                         }
10280                         ret = 1;
10281                 }
10282         }
10283         ret = 1;
10284         
10285 release:
10286         freeAsmop(right,NULL,ic,TRUE);
10287         freeAsmop(result,NULL,ic,TRUE);
10288         freeAsmop(nextright,NULL,ic,TRUE);
10289         freeAsmop(nextleft,NULL,ic,TRUE);
10290         if(ret)
10291                 nextic->generated = 1;
10292         
10293         return ret;
10294 #else
10295         return 0;
10296 #endif
10297 }
10298 /*-----------------------------------------------------------------*/
10299 /* genCast - gen code for casting                                  */
10300 /*-----------------------------------------------------------------*/
10301 static void genCast (iCode *ic)
10302 {
10303         operand *result = IC_RESULT(ic);
10304         sym_link *restype = operandType(result);
10305         sym_link *rtype = operandType(IC_RIGHT(ic));
10306         operand *right = IC_RIGHT(ic);
10307         int size, offset ;
10308         
10309         FENTRY;
10310         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10311         /* if they are equivalent then do nothing */
10312         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10313                 return ;
10314         
10315         aopOp(right,ic,FALSE) ;
10316         aopOp(result,ic,FALSE);
10317         
10318         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10319         
10320         /* if the result is a bit */
10321         if (AOP_TYPE(result) == AOP_CRY) {
10322                 assert(!"assigning to bit variables is not supported");
10323         }
10324         
10325         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10326                 int offset = 1;
10327                 size = AOP_SIZE(result);
10328                 
10329                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10330                 
10331                 emitpcode(POC_CLRF,   popGet(AOP(result),0));
10332                 emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10333                 emitpcode(POC_INCF,   popGet(AOP(result),0));
10334                 
10335                 while (size--)
10336                         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
10337                 
10338                 goto release;
10339         }
10340         
10341         if (IS_PTR(restype))
10342         {
10343           operand *result = IC_RESULT(ic);
10344           //operand *left = IC_LEFT(ic);
10345           operand *right = IC_RIGHT(ic);
10346           int tag = 0xff;
10347           
10348           /* copy common part */
10349           int max, size = AOP_SIZE(result);
10350           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10351           DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10352
10353           /* warn if we discard generic opinter tag */
10354           if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10355           {
10356             //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10357           } // if
10358
10359           max = size;
10360           while (size--)
10361           {
10362             mov2w_op (right, size);
10363             movwf (AOP(result), size);
10364           } // while
10365
10366           /* upcast into generic pointer type? */
10367           if (IS_GENPTR(restype)
10368                 && (size < AOP_SIZE(result))
10369                 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10370           {
10371             //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10372             if (IS_PTR(rtype))
10373             {
10374               switch (DCL_TYPE(rtype))
10375               {
10376               case POINTER:     /* __data */
10377               case FPOINTER:    /* __data */
10378                 assert (AOP_SIZE(right) == 2);
10379                 tag = GPTRTAG_DATA;
10380                 break;
10381
10382               case CPOINTER:    /* __code */
10383                 assert (AOP_SIZE(right) == 2);
10384                 tag = GPTRTAG_CODE;
10385                 break;
10386                 
10387               case GPOINTER:    /* unknown destination, __data or __code */
10388                 /* assume __data space (address of immediate) */
10389                 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10390                 if (AOP(right)->code)
10391                   tag = GPTRTAG_CODE;
10392                 else
10393                   tag = GPTRTAG_DATA;
10394                 break;
10395                 
10396               default:
10397                 assert (!"unhandled pointer type");
10398               } // switch
10399             } else {
10400               /* convert other values into pointers to __data space */
10401               tag = GPTRTAG_DATA;
10402             }
10403
10404             assert (AOP_SIZE(result) == 3);
10405             if (tag == 0) {
10406               emitpcode(POC_CLRF, popGet(AOP(result), 2));
10407             } else {
10408               emitpcode(POC_MOVLW, popGetLit(tag));
10409               movwf(AOP(result), 2);
10410             }
10411           } else {
10412             addSign(result, max, 0);
10413           } // if
10414           goto release;
10415         }
10416         
10417         /* if they are the same size : or less */
10418         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10419                 
10420                 /* if they are in the same place */
10421                 if (pic14_sameRegs(AOP(right),AOP(result)))
10422                         goto release;
10423                 
10424                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10425                 if (IS_PTR_CONST(rtype))
10426                         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10427                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10428                         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10429                 
10430                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10431                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10432                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
10433                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10434                         emitpcode(POC_MOVWF, popGet(AOP(result),1));
10435                         if(AOP_SIZE(result) <2)
10436                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10437                         
10438                 } else {
10439                         
10440                         /* if they in different places then copy */
10441                         size = AOP_SIZE(result);
10442                         offset = 0 ;
10443                         while (size--) {
10444                                 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10445                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10446                                 
10447                                 //aopPut(AOP(result),
10448                                 // aopGet(AOP(right),offset,FALSE,FALSE),
10449                                 // offset);
10450                                 
10451                                 offset++;
10452                         }
10453                 }
10454                 goto release;
10455         }
10456         
10457         /* so we now know that the size of destination is greater
10458         than the size of the source.
10459         Now, if the next iCode is an operator then we might be
10460         able to optimize the operation without performing a cast.
10461         */
10462         if(0 && genMixedOperation(ic)) {
10463                 /* XXX: cannot optimize: must copy regs! */
10464                 goto release;
10465         }
10466         
10467         /* we move to result for the size of source */
10468         size = AOP_SIZE(right);
10469         offset = 0 ;
10470         while (size--) {
10471                 emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
10472                 emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
10473                 offset++;
10474         }
10475
10476         addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10477
10478 release:
10479         freeAsmop(right,NULL,ic,TRUE);
10480         freeAsmop(result,NULL,ic,TRUE);
10481         
10482 }
10483
10484 /*-----------------------------------------------------------------*/
10485 /* genDjnz - generate decrement & jump if not zero instrucion      */
10486 /*-----------------------------------------------------------------*/
10487 static int genDjnz (iCode *ic, iCode *ifx)
10488 {
10489         symbol *lbl, *lbl1;
10490         FENTRY;
10491         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10492         
10493         if (!ifx)
10494                 return 0;
10495         
10496                 /* if the if condition has a false label
10497         then we cannot save */
10498         if (IC_FALSE(ifx))
10499                 return 0;
10500         
10501                 /* if the minus is not of the form 
10502         a = a - 1 */
10503         if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10504                 !IS_OP_LITERAL(IC_RIGHT(ic)))
10505                 return 0;
10506         
10507         if (operandLitValue(IC_RIGHT(ic)) != 1)
10508                 return 0;
10509         
10510                 /* if the size of this greater than one then no
10511         saving */
10512         if (getSize(operandType(IC_RESULT(ic))) > 1)
10513                 return 0;
10514         
10515         /* otherwise we can save BIG */
10516         lbl = newiTempLabel(NULL);
10517         lbl1= newiTempLabel(NULL);
10518         
10519         aopOp(IC_RESULT(ic),ic,FALSE);
10520         
10521         if (IS_AOP_PREG(IC_RESULT(ic))) {
10522                 pic14_emitcode("dec","%s",
10523                         aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10524                 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10525                 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10526         } else {  
10527                 
10528                 
10529                 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10530                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10531                 
10532                 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10533                 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10534                 
10535         }
10536         /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10537         /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10538         /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10539         /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10540         
10541         
10542         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10543         ifx->generated = 1;
10544         return 1;
10545 }
10546
10547 /*-----------------------------------------------------------------*/
10548 /* genReceive - generate code for a receive iCode                  */
10549 /*-----------------------------------------------------------------*/
10550 static void genReceive (iCode *ic)
10551 {
10552         FENTRY;
10553         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10554         
10555         if (isOperandInFarSpace(IC_RESULT(ic)) &&
10556                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10557                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10558                 
10559                 int size = getSize(operandType(IC_RESULT(ic)));
10560                 int offset =  fReturnSizePic - size;
10561                 while (size--) {
10562                         pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10563                                 fReturn[fReturnSizePic - offset - 1] : "acc"));
10564                         offset++;
10565                 }
10566                 aopOp(IC_RESULT(ic),ic,FALSE);
10567                 size = AOP_SIZE(IC_RESULT(ic));
10568                 offset = 0;
10569                 while (size--) {
10570                         pic14_emitcode ("pop","acc");
10571                         aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10572                 }
10573                 
10574         } else {
10575                 _G.accInUse++;
10576                 aopOp(IC_RESULT(ic),ic,FALSE);
10577                 _G.accInUse--;
10578                 assignResultValue(IC_RESULT(ic));
10579         }
10580         
10581         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10582 }
10583
10584 /*-----------------------------------------------------------------*/
10585 /* genDummyRead - generate code for dummy read of volatiles        */
10586 /*-----------------------------------------------------------------*/
10587 static void
10588 genDummyRead (iCode * ic)
10589 {
10590         FENTRY;
10591         pic14_emitcode ("; genDummyRead","");
10592         pic14_emitcode ("; not implemented","");
10593         
10594         ic = ic;
10595 }
10596
10597 /*-----------------------------------------------------------------*/
10598 /* genpic14Code - generate code for pic14 based controllers        */
10599 /*-----------------------------------------------------------------*/
10600 /*
10601 * At this point, ralloc.c has gone through the iCode and attempted
10602 * to optimize in a way suitable for a PIC. Now we've got to generate
10603 * PIC instructions that correspond to the iCode.
10604 *
10605 * Once the instructions are generated, we'll pass through both the
10606 * peep hole optimizer and the pCode optimizer.
10607 *-----------------------------------------------------------------*/
10608
10609 void genpic14Code (iCode *lic)
10610 {
10611         iCode *ic;
10612         int cln = 0;
10613         const char *cline;
10614         
10615         FENTRY;
10616         lineHead = lineCurr = NULL;
10617         
10618         pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10619         addpBlock(pb);
10620         
10621         /* if debug information required */
10622         if (options.debug && currFunc) { 
10623                 if (currFunc) {
10624                         debugFile->writeFunction (currFunc, lic);
10625                 }
10626         }
10627         
10628         
10629         for (ic = lic ; ic ; ic = ic->next ) {
10630                 
10631                 //DEBUGpic14_emitcode(";ic","");
10632                 //fprintf (stderr, "in ic loop\n");
10633                 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10634                 //ic->lineno, printCLine(ic->filename, ic->lineno));
10635                 
10636                 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10637                   cln = ic->lineno;
10638                   //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10639                   cline = printCLine (ic->filename, ic->lineno);
10640                   if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10641                   addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10642                   //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10643                 }
10644                 
10645                 if (options.iCodeInAsm) {
10646                   emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10647                 }
10648                 /* if the result is marked as
10649                 spilt and rematerializable or code for
10650                 this has already been generated then
10651                 do nothing */
10652                 if (resultRemat(ic) || ic->generated ) 
10653                         continue ;
10654                 
10655                 /* depending on the operation */
10656                 switch (ic->op) {
10657                 case '!' :
10658                         genNot(ic);
10659                         break;
10660                         
10661                 case '~' :
10662                         genCpl(ic);
10663                         break;
10664                         
10665                 case UNARYMINUS:
10666                         genUminus (ic);
10667                         break;
10668                         
10669                 case IPUSH:
10670                         genIpush (ic);
10671                         break;
10672                         
10673                 case IPOP:
10674                         /* IPOP happens only when trying to restore a 
10675                         spilt live range, if there is an ifx statement
10676                         following this pop then the if statement might
10677                         be using some of the registers being popped which
10678                         would destory the contents of the register so
10679                         we need to check for this condition and handle it */
10680                         if (ic->next            && 
10681                                 ic->next->op == IFX &&
10682                                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10683                                 genIfx (ic->next,ic);
10684                         else
10685                                 genIpop (ic);
10686                         break; 
10687                         
10688                 case CALL:
10689                         genCall (ic);
10690                         break;
10691                         
10692                 case PCALL:
10693                         genPcall (ic);
10694                         break;
10695                         
10696                 case FUNCTION:
10697                         genFunction (ic);
10698                         break;
10699                         
10700                 case ENDFUNCTION:
10701                         genEndFunction (ic);
10702                         break;
10703                         
10704                 case RETURN:
10705                         genRet (ic);
10706                         break;
10707                         
10708                 case LABEL:
10709                         genLabel (ic);
10710                         break;
10711                         
10712                 case GOTO:
10713                         genGoto (ic);
10714                         break;
10715                         
10716                 case '+' :
10717                         genPlus (ic) ;
10718                         break;
10719                         
10720                 case '-' :
10721                         if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10722                                 genMinus (ic);
10723                         break;
10724                         
10725                 case '*' :
10726                         genMult (ic);
10727                         break;
10728                         
10729                 case '/' :
10730                         genDiv (ic) ;
10731                         break;
10732                         
10733                 case '%' :
10734                         genMod (ic);
10735                         break;
10736                         
10737                 case '>' :
10738                         genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));         
10739                         break;
10740                         
10741                 case '<' :
10742                         genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10743                         break;
10744                         
10745                 case LE_OP:
10746                 case GE_OP:
10747                 case NE_OP:
10748                         
10749                         /* note these two are xlated by algebraic equivalence
10750                         during parsing SDCC.y */
10751                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10752                                 "got '>=' or '<=' shouldn't have come here");
10753                         break;  
10754                         
10755                 case EQ_OP:
10756                         genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10757                         break;      
10758                         
10759                 case AND_OP:
10760                         genAndOp (ic);
10761                         break;
10762                         
10763                 case OR_OP:
10764                         genOrOp (ic);
10765                         break;
10766                         
10767                 case '^' :
10768                         genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10769                         break;
10770                         
10771                 case '|' :
10772                         genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10773                         break;
10774                         
10775                 case BITWISEAND:
10776                         genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10777                         break;
10778                         
10779                 case INLINEASM:
10780                         genInline (ic);
10781                         break;
10782                         
10783                 case RRC:
10784                         genRRC (ic);
10785                         break;
10786                         
10787                 case RLC:
10788                         genRLC (ic);
10789                         break;
10790                         
10791                 case GETHBIT:
10792                         genGetHbit (ic);
10793                         break;
10794                         
10795                 case LEFT_OP:
10796                         genLeftShift (ic);
10797                         break;
10798                         
10799                 case RIGHT_OP:
10800                         genRightShift (ic);
10801                         break;
10802                         
10803                 case GET_VALUE_AT_ADDRESS:
10804                         genPointerGet(ic);
10805                         break;
10806                         
10807                 case '=' :
10808                         if (POINTER_SET(ic))
10809                                 genPointerSet(ic);
10810                         else
10811                                 genAssign(ic);
10812                         break;
10813                         
10814                 case IFX:
10815                         genIfx (ic,NULL);
10816                         break;
10817                         
10818                 case ADDRESS_OF:
10819                         genAddrOf (ic);
10820                         break;
10821                         
10822                 case JUMPTABLE:
10823                         genJumpTab (ic);
10824                         break;
10825                         
10826                 case CAST:
10827                         genCast (ic);
10828                         break;
10829                         
10830                 case RECEIVE:
10831                         genReceive(ic);
10832                         break;
10833                         
10834                 case SEND:
10835                         addSet(&_G.sendSet,ic);
10836                         break;
10837                         
10838                 case DUMMY_READ_VOLATILE:
10839                         genDummyRead (ic);
10840                         break;
10841                         
10842                 default :
10843                         fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10844                         ic = ic;
10845                         break;
10846                 }
10847         }
10848
10849         
10850         /* now we are ready to call the
10851         peep hole optimizer */
10852         if (!options.nopeep) {
10853                 peepHole (&lineHead);
10854         }
10855         /* now do the actual printing */
10856         printLine (lineHead,codeOutFile);
10857         
10858 #ifdef PCODE_DEBUG
10859         DFPRINTF((stderr,"printing pBlock\n\n"));
10860         printpBlock(stdout,pb);
10861 #endif
10862         
10863         return;
10864 }
10865
10866 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10867  * (meaning: representing its own address) or not (referencing its contents).
10868  * This can only be decided based on the operand's type. */
10869 int
10870 aop_isLitLike (asmop *aop)
10871 {
10872   assert (aop);
10873   if (aop->type == AOP_LIT) return 1;
10874 if (aop->type == AOP_IMMD) return 1;
10875   if ((aop->type == AOP_PCODE) &&
10876                 ((aop->aopu.pcop->type == PO_LITERAL)))
10877   {
10878     /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10879      * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10880     return 1;
10881   }
10882   return 0;
10883 }
10884
10885 int
10886 op_isLitLike (operand *op)
10887 {
10888   assert (op);
10889   if (aop_isLitLike (AOP(op))) return 1;
10890   if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10891   if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;
10892   return 0;
10893 }