* src/pic/gen.c: handle FPOINTERS like POINTERS everywhere
[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@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
46 /* When changing these, you must also update the assembler template
47  * in device/lib/libsdcc/macros.inc */
48 #define GPTRTAG_DATA    0x00
49 #define GPTRTAG_CODE    0x80
50
51 /* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
52 #define PIC_IS_DATA_PTR(x)      (IS_DATA_PTR(x) || IS_FARPTR(x))
53 #define PIC_IS_FARPTR(x)        (PIC_IS_DATA_PTR(x))
54
55 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
56 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
57 void genMult8X8_8 (operand *, operand *,operand *);
58 extern void printpBlock(FILE *of, pBlock *pb);
59
60 static int labelOffset=0;
61 extern int debug_verbose;
62 //static int optimized_for_speed = 0;
63
64 /* max_key keeps track of the largest label number used in 
65 a function. This is then used to adjust the label offset
66 for the next function.
67 */
68 static int max_key=0;
69 static int GpsuedoStkPtr=0;
70
71 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
72 extern char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
73 unsigned int pic14aopLiteral (value *val, int offset);
74 const char *AopType(short type);
75
76 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
77
78 /* this is the down and dirty file with all kinds of 
79 kludgy & hacky stuff. This is what it is all about
80 CODE GENERATION for a specific MCU . some of the
81 routines may be reusable, will have to see */
82
83 static char *zero = "#0x00";
84 static char *one  = "#0x01";
85 static char *spname = "sp";
86
87 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
88 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
89 static char **fReturn = fReturnpic14;
90
91 //static char *accUse[] = {"a","b"};
92
93 //static short rbank = -1;
94
95 static struct {
96         short r0Pushed;
97         short r1Pushed;
98         short accInUse;
99         short inLine;
100         short debugLine;
101         short nRegsSaved;
102         set *sendSet;
103 } _G;
104
105 /* Resolved ifx structure. This structure stores information
106 about an iCode ifx that makes it easier to generate code.
107 */
108 typedef struct resolvedIfx {
109         symbol *lbl;     /* pointer to a label */
110         int condition;   /* true or false ifx */
111         int generated;   /* set true when the code associated with the ifx
112                           * is generated */
113 } resolvedIfx;
114
115 extern int pic14_ptrRegReq ;
116 extern int pic14_nRegs;
117 extern FILE *codeOutFile;
118 static void saverbank (int, iCode *,bool);
119
120 static lineNode *lineHead = NULL;
121 static lineNode *lineCurr = NULL;
122
123 #if 0
124 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
125 0xE0, 0xC0, 0x80, 0x00};
126 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
127 0x07, 0x03, 0x01, 0x00};
128 #endif
129
130 static  pBlock *pb;
131
132 /*-----------------------------------------------------------------*/
133 /*      my_powof2(n) - If `n' is an integaer power of 2, then the          */
134 /*                                 exponent of 2 is returned, otherwise -1 is      */
135 /*                                 returned.                                                                       */
136 /* note that this is similar to the function `powof2' in SDCCsymt  */
137 /* if(n == 2^y)                                                                                                    */
138 /*       return y;                                                                                                         */
139 /* return -1;                                                                                                      */
140 /*-----------------------------------------------------------------*/
141 static int my_powof2 (unsigned long num)
142 {
143         if(num) {
144                 if( (num & (num-1)) == 0) {
145                         int nshifts = -1;
146                         while(num) {
147                                 num>>=1;
148                                 nshifts++;
149                         }
150                         return nshifts;
151                 }
152         }
153         
154         return -1;
155 }
156
157 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
158 {
159         
160         DEBUGpic14_emitcode ("; ","line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
161                 line_no,
162                 ((result) ? AopType(AOP_TYPE(result)) : "-"),
163                 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
164                 ((result) ? AOP_SIZE(result) : 0),
165                 ((left)   ? AopType(AOP_TYPE(left)) : "-"),
166                 ((left)   ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
167                 ((left)   ? AOP_SIZE(left) : 0),
168                 ((right)  ? AopType(AOP_TYPE(right)) : "-"),
169                 ((right)  ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
170                 ((right)  ? AOP_SIZE(right) : 0));
171         
172 }
173
174 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
175 {
176         
177         DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
178                 line_no,
179                 ((result) ? AopType(AOP_TYPE(result)) : "-"),
180                 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
181                 ((left)   ? AopType(AOP_TYPE(left)) : "-"),
182                 ((left)   ? (SPEC_USIGN(operandType(left))       ? 'u' : 's') : '-'),
183                 ((right)  ? AopType(AOP_TYPE(right)) : "-"),
184                 ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
185         
186 }
187
188 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
189 {
190         va_list ap;
191         char lb[INITIAL_INLINEASM];  
192         unsigned char *lbp = lb;
193         
194         if(!debug_verbose && !options.debug)
195                 return;
196         
197         va_start(ap,fmt);   
198         
199         if (inst && *inst) {
200                 if (fmt && *fmt)
201                         sprintf(lb,"%s\t",inst);
202                 else
203                         sprintf(lb,"%s",inst);
204                 vsprintf(lb+(strlen(lb)),fmt,ap);
205         }  else
206                 vsprintf(lb,fmt,ap);
207         
208         while (isspace(*lbp)) lbp++;
209         
210         if (lbp && *lbp) 
211                 lineCurr = (lineCurr ?
212                 connectLine(lineCurr,newLineNode(lb)) :
213         (lineHead = newLineNode(lb)));
214         lineCurr->isInline = _G.inLine;
215         lineCurr->isDebug  = _G.debugLine;
216         
217         addpCode2pBlock(pb,newpCodeCharP(lb));
218         
219         va_end(ap);
220 }
221
222 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
223 {
224 #if defined (HAVE_VSNPRINTF)
225   vsnprintf (buf, size, fmt, ap);
226 #elif defined (HAVE_VSPRINTF)
227   vsprintf (buf, size, fmt, ap);
228   if (strlen (buf) >= size)
229   {
230     fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
231   }
232 #elif defined (HAVE_SNPRINTF)
233   snprintf (buf, size, "vs(n)printf required");
234 #elif defined (HAVE_SRINTF)
235   sprintf (buf, "vs(n)printf required");
236   if (strlen (buf) >= size)
237   {
238     fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
239   }
240 #else
241   assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
242 #endif
243 }
244
245 void emitpComment (const char *fmt, ...)
246 {
247   va_list va;
248   char buffer[4096];
249   
250   va_start (va, fmt);
251   if (pb) {
252     Safe_vsnprintf (buffer, 4096, fmt, va);
253     //fprintf (stderr, "%s\n" ,buffer);
254     addpCode2pBlock (pb, newpCodeCharP (buffer));
255 #if 0
256   } else {
257     Safe_vsnprintf (buffer, 4096, fmt, va);
258     fprintf (stderr, "No current pBlock -- discarding comment [%s]\n", buffer);
259 #endif
260   }
261   va_end (va);
262 }
263
264 void emitpLabel(int key)
265 {
266         addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
267 }
268
269 /* gen.h defines a macro emitpcode that should be used to call emitpcode
270  * as this allows for easy debugging (ever asked the question: where was
271  * this instruction geenrated? Here is the answer... */
272 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
273 {
274         if(pcop)
275                 addpCode2pBlock(pb,newpCode(poc,pcop));
276         else
277                 DEBUGpic14_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
278 }
279
280 void emitpcodeNULLop(PIC_OPCODE poc)
281 {
282         
283         addpCode2pBlock(pb,newpCode(poc,NULL));
284         
285 }
286
287
288 /*-----------------------------------------------------------------*/
289 /* pic14_emitcode - writes the code into a file : for now it is simple    */
290 /*-----------------------------------------------------------------*/
291 void pic14_emitcode (char *inst,char *fmt, ...)
292 {
293         va_list ap;
294         char lb[INITIAL_INLINEASM];  
295         unsigned char *lbp = lb;
296         
297         va_start(ap,fmt);   
298         
299         if (inst && *inst) {
300                 if (fmt && *fmt)
301                         sprintf(lb,"%s\t",inst);
302                 else
303                         sprintf(lb,"%s",inst);
304                 vsprintf(lb+(strlen(lb)),fmt,ap);
305         }  else
306                 vsprintf(lb,fmt,ap);
307         
308         while (isspace(*lbp)) lbp++;
309         
310         if (lbp && *lbp) 
311                 lineCurr = (lineCurr ?
312                 connectLine(lineCurr,newLineNode(lb)) :
313         (lineHead = newLineNode(lb)));
314         lineCurr->isInline = _G.inLine;
315         lineCurr->isDebug  = _G.debugLine;
316         
317         if(debug_verbose)
318                 addpCode2pBlock(pb,newpCodeCharP(lb));
319         
320         va_end(ap);
321 }
322
323 /*-----------------------------------------------------------------*/
324 /* pic14_emitDebuggerSymbol - associate the current code location  */
325 /*       with a debugger symbol                                                                            */
326 /*-----------------------------------------------------------------*/
327 void
328 pic14_emitDebuggerSymbol (char * debugSym)
329 {
330         _G.debugLine = 1;
331         pic14_emitcode ("", ";%s ==.", debugSym);
332         _G.debugLine = 0;
333 }
334
335 #if 0
336 /*-----------------------------------------------------------------*/
337 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
338 /*-----------------------------------------------------------------*/
339 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
340 {
341         bool r0iu = FALSE , r1iu = FALSE;
342         bool r0ou = FALSE , r1ou = FALSE;
343         
344         /* the logic: if r0 & r1 used in the instruction
345         then we are in trouble otherwise */
346         
347         /* first check if r0 & r1 are used by this
348         instruction, in which case we are in trouble */
349         if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
350                 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
351         {
352                 goto endOfWorld;          
353         }
354         
355         r0ou = bitVectBitValue(ic->rMask,R0_IDX);
356         r1ou = bitVectBitValue(ic->rMask,R1_IDX);
357         
358         /* if no usage of r0 then return it */
359         if (!r0iu && !r0ou) {
360                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
361                 (*aopp)->type = AOP_R0;
362                 
363                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
364         }
365         
366         /* if no usage of r1 then return it */
367         if (!r1iu && !r1ou) {
368                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
369                 (*aopp)->type = AOP_R1;
370                 
371                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
372         }    
373         
374         /* now we know they both have usage */
375         /* if r0 not used in this instruction */
376         if (!r0iu) {
377                 /* push it if not already pushed */
378                 if (!_G.r0Pushed) {
379                         //pic14_emitcode ("push","%s",
380                         //                pic14_regWithIdx(R0_IDX)->dname);
381                         _G.r0Pushed++ ;
382                 }
383                 
384                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
385                 (*aopp)->type = AOP_R0;
386                 
387                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
388         }
389         
390         /* if r1 not used then */
391         
392         if (!r1iu) {
393                 /* push it if not already pushed */
394                 if (!_G.r1Pushed) {
395                         //pic14_emitcode ("push","%s",
396                         //                pic14_regWithIdx(R1_IDX)->dname);
397                         _G.r1Pushed++ ;
398                 }
399                 
400                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
401                 (*aopp)->type = AOP_R1;
402                 return pic14_regWithIdx(R1_IDX);
403         }
404         
405 endOfWorld :
406         /* I said end of world but not quite end of world yet */
407         /* if this is a result then we can push it on the stack*/
408         if (result) {
409                 (*aopp)->type = AOP_STK;        
410                 return NULL;
411         }
412         
413         /* other wise this is true end of the world */
414         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
415                 "getFreePtr should never reach here");
416         exit(0);
417 }
418 #endif
419
420 /*-----------------------------------------------------------------*/
421 /* newAsmop - creates a new asmOp                                                                  */
422 /*-----------------------------------------------------------------*/
423 asmop *newAsmop (short type)
424 {
425         asmop *aop;
426         
427         aop = Safe_calloc(1,sizeof(asmop));
428         aop->type = type;
429         return aop;
430 }
431
432 static void genSetDPTR(int n)
433 {
434         if (!n)
435         {
436                 pic14_emitcode(";", "Select standard DPTR");
437                 pic14_emitcode("mov", "dps, #0x00");
438         }
439         else
440         {
441                 pic14_emitcode(";", "Select alternate DPTR");
442                 pic14_emitcode("mov", "dps, #0x01");
443         }
444 }
445
446 /*-----------------------------------------------------------------*/
447 /* resolveIfx - converts an iCode ifx into a form more useful for  */
448 /*                              generating code                                                                    */
449 /*-----------------------------------------------------------------*/
450 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
451 {
452         if(!resIfx) 
453                 return;
454         
455         //  DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
456         
457         resIfx->condition = 1;  /* assume that the ifx is true */
458         resIfx->generated = 0;  /* indicate that the ifx has not been used */
459         
460         if(!ifx) {
461                 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL);      / * oops, there is no ifx. so create a label */
462                                                                                         /*
463                                                                                         DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
464                                                                                         __FUNCTION__,__LINE__,resIfx->lbl->key);
465                 */
466         } else {
467                 if(IC_TRUE(ifx)) {
468                         resIfx->lbl = IC_TRUE(ifx);
469                 } else {
470                         resIfx->lbl = IC_FALSE(ifx);
471                         resIfx->condition = 0;
472                 }
473                 /*
474                 if(IC_TRUE(ifx)) 
475                 DEBUGpic14_emitcode("; ***","ifx true is non-null");
476                 if(IC_FALSE(ifx)) 
477                 DEBUGpic14_emitcode("; ***","ifx false is non-null");
478                 */
479         }
480         
481         //  DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
482         
483 }
484 /*-----------------------------------------------------------------*/
485 /* pointerCode - returns the code for a pointer type                       */
486 /*-----------------------------------------------------------------*/
487 #if 0
488 static int pointerCode (sym_link *etype)
489 {
490         
491         return PTR_TYPE(SPEC_OCLS(etype));
492         
493 }
494 #endif
495
496 /*-----------------------------------------------------------------*/
497 /* aopForSym - for a true symbol                                                                   */
498 /*-----------------------------------------------------------------*/
499 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
500 {
501         asmop *aop;
502         memmap *space= SPEC_OCLS(sym->etype);
503         
504         DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
505         /* if already has one */
506         if (sym->aop)
507                 return sym->aop;
508         
509 #if 0
510         /* assign depending on the storage class */
511         /* if it is on the stack or indirectly addressable */
512         /* space we need to assign either r0 or r1 to it         */    
513         if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
514                 sym->aop = aop = newAsmop(0);
515                 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
516                 aop->size = getSize(sym->type);
517                 
518                 /* now assign the address of the variable to 
519                 the pointer register */
520                 if (aop->type != AOP_STK) {
521                         
522                         if (sym->onStack) {
523                                 if ( _G.accInUse )
524                                         pic14_emitcode("push","acc");
525                                 
526                                 pic14_emitcode("mov","a,_bp");
527                                 pic14_emitcode("add","a,#0x%02x",
528                                         ((sym->stack < 0) ?
529                                         ((char)(sym->stack - _G.nRegsSaved )) :
530                                 ((char)sym->stack)) & 0xff);
531                                 pic14_emitcode("mov","%s,a",
532                                         aop->aopu.aop_ptr->name);
533                                 
534                                 if ( _G.accInUse )
535                                         pic14_emitcode("pop","acc");
536                         } else
537                                 pic14_emitcode("mov","%s,#%s",
538                                 aop->aopu.aop_ptr->name,
539                                 sym->rname);
540                         aop->paged = space->paged;
541                 } else
542                         aop->aopu.aop_stk = sym->stack;
543                 return aop;
544         }
545         
546         if (sym->onStack && options.stack10bit)
547         {
548                 /* It's on the 10 bit stack, which is located in
549                 * far data space.
550                 */
551                 
552                 //DEBUGpic14_emitcode(";","%d",__LINE__);
553                 
554                 if ( _G.accInUse )
555                         pic14_emitcode("push","acc");
556                 
557                 pic14_emitcode("mov","a,_bp");
558                 pic14_emitcode("add","a,#0x%02x",
559                         ((sym->stack < 0) ?
560                         ((char)(sym->stack - _G.nRegsSaved )) :
561                 ((char)sym->stack)) & 0xff);
562                 
563                 genSetDPTR(1);
564                 pic14_emitcode ("mov","dpx1,#0x40");
565                 pic14_emitcode ("mov","dph1,#0x00");
566                 pic14_emitcode ("mov","dpl1, a");
567                 genSetDPTR(0);
568                 
569                 if ( _G.accInUse )
570                         pic14_emitcode("pop","acc");
571                 
572                 sym->aop = aop = newAsmop(AOP_DPTR2);
573                 aop->size = getSize(sym->type); 
574                 return aop;
575         }
576 #endif
577
578         //DEBUGpic14_emitcode(";","%d",__LINE__);
579         /* if in bit space */
580         if (IN_BITSPACE(space)) {
581                 sym->aop = aop = newAsmop (AOP_CRY);
582                 aop->aopu.aop_dir = sym->rname ;
583                 aop->size = getSize(sym->type);
584                 //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
585                 return aop;
586         }
587         /* if it is in direct space */
588         if (IN_DIRSPACE(space)) {
589                 sym->aop = aop = newAsmop (AOP_DIR);
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         
596         /* special case for a function */
597         if (IS_FUNC(sym->type)) {   
598                 
599                 sym->aop = aop = newAsmop(AOP_PCODE);
600                 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
601                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
602                 PCOI(aop->aopu.pcop)->_function = 1;
603                 PCOI(aop->aopu.pcop)->index = 0;
604                 aop->size = FPTRSIZE; 
605                 /*
606                 sym->aop = aop = newAsmop(AOP_IMMD);    
607                 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
608                 strcpy(aop->aopu.aop_immd,sym->rname);
609                 aop->size = FPTRSIZE; 
610                 */
611                 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
612                 return aop;
613         }
614         
615         if (IS_ARRAY(sym->type)) {
616                 sym->aop = aop = newAsmop(AOP_PCODE);
617                 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
618                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
619                 PCOI(aop->aopu.pcop)->_function = 0;
620                 PCOI(aop->aopu.pcop)->index = 0;
621                 aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
622                 
623                 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
624                 return aop;
625         }
626         
627         /* only remaining is far space */
628         /* in which case DPTR gets the address */
629         sym->aop = aop = newAsmop(AOP_PCODE);
630         
631         aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
632         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
633         PCOI(aop->aopu.pcop)->index = 0;
634         
635         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
636                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
637         
638         allocDirReg (IC_LEFT(ic));
639         
640         aop->size = FPTRSIZE;
641         /*
642         DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
643         sym->aop = aop = newAsmop(AOP_DPTR);
644         pic14_emitcode ("mov","dptr,#%s", sym->rname);
645         aop->size = getSize(sym->type);
646         
647           DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
648         */
649         
650         /* if it is in code space */
651         if (IN_CODESPACE(space))
652                 aop->code = 1;
653         
654         return aop;       
655 }
656
657 /*-----------------------------------------------------------------*/
658 /* aopForRemat - rematerialzes an object                                                   */
659 /*-----------------------------------------------------------------*/
660 static asmop *aopForRemat (operand *op) // x symbol *sym)
661 {
662         symbol *sym = OP_SYMBOL(op);
663         iCode *ic = NULL;
664         asmop *aop = newAsmop(AOP_PCODE);
665         int val = 0;
666         int offset = 0;
667         
668         ic = sym->rematiCode;
669
670         DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
671         if(IS_OP_POINTER(op)) {
672                 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
673         }
674         for (;;) {
675                 if (ic->op == '+') {
676                         val += (int) operandLitValue(IC_RIGHT(ic));
677                 } else if (ic->op == '-') {
678                         val -= (int) operandLitValue(IC_RIGHT(ic));
679                 } else
680                         break;
681                 
682                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
683         }
684         
685         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
686         aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
687         PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
688         PCOI(aop->aopu.pcop)->index = val;
689         
690         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
691                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
692                 val, IS_PTR_CONST(operandType(op)));
693         
694         //      DEBUGpic14_emitcode(";","aop type  %s",AopType(AOP_TYPE(IC_LEFT(ic))));
695         
696         allocDirReg (IC_LEFT(ic));
697         
698         return aop;              
699 }
700
701 int aopIdx (asmop *aop, int offset)
702 {
703         if(!aop)
704                 return -1;
705         
706         if(aop->type !=  AOP_REG)
707                 return -2;
708         
709         return aop->aopu.aop_reg[offset]->rIdx;
710         
711 }
712 /*-----------------------------------------------------------------*/
713 /* regsInCommon - two operands have some registers in common       */
714 /*-----------------------------------------------------------------*/
715 static bool regsInCommon (operand *op1, operand *op2)
716 {
717         symbol *sym1, *sym2;
718         int i;
719         
720         /* if they have registers in common */
721         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
722                 return FALSE ;
723         
724         sym1 = OP_SYMBOL(op1);
725         sym2 = OP_SYMBOL(op2);
726         
727         if (sym1->nRegs == 0 || sym2->nRegs == 0)
728                 return FALSE ;
729         
730         for (i = 0 ; i < sym1->nRegs ; i++) {
731                 int j;
732                 if (!sym1->regs[i])
733                         continue ;
734                 
735                 for (j = 0 ; j < sym2->nRegs ;j++ ) {
736                         if (!sym2->regs[j])
737                                 continue ;
738                         
739                         if (sym2->regs[j] == sym1->regs[i])
740                                 return TRUE ;
741                 }
742         }
743         
744         return FALSE ;
745 }
746
747 /*-----------------------------------------------------------------*/
748 /* operandsEqu - equivalent                                                                        */
749 /*-----------------------------------------------------------------*/
750 static bool operandsEqu ( operand *op1, operand *op2)
751 {
752         symbol *sym1, *sym2;
753         
754         /* if they not symbols */
755         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
756                 return FALSE;
757         
758         sym1 = OP_SYMBOL(op1);
759         sym2 = OP_SYMBOL(op2);
760         
761         /* if both are itemps & one is spilt
762         and the other is not then false */
763         if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
764                 sym1->isspilt != sym2->isspilt )
765                 return FALSE ;
766         
767         /* if they are the same */
768         if (sym1 == sym2)
769                 return TRUE ;
770         
771         if (sym1->rname[0] && sym2->rname[0]
772                 && strcmp (sym1->rname, sym2->rname) == 0)
773                 return TRUE;
774         
775         
776         /* if left is a tmp & right is not */
777         if (IS_ITEMP(op1)  && 
778                 !IS_ITEMP(op2) &&
779                 sym1->isspilt  &&
780                 (sym1->usl.spillLoc == sym2))
781                 return TRUE;
782         
783         if (IS_ITEMP(op2)  && 
784                 !IS_ITEMP(op1) &&
785                 sym2->isspilt  &&
786                 sym1->level > 0 &&
787                 (sym2->usl.spillLoc == sym1))
788                 return TRUE ;
789         
790         return FALSE ;
791 }
792
793 /*-----------------------------------------------------------------*/
794 /* pic14_sameRegs - two asmops have the same registers             */
795 /*-----------------------------------------------------------------*/
796 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
797 {
798         int i;
799         
800         if (aop1 == aop2)
801                 return TRUE ;
802         
803         if (aop1->type != AOP_REG ||
804                 aop2->type != AOP_REG )
805                 return FALSE ;
806         
807         if (aop1->size != aop2->size )
808                 return FALSE ;
809         
810         for (i = 0 ; i < aop1->size ; i++ )
811                 if (aop1->aopu.aop_reg[i] !=
812                         aop2->aopu.aop_reg[i] )
813                         return FALSE ;
814                 
815                 return TRUE ;
816 }
817
818 /*-----------------------------------------------------------------*/
819 /* aopOp - allocates an asmop for an operand  :                    */
820 /*-----------------------------------------------------------------*/
821 void aopOp (operand *op, iCode *ic, bool result)
822 {
823         asmop *aop;
824         symbol *sym;
825         int i;
826         
827         if (!op)
828                 return ;
829         
830         /* if this a literal */
831         if (IS_OP_LITERAL(op)) {
832                 op->aop = aop = newAsmop(AOP_LIT);
833                 aop->aopu.aop_lit = op->operand.valOperand;
834                 aop->size = getSize(operandType(op));
835                 return;
836         }
837         
838         {
839                 sym_link *type = operandType(op);
840                 if(IS_PTR_CONST(type))
841                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
842         }
843         
844         /* if already has a asmop then continue */
845         if (op->aop)
846                 return ;
847         
848         /* if the underlying symbol has a aop */
849         if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
850                 DEBUGpic14_emitcode(";","%d",__LINE__);
851                 op->aop = OP_SYMBOL(op)->aop;
852                 return;
853         }
854         
855         /* if this is a true symbol */
856         if (IS_TRUE_SYMOP(op)) {          
857                 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
858                 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
859                 return ;
860         }
861         
862         /* this is a temporary : this has
863         only four choices :
864         a) register
865         b) spillocation
866         c) rematerialize 
867         d) conditional   
868         e) can be a return use only */
869         
870         sym = OP_SYMBOL(op);
871         
872         
873         /* if the type is a conditional */
874         if (sym->regType == REG_CND) {
875                 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
876                 aop->size = 0;
877                 return;
878         }
879         
880         /* if it is spilt then two situations
881         a) is rematerialize 
882         b) has a spill location */
883         if (sym->isspilt || sym->nRegs == 0) {
884                 
885                 DEBUGpic14_emitcode(";","%d",__LINE__);
886                 /* rematerialize it NOW */
887                 if (sym->remat) {
888                         
889                         sym->aop = op->aop = aop = aopForRemat (op);
890                         aop->size = getSize(sym->type);
891                         //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
892                         return;
893                 }
894                 
895 #if 0
896                 /* WREG is not usable as an ordinary operand with PIC architecture,
897                  * one might introduce a scratch register that can be used to make
898                  * WREG accesible as an operand... disable WREG for now */
899                 if (sym->accuse) {
900                         int i;
901                         aop = op->aop = sym->aop = newAsmop(AOP_ACC);
902                         aop->size = getSize(sym->type);
903                         for ( i = 0 ; i < 2 ; i++ )
904                                 aop->aopu.aop_str[i] = accUse[i];
905                         DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
906                         return;  
907                 }
908 #endif
909                 
910                 if (sym->ruonly ) {
911                         if(sym->isptr) {        // && sym->uptr 
912                                 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
913                                 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
914                                 
915                                 //PCOI(aop->aopu.pcop)->_const = 0;
916                                 //PCOI(aop->aopu.pcop)->index = 0;
917                                 /*
918                                 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
919                                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
920                                 */
921                                 //allocDirReg (IC_LEFT(ic));
922                                 
923                                 aop->size = getSize(sym->type);
924                                 DEBUGpic14_emitcode(";","%d",__LINE__);
925                                 return;
926                                 
927                         } else {
928                                 
929                                 unsigned i;
930                                 
931                                 aop = op->aop = sym->aop = newAsmop(AOP_STR);
932                                 aop->size = getSize(sym->type);
933                                 for ( i = 0 ; i < fReturnSizePic ; i++ )
934                                         aop->aopu.aop_str[i] = fReturn[i];
935                                 
936                                 DEBUGpic14_emitcode(";","%d",__LINE__);
937                                 return;
938                         }
939                 }
940                 
941                 /* else spill location  */
942                 if (sym->usl.spillLoc)
943                 {
944                         if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
945                         {
946                                 /* force a new aop if sizes differ */
947                                 sym->usl.spillLoc->aop = NULL;
948                         }
949                         DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
950                                 __FUNCTION__,__LINE__,
951                                 sym->usl.spillLoc->rname,
952                                 sym->rname, sym->usl.spillLoc->offset);
953                 
954                         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
955                         //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
956                         aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
957                                 getSize(sym->type), 
958                                 sym->usl.spillLoc->offset);
959                         aop->size = getSize(sym->type);
960                 
961                         return;
962                 }
963         }
964         
965         {
966                 sym_link *type = operandType(op);
967                 if(IS_PTR_CONST(type)) 
968                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
969         }
970         
971         /* must be in a register */
972         DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
973         sym->aop = op->aop = aop = newAsmop(AOP_REG);
974         aop->size = sym->nRegs;
975         for ( i = 0 ; i < sym->nRegs ;i++)
976                 aop->aopu.aop_reg[i] = sym->regs[i];
977 }
978
979 /*-----------------------------------------------------------------*/
980 /* freeAsmop - free up the asmop given to an operand                       */
981 /*----------------------------------------------------------------*/
982 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
983 {       
984         asmop *aop ;
985         
986         if (!op)
987                 aop = aaop;
988         else 
989                 aop = op->aop;
990         
991         if (!aop)
992                 return ;
993         
994         if (aop->freed)
995                 goto dealloc; 
996         
997         aop->freed = 1;
998         
999         /* depending on the asmop type only three cases need work AOP_RO
1000         , AOP_R1 && AOP_STK */
1001 #if 0
1002         switch (aop->type) {
1003         case AOP_R0 :
1004                 if (_G.r0Pushed ) {
1005                         if (pop) {
1006                                 pic14_emitcode ("pop","ar0");     
1007                                 _G.r0Pushed--;
1008                         }
1009                 }
1010                 bitVectUnSetBit(ic->rUsed,R0_IDX);
1011                 break;
1012                 
1013         case AOP_R1 :
1014                 if (_G.r1Pushed ) {
1015                         if (pop) {
1016                                 pic14_emitcode ("pop","ar1");
1017                                 _G.r1Pushed--;
1018                         }
1019                 }
1020                 bitVectUnSetBit(ic->rUsed,R1_IDX);                      
1021                 break;
1022                 
1023         case AOP_STK :
1024                 {
1025                         int sz = aop->size;      
1026                         int stk = aop->aopu.aop_stk + aop->size;
1027                         bitVectUnSetBit(ic->rUsed,R0_IDX);
1028                         bitVectUnSetBit(ic->rUsed,R1_IDX);                
1029                         
1030                         getFreePtr(ic,&aop,FALSE);
1031                         
1032                         if (options.stack10bit)
1033                         {
1034                                 /* I'm not sure what to do here yet... */
1035                                 /* #STUB */
1036                                 fprintf(stderr, 
1037                                         "*** Warning: probably generating bad code for "
1038                                         "10 bit stack mode.\n");
1039                         }
1040                         
1041                         if (stk) {
1042                                 pic14_emitcode ("mov","a,_bp");
1043                                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1044                                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1045                         } else {
1046                                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1047                         }
1048                         
1049                         while (sz--) {
1050                                 pic14_emitcode("pop","acc");
1051                                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1052                                 if (!sz) break;
1053                                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1054                         }
1055                         op->aop = aop;
1056                         freeAsmop(op,NULL,ic,TRUE);
1057                         if (_G.r0Pushed) {
1058                                 pic14_emitcode("pop","ar0");
1059                                 _G.r0Pushed--;
1060                         }
1061                         
1062                         if (_G.r1Pushed) {
1063                                 pic14_emitcode("pop","ar1");
1064                                 _G.r1Pushed--;
1065                         }         
1066                 }
1067         }
1068 #endif
1069         
1070 dealloc:
1071         /* all other cases just dealloc */
1072         if (op ) {
1073                 op->aop = NULL;
1074                 if (IS_SYMOP(op)) {
1075                         OP_SYMBOL(op)->aop = NULL;      
1076                         /* if the symbol has a spill */
1077                         if (SPIL_LOC(op))
1078                                 SPIL_LOC(op)->aop = NULL;
1079                 }
1080         }
1081 }
1082
1083 /*-----------------------------------------------------------------*/
1084 /* aopGet - for fetching value of the aop                                                  */
1085 /*-----------------------------------------------------------------*/
1086 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1087 {
1088         char *s = buffer ;
1089         char *rs;
1090         
1091         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1092         /* offset is greater than
1093         size then zero */
1094         if (offset > (aop->size - 1) &&
1095                 aop->type != AOP_LIT)
1096                 return zero;
1097         
1098         /* depending on type */
1099         switch (aop->type) {
1100                 
1101         case AOP_R0:
1102         case AOP_R1:
1103                 DEBUGpic14_emitcode(";","%d",__LINE__);
1104                 /* if we need to increment it */           
1105                 while (offset > aop->coff) {            
1106                         pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);    
1107                         aop->coff++;
1108                 }
1109                 
1110                 while (offset < aop->coff) {
1111                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1112                         aop->coff--;
1113                 }
1114                 
1115                 aop->coff = offset ;
1116                 if (aop->paged) {
1117                         pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1118                         return (dname ? "acc" : "a");
1119                 }               
1120                 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1121                 rs = Safe_calloc(1,strlen(s)+1);
1122                 strcpy(rs,s);   
1123                 return rs;
1124                 
1125         case AOP_DPTR:
1126         case AOP_DPTR2:
1127                 DEBUGpic14_emitcode(";","%d",__LINE__);
1128                 if (aop->type == AOP_DPTR2)
1129                 {
1130                         genSetDPTR(1);
1131                 }
1132                 
1133                 while (offset > aop->coff) {
1134                         pic14_emitcode ("inc","dptr");
1135                         aop->coff++;
1136                 }
1137                 
1138                 while (offset < aop->coff) {            
1139                         pic14_emitcode("lcall","__decdptr");
1140                         aop->coff--;
1141                 }
1142                 
1143                 aop->coff = offset;
1144                 if (aop->code) {
1145                         pic14_emitcode("clr","a");
1146                         pic14_emitcode("movc","a,@a+dptr");
1147                 }
1148                 else {
1149                         pic14_emitcode("movx","a,@dptr");
1150                 }
1151                 
1152                 if (aop->type == AOP_DPTR2)
1153                 {
1154                         genSetDPTR(0);
1155                 }
1156                 
1157                 return (dname ? "acc" : "a");
1158                 
1159                 
1160         case AOP_IMMD:
1161                 if (bit16) 
1162                         sprintf (s,"%s",aop->aopu.aop_immd);
1163                 else
1164                         if (offset) 
1165                                 sprintf(s,"(%s >> %d)",
1166                                 aop->aopu.aop_immd,
1167                                 offset*8);
1168                         else
1169                                 sprintf(s,"%s",
1170                                 aop->aopu.aop_immd);
1171                         DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1172                         rs = Safe_calloc(1,strlen(s)+1);
1173                         strcpy(rs,s);   
1174                         return rs;
1175                         
1176         case AOP_DIR:
1177                 if (offset) {
1178                         sprintf(s,"(%s + %d)",
1179                                 aop->aopu.aop_dir,
1180                                 offset);
1181                         DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1182                 } else
1183                         sprintf(s,"%s",aop->aopu.aop_dir);
1184                 rs = Safe_calloc(1,strlen(s)+1);
1185                 strcpy(rs,s);   
1186                 return rs;
1187                 
1188         case AOP_REG:
1189                 //if (dname) 
1190                 //        return aop->aopu.aop_reg[offset]->dname;
1191                 //else
1192                 return aop->aopu.aop_reg[offset]->name;
1193                 
1194         case AOP_CRY:
1195                 //pic14_emitcode(";","%d",__LINE__);
1196                 return aop->aopu.aop_dir;
1197                 
1198         case AOP_ACC:
1199                 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1200                 return "AOP_accumulator_bug";
1201                 
1202         case AOP_LIT:
1203                 sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1204                 rs = Safe_calloc(1,strlen(s)+1);
1205                 strcpy(rs,s);   
1206                 return rs;
1207                 
1208         case AOP_STR:
1209                 aop->coff = offset ;
1210                 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1211                         dname)
1212                         return "acc";
1213                 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1214                 
1215                 return aop->aopu.aop_str[offset];
1216                 
1217         case AOP_PCODE:
1218                 {
1219                         pCodeOp *pcop = aop->aopu.pcop;
1220                         DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1221                         if(pcop->name) {
1222                                 if (offset) {
1223                                         DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1224                                         sprintf(s,"(%s+%d)", pcop->name,offset);
1225                                 } else {
1226                                         DEBUGpic14_emitcode(";","%s",pcop->name);
1227                                         sprintf(s,"%s", pcop->name);
1228                                 }
1229                         } else
1230                                 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1231                         
1232                 }
1233                 rs = Safe_calloc(1,strlen(s)+1);
1234                 strcpy(rs,s);   
1235                 return rs;
1236                 
1237   }
1238   
1239   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1240           "aopget got unsupported aop->type");
1241   exit(0);
1242 }
1243
1244
1245 /*-----------------------------------------------------------------*/
1246 /* popGetTempReg - create a new temporary pCodeOp                                  */
1247 /*-----------------------------------------------------------------*/
1248 pCodeOp *popGetTempReg(void)
1249 {
1250         
1251         pCodeOp *pcop;
1252         
1253         pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1254         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1255                 PCOR(pcop)->r->wasUsed=1;
1256                 PCOR(pcop)->r->isFree=0;
1257         }
1258         
1259         return pcop;
1260 }
1261
1262 /*-----------------------------------------------------------------*/
1263 /* popReleaseTempReg - create a new temporary pCodeOp                              */
1264 /*-----------------------------------------------------------------*/
1265 void popReleaseTempReg(pCodeOp *pcop)
1266 {
1267         
1268         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1269                 PCOR(pcop)->r->isFree = 1;
1270         
1271 }
1272 /*-----------------------------------------------------------------*/
1273 /* popGetLabel - create a new pCodeOp of type PO_LABEL                     */
1274 /*-----------------------------------------------------------------*/
1275 pCodeOp *popGetLabel(unsigned int key)
1276 {
1277         
1278         DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1279         
1280         if(key>(unsigned int)max_key)
1281                 max_key = key;
1282         
1283         return newpCodeOpLabel(NULL,key+100+labelOffset);
1284 }
1285
1286 /*-------------------------------------------------------------------*/
1287 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1288 /*-------------------------------------------------------------------*/
1289 pCodeOp *popGetHighLabel(unsigned int key)
1290 {
1291         pCodeOp *pcop;
1292         pcop = popGetLabel(key);
1293         PCOLAB(pcop)->offset = 1;
1294         return pcop;
1295 }
1296
1297 /*-----------------------------------------------------------------*/
1298 /* popGetLit - asm operator to pcode operator conversion                           */
1299 /*-----------------------------------------------------------------*/
1300 pCodeOp *popGetLit(unsigned int lit)
1301 {
1302         
1303         return newpCodeOpLit((unsigned char)lit);
1304 }
1305
1306 /*-----------------------------------------------------------------*/
1307 /* popGetImmd - asm operator to pcode immediate conversion                 */
1308 /*-----------------------------------------------------------------*/
1309 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1310 {
1311         
1312         return newpCodeOpImmd(name, offset,index, 0, is_func);
1313 }
1314
1315 extern set *externs;
1316
1317 /*-----------------------------------------------------------------*/
1318 /* popGetWithString - asm operator to pcode operator conversion                    */
1319 /*-----------------------------------------------------------------*/
1320 pCodeOp *popGetWithString(char *str, int isExtern)
1321 {
1322         pCodeOp *pcop;
1323         
1324         
1325         if(!str) {
1326                 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1327                 exit (1);
1328         }
1329         
1330         pcop = newpCodeOp(str,PO_STR);
1331         PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1332
1333         return pcop;
1334 }
1335
1336 pCodeOp *popGetExternal (char *str)
1337 {
1338         pCodeOp *pcop = popGetWithString (str, 1);
1339         
1340         if (str) {
1341           symbol *sym;
1342           bool found = 0;
1343
1344           for (sym = setFirstItem (externs); !found && sym; sym = setNextItem (externs))
1345           {
1346             if (!strcmp (str, sym->rname))
1347               found = 1;
1348           }
1349           
1350           if (!found)
1351           {
1352             sym = newSymbol(str, 0);
1353             strncpy(sym->rname, str, SDCC_NAME_MAX);
1354             addSet (&externs, sym);
1355           } // if
1356         }
1357         return pcop;
1358 }
1359
1360 /*-----------------------------------------------------------------*/
1361 /* popRegFromString -                                                                                      */
1362 /*-----------------------------------------------------------------*/
1363 pCodeOp *popRegFromString(char *str, int size, int offset)
1364 {
1365         
1366         pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1367         pcop->type = PO_DIR;
1368         
1369         DEBUGpic14_emitcode(";","%d",__LINE__);
1370         
1371         if(!str)
1372                 str = "BAD_STRING";
1373         
1374         pcop->name = Safe_calloc(1,strlen(str)+1);
1375         strcpy(pcop->name,str);
1376         
1377         //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1378         
1379         PCOR(pcop)->r = dirregWithName(pcop->name);
1380         if(PCOR(pcop)->r == NULL) {
1381                 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1382                 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1383                 DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1384         } else {
1385                 DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1386         }
1387         PCOR(pcop)->instance = offset;
1388         
1389         return pcop;
1390 }
1391
1392 /*-----------------------------------------------------------------*/
1393 /*-----------------------------------------------------------------*/
1394 pCodeOp *popRegFromIdx(int rIdx)
1395 {
1396         pCodeOp *pcop;
1397         
1398         DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1399                 __FUNCTION__,__LINE__,rIdx);
1400         
1401         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1402         
1403         PCOR(pcop)->rIdx = rIdx;
1404         PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1405         PCOR(pcop)->r->isFree = 0;
1406         PCOR(pcop)->r->wasUsed = 1;
1407         
1408         pcop->type = PCOR(pcop)->r->pc_type;
1409         
1410         
1411         return pcop;
1412 }
1413
1414 /*-----------------------------------------------------------------*/
1415 /* popGet - asm operator to pcode operator conversion                      */
1416 /*-----------------------------------------------------------------*/
1417 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1418 {
1419         //char *s = buffer ;
1420         //char *rs;
1421         
1422         pCodeOp *pcop;
1423         
1424         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1425         /* offset is greater than
1426         size then zero */
1427
1428         assert (aop);
1429
1430         /* XXX: still needed for BIT operands (AOP_CRY) */
1431         if (offset > (aop->size - 1) &&
1432                 aop->type != AOP_LIT)
1433                 return NULL;  //zero;
1434         
1435         /* depending on type */
1436         switch (aop->type) {
1437                 
1438         case AOP_R0:
1439         case AOP_R1:
1440         case AOP_DPTR:
1441         case AOP_DPTR2:
1442         case AOP_ACC:
1443                 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1444                 return NULL;
1445                 
1446         case AOP_IMMD:
1447                 DEBUGpic14_emitcode(";","%d",__LINE__);
1448                 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1449                 
1450         case AOP_DIR:
1451                 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1452 #if 0
1453                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1454                 pcop->type = PO_DIR;
1455                 
1456                 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1457                 strcpy(pcop->name,aop->aopu.aop_dir);   
1458                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1459                 if(PCOR(pcop)->r == NULL) {
1460                         //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1461                         PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1462                         DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1463                 } else {
1464                         DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1465                 }
1466                 PCOR(pcop)->instance = offset;
1467                 
1468                 return pcop;
1469 #endif
1470                 
1471         case AOP_REG:
1472                 {
1473                         int rIdx;
1474                         assert (offset < aop->size);
1475                         rIdx = aop->aopu.aop_reg[offset]->rIdx;
1476                         
1477                         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1478                         PCOR(pcop)->rIdx = rIdx;
1479                         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1480                         PCOR(pcop)->r->wasUsed=1;
1481                         PCOR(pcop)->r->isFree=0;
1482                         
1483                         PCOR(pcop)->instance = offset;
1484                         pcop->type = PCOR(pcop)->r->pc_type;
1485                         //rs = aop->aopu.aop_reg[offset]->name;
1486                         DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1487                         return pcop;
1488                 }
1489                 
1490         case AOP_CRY:
1491                 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1492                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1493                 //if(PCOR(pcop)->r == NULL)
1494                 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1495                 return pcop;
1496                 
1497         case AOP_LIT:
1498                 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1499                 
1500         case AOP_STR:
1501                 DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1502                 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1503                 /*
1504                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1505                 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1506                 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1507                 pcop->type = PCOR(pcop)->r->pc_type;
1508                 pcop->name = PCOR(pcop)->r->name;
1509                 
1510                   return pcop;
1511                 */
1512                 
1513         case AOP_PCODE:
1514                 pcop = NULL;
1515                 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1516                         __LINE__, 
1517                         ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1518                 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1519                 switch (aop->aopu.pcop->type)
1520                 {
1521                 case PO_IMMEDIATE:
1522                   pcop = pCodeOpCopy (aop->aopu.pcop);
1523                   /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1524                    * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1525                   PCOI(pcop)->index += offset;
1526                   //PCOI(pcop)->offset = 0;
1527                   break;
1528                 case PO_DIR:
1529                   pcop = pCodeOpCopy (aop->aopu.pcop);
1530                   PCOR(pcop)->instance = offset;
1531                   break;
1532                 default:
1533                   assert ( !"unhandled pCode type" );
1534                   break;
1535                 } // switch
1536                 return pcop;
1537         }
1538         
1539         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1540                 "popGet got unsupported aop->type");
1541         exit(0);
1542 }
1543
1544 /*-----------------------------------------------------------------*/
1545 /* popGetAddr - access the low/high word of a symbol (immediate)   */
1546 /*              (for non-PO_IMMEDIATEs this is the same as popGet) */
1547 /*-----------------------------------------------------------------*/
1548 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1549 {
1550   if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1551   {
1552     pCodeOp *pcop = aop->aopu.pcop;
1553     assert (offset <= GPTRSIZE);
1554
1555     /* special case: index >= 2 should return GPOINTER-style values */
1556     if (offset == 2)
1557     {
1558       pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1559       return pcop;
1560     }
1561     
1562     pcop = pCodeOpCopy (pcop);
1563     /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1564      * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1565     PCOI(pcop)->offset += offset;
1566     PCOI(pcop)->index += index;
1567     //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);
1568     return pcop;
1569   } else {
1570     return popGet (aop, offset + index);
1571   }
1572 }
1573
1574 /*-----------------------------------------------------------------*/
1575 /* aopPut - puts a string for a aop                                                        */
1576 /*-----------------------------------------------------------------*/
1577 void aopPut (asmop *aop, char *s, int offset)
1578 {
1579         char *d = buffer ;
1580         symbol *lbl ;
1581         
1582         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1583         
1584         if (aop->size && offset > ( aop->size - 1)) {
1585                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1586                         "aopPut got offset > aop->size");
1587                 exit(0);
1588         }
1589         
1590         /* will assign value to value */
1591         /* depending on where it is ofcourse */
1592         switch (aop->type) {
1593         case AOP_DIR:
1594                 if (offset) {
1595                         sprintf(d,"(%s + %d)",
1596                                 aop->aopu.aop_dir,offset);
1597                         fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1598                         
1599                 } else
1600                         sprintf(d,"%s",aop->aopu.aop_dir);
1601                 
1602                 if (strcmp(d,s)) {
1603                         DEBUGpic14_emitcode(";","%d",__LINE__);
1604                         if(strcmp(s,"W"))
1605                                 pic14_emitcode("movf","%s,w",s);
1606                         pic14_emitcode("movwf","%s",d);
1607                         
1608                         if(strcmp(s,"W")) {
1609                                 pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1610                                 if(offset >= aop->size) {
1611                                         emitpcode(POC_CLRF,popGet(aop,offset));
1612                                         break;
1613                                 } else {
1614                                         emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1615                                 }
1616                         }
1617                         emitpcode(POC_MOVWF,popGet(aop,offset));
1618                 
1619                 }
1620                 break;
1621                 
1622         case AOP_REG:
1623                 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1624                         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1625                         /*
1626                         if (*s == '@'             ||
1627                         strcmp(s,"r0") == 0 ||
1628                         strcmp(s,"r1") == 0 ||
1629                         strcmp(s,"r2") == 0 ||
1630                         strcmp(s,"r3") == 0 ||
1631                         strcmp(s,"r4") == 0 ||
1632                         strcmp(s,"r5") == 0 ||
1633                         strcmp(s,"r6") == 0 || 
1634                         strcmp(s,"r7") == 0 )
1635                         pic14_emitcode("mov","%s,%s  ; %d",
1636                         aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1637                         else
1638                         */
1639                         
1640                         if(strcmp(s,"W")==0 )
1641                                 pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1642                         
1643                         pic14_emitcode("movwf","%s",
1644                                 aop->aopu.aop_reg[offset]->name);
1645                         
1646                         if(strcmp(s,zero)==0) {
1647                                 emitpcode(POC_CLRF,popGet(aop,offset));
1648                                 
1649                         } else if(strcmp(s,"W")==0) {
1650                                 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1651                                 pcop->type = PO_GPR_REGISTER;
1652                                 
1653                                 PCOR(pcop)->rIdx = -1;
1654                                 PCOR(pcop)->r = NULL;
1655                                 
1656                                 DEBUGpic14_emitcode(";","%d",__LINE__);
1657                                 pcop->name = Safe_strdup(s);
1658                                 emitpcode(POC_MOVFW,pcop);
1659                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1660                         } else if(strcmp(s,one)==0) {
1661                                 emitpcode(POC_CLRF,popGet(aop,offset));
1662                                 emitpcode(POC_INCF,popGet(aop,offset));
1663                         } else {
1664                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1665                         }
1666                 }
1667                 break;
1668                 
1669         case AOP_DPTR:
1670         case AOP_DPTR2:
1671                 
1672                 if (aop->type == AOP_DPTR2)
1673                 {
1674                         genSetDPTR(1);
1675                 }
1676                 
1677                 if (aop->code) {
1678                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1679                                 "aopPut writting to code space");
1680                         exit(0);
1681                 }
1682                 
1683                 while (offset > aop->coff) {
1684                         aop->coff++;
1685                         pic14_emitcode ("inc","dptr");
1686                 }
1687                 
1688                 while (offset < aop->coff) {
1689                         aop->coff-- ;
1690                         pic14_emitcode("lcall","__decdptr");
1691                 }
1692                 
1693                 aop->coff = offset;
1694                 
1695                 /* if not in accumulater */
1696                 MOVA(s);
1697                 
1698                 pic14_emitcode ("movx","@dptr,a");
1699                 
1700                 if (aop->type == AOP_DPTR2)
1701                 {
1702                         genSetDPTR(0);
1703                 }
1704                 break;
1705                 
1706         case AOP_R0:
1707         case AOP_R1:
1708                 while (offset > aop->coff) {
1709                         aop->coff++;
1710                         pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1711                 }
1712                 while (offset < aop->coff) {
1713                         aop->coff-- ;
1714                         pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1715                 }
1716                 aop->coff = offset;
1717                 
1718                 if (aop->paged) {
1719                         MOVA(s);                         
1720                         pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1721                         
1722                 } else
1723                         if (*s == '@') {
1724                                 MOVA(s);
1725                                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1726                         } else
1727                                 if (strcmp(s,"r0") == 0 ||
1728                                         strcmp(s,"r1") == 0 ||
1729                                         strcmp(s,"r2") == 0 ||
1730                                         strcmp(s,"r3") == 0 ||
1731                                         strcmp(s,"r4") == 0 ||
1732                                         strcmp(s,"r5") == 0 ||
1733                                         strcmp(s,"r6") == 0 || 
1734                                         strcmp(s,"r7") == 0 ) {
1735                                         char buffer[10];
1736                                         sprintf(buffer,"a%s",s);
1737                                         pic14_emitcode("mov","@%s,%s",
1738                                                 aop->aopu.aop_ptr->name,buffer);
1739                                 } else
1740                                         pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1741                                 
1742                                 break;
1743                                 
1744         case AOP_STK:
1745                 if (strcmp(s,"a") == 0)
1746                         pic14_emitcode("push","acc");
1747                 else
1748                         pic14_emitcode("push","%s",s);
1749                 
1750                 break;
1751                 
1752         case AOP_CRY:
1753                 /* if bit variable */
1754                 if (!aop->aopu.aop_dir) {
1755                         pic14_emitcode("clr","a");
1756                         pic14_emitcode("rlc","a");
1757                 } else {
1758                         if (s == zero) 
1759                                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1760                         else
1761                                 if (s == one)
1762                                         pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1763                                 else
1764                                         if (!strcmp(s,"c"))
1765                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1766                                         else {
1767                                                 lbl = newiTempLabel(NULL);
1768                                                 
1769                                                 if (strcmp(s,"a")) {
1770                                                         MOVA(s);
1771                                                 }
1772                                                 pic14_emitcode("clr","c");
1773                                                 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1774                                                 pic14_emitcode("cpl","c");
1775                                                 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1776                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1777                                         }
1778                 }
1779                 break;
1780                 
1781         case AOP_STR:
1782                 aop->coff = offset;
1783                 if (strcmp(aop->aopu.aop_str[offset],s))
1784                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1785                 break;
1786                 
1787         case AOP_ACC:
1788                 aop->coff = offset;
1789                 if (!offset && (strcmp(s,"acc") == 0))
1790                         break;
1791                 
1792                 if (strcmp(aop->aopu.aop_str[offset],s))
1793                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1794                 break;
1795                 
1796         default :
1797                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1798                         "aopPut got unsupported aop->type");
1799                 exit(0);
1800         }
1801         
1802 }
1803
1804 /*-----------------------------------------------------------------*/
1805 /* mov2w_op - generate either a MOVLW or MOVFW based operand type  */
1806 /*-----------------------------------------------------------------*/
1807 static void mov2w_op (operand *op, int offset)
1808 {
1809         assert (op);
1810         FENTRY;
1811
1812         /* for PO_IMMEDIATEs: use address or value? */
1813         if (op_isLitLike (op))
1814         {
1815                 /* access address of op */
1816                 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1817                 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1818                 {
1819                         if (offset == GPTRSIZE-1)
1820                                 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1821                         else
1822                                 emitpcode (POC_MOVLW, popGetLit (0));
1823                 }
1824                 else
1825                         emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1826         } else {
1827                 /* access value stored in op */
1828                 mov2w (AOP(op), offset);
1829         }
1830 }
1831
1832
1833 /*-----------------------------------------------------------------*/
1834 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1835 /*-----------------------------------------------------------------*/
1836 void mov2w (asmop *aop, int offset)
1837 {
1838         
1839         if(!aop)
1840                 return;
1841         
1842         DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1843         
1844         if ( aop_isLitLike (aop) )
1845                 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1846         else
1847                 emitpcode(POC_MOVFW,popGet(aop,offset));
1848         
1849 }
1850
1851 static void movwf (asmop *op, int offset)
1852 {
1853         emitpcode (POC_MOVWF, popGet(op, offset));
1854 }
1855
1856 static pCodeOp *get_argument_pcop (int idx)
1857 {
1858         assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1859         return popRegFromIdx (Gstack_base_addr - (idx - 1));
1860 }
1861
1862 static pCodeOp *get_return_val_pcop (int offset)
1863 {
1864         assert (offset > 0 && "the most significant byte is returned via WREG");
1865         return popRegFromIdx (Gstack_base_addr - (offset - 1));
1866 }
1867
1868 static void pass_argument (operand *op, int offset, int idx)
1869 {
1870         if (op)
1871                 mov2w_op (op, offset);
1872         if (idx != 0)
1873                 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1874 }
1875
1876 static void get_returnvalue (operand *op, int offset, int idx)
1877 {
1878         if (idx != 0)
1879                 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1880         movwf(AOP(op), offset);
1881 }
1882
1883 static void call_libraryfunc (char *name)
1884 {
1885   /* library code might reside in different page... */
1886   emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1887   /* call the library function */
1888   emitpcode (POC_CALL, popGetExternal (name));
1889   /* might return from different page... */
1890   emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1891 }
1892 #if 0
1893 /*-----------------------------------------------------------------*/
1894 /* reAdjustPreg - points a register back to where it should        */
1895 /*-----------------------------------------------------------------*/
1896 static void reAdjustPreg (asmop *aop)
1897 {
1898         int size ;
1899         
1900         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1901         aop->coff = 0;
1902         if ((size = aop->size) <= 1)
1903                 return ;
1904         size-- ;
1905         switch (aop->type) {
1906         case AOP_R0 :
1907         case AOP_R1 :
1908                 while (size--)
1909                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1910                 break;                  
1911         case AOP_DPTR :
1912         case AOP_DPTR2:
1913                 if (aop->type == AOP_DPTR2)
1914                 {
1915                         genSetDPTR(1);
1916                 } 
1917                 while (size--)
1918                 {
1919                         pic14_emitcode("lcall","__decdptr");
1920                 }
1921                 
1922                 if (aop->type == AOP_DPTR2)
1923                 {
1924                         genSetDPTR(0);
1925                 }
1926                 break;
1927                 
1928         }
1929         
1930 }
1931 #endif
1932
1933
1934 #if 0
1935 /*-----------------------------------------------------------------*/
1936 /* opIsGptr: returns non-zero if the passed operand is             */
1937 /* a generic pointer type.                                         */
1938 /*-----------------------------------------------------------------*/ 
1939 static int opIsGptr(operand *op)
1940 {
1941         sym_link *type = operandType(op);
1942         
1943         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1944         if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1945         {
1946                 return 1;
1947         }
1948         return 0;          
1949 }
1950 #endif
1951
1952 /*-----------------------------------------------------------------*/
1953 /* pic14_getDataSize - get the operand data size                   */
1954 /*-----------------------------------------------------------------*/
1955 int pic14_getDataSize(operand *op)
1956 {
1957         int size;
1958         
1959         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1960         
1961 #if 0
1962         size = getSize(OP_SYM_ETYPE(op));
1963         return size;
1964         //return AOP_SIZE(op);
1965         
1966         // tsd- in the pic port, the genptr size is 1, so this code here
1967         // fails. ( in the 8051 port, the size was 4).
1968 #else
1969         size = AOP_SIZE(op);
1970         if (IS_GENPTR(OP_SYM_TYPE(op)))
1971         {
1972                 sym_link *type = operandType(op);
1973                 if (IS_GENPTR(type))
1974                 {
1975                         /* generic pointer; arithmetic operations
1976                         * should ignore the high byte (pointer type).
1977                         */
1978                         size--;
1979                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1980                 }
1981         }
1982         return size;
1983 #endif
1984 }
1985
1986 /*-----------------------------------------------------------------*/
1987 /* pic14_outAcc - output Acc                                       */
1988 /*-----------------------------------------------------------------*/
1989 void pic14_outAcc(operand *result)
1990 {
1991         int size,offset;
1992         DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1993         DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1994         
1995         
1996         size = pic14_getDataSize(result);
1997         if(size){
1998                 emitpcode(POC_MOVWF,popGet(AOP(result),0));
1999                 size--;
2000                 offset = 1;
2001                 /* unsigned or positive */
2002                 while(size--)
2003                         emitpcode(POC_CLRF,popGet(AOP(result),offset++));
2004         }
2005         
2006 }
2007
2008 /*-----------------------------------------------------------------*/
2009 /* pic14_outBitC - output a bit C                                  */
2010 /*-----------------------------------------------------------------*/
2011 void pic14_outBitC(operand *result)
2012 {
2013         
2014         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2015         /* if the result is bit */
2016         if (AOP_TYPE(result) == AOP_CRY) 
2017                 aopPut(AOP(result),"c",0);
2018         else {
2019                 pic14_emitcode("clr","a  ; %d", __LINE__);
2020                 pic14_emitcode("rlc","a");
2021                 pic14_outAcc(result);
2022         }
2023 }
2024
2025 /*-----------------------------------------------------------------*/
2026 /* pic14_toBoolean - emit code for orl a,operator(sizeop)          */
2027 /*-----------------------------------------------------------------*/
2028 void pic14_toBoolean(operand *oper)
2029 {
2030         int size = AOP_SIZE(oper);
2031         int offset = 0;
2032         
2033         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2034
2035         assert (size > 0);
2036
2037         if (size == 1) {
2038                 /* MOVFW does not load the flags... */
2039                 if (AOP_TYPE(oper) == AOP_ACC) {
2040                         emitpcode(POC_IORLW, popGetLit(0));
2041                         offset = 1;
2042                 } else {
2043                         emitpcode(POC_MOVLW, popGetLit(0));
2044                         offset = 0;
2045                 }
2046         } else {
2047                 if ( AOP_TYPE(oper) != AOP_ACC) {
2048                         emitpcode(POC_MOVFW,popGet(AOP(oper),0));
2049                         offset = 1;
2050                 }
2051         }
2052         
2053         while (offset < size) {
2054                 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
2055         }
2056         /* Z is set iff (oper == 0) */
2057 }
2058
2059
2060 /*-----------------------------------------------------------------*/
2061 /* genNot - generate code for ! operation                          */
2062 /*-----------------------------------------------------------------*/
2063 static void genNot (iCode *ic)
2064 {
2065         //symbol *tlbl;
2066         int size;
2067
2068         FENTRY;
2069         
2070         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2071         /* assign asmOps to operand & result */
2072         aopOp (IC_LEFT(ic),ic,FALSE);
2073         aopOp (IC_RESULT(ic),ic,TRUE);
2074         
2075         DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2076         /* if in bit space then a special case */
2077         if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2078                 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2079                         emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2080                         emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2081                 } else {
2082                         emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2083                         emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2084                         emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2085                 }
2086                 goto release;
2087         }
2088         
2089         size = AOP_SIZE(IC_LEFT(ic));
2090         mov2w (AOP(IC_LEFT(ic)),0);
2091         while (--size > 0)
2092         {
2093           if (op_isLitLike (IC_LEFT(ic)))
2094             emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2095           else
2096             emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2097         }
2098         emitpcode(POC_MOVLW, popGetLit (0));
2099         emitSKPNZ;
2100         emitpcode(POC_MOVLW, popGetLit (1));
2101         movwf(AOP(IC_RESULT(ic)), 0);
2102
2103         for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2104         {
2105           emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2106         }
2107         goto release;
2108         
2109 release:        
2110         /* release the aops */
2111         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2112         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2113 }
2114
2115
2116 /*-----------------------------------------------------------------*/
2117 /* genCpl - generate code for complement                                                   */
2118 /*-----------------------------------------------------------------*/
2119 static void genCpl (iCode *ic)
2120 {
2121         operand *left, *result;
2122         int size, offset=0;  
2123         
2124         FENTRY;
2125         
2126         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2127         aopOp((left = IC_LEFT(ic)),ic,FALSE);
2128         aopOp((result=IC_RESULT(ic)),ic,TRUE);
2129         
2130         /* if both are in bit space then 
2131         a special case */
2132         if (AOP_TYPE(result) == AOP_CRY &&
2133                 AOP_TYPE(left) == AOP_CRY ) { 
2134                 
2135                 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir); 
2136                 pic14_emitcode("cpl","c"); 
2137                 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir); 
2138                 goto release; 
2139         } 
2140         
2141         size = AOP_SIZE(result);
2142         if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2143         while (size--) {
2144                 
2145                 if(AOP_TYPE(left) == AOP_ACC) 
2146                         emitpcode(POC_XORLW, popGetLit(0xff));
2147                 else
2148                         emitpcode(POC_COMFW,popGet(AOP(left),offset));
2149                 
2150                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2151                 offset++;
2152         }
2153         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2154         
2155         
2156 release:
2157         /* release the aops */
2158         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2159         freeAsmop(result,NULL,ic,TRUE);
2160 }
2161
2162 /*-----------------------------------------------------------------*/
2163 /* genUminusFloat - unary minus for floating points                        */
2164 /*-----------------------------------------------------------------*/
2165 static void genUminusFloat(operand *op,operand *result)
2166 {
2167         int size ,offset =0 ;
2168         char *l;
2169         
2170         FENTRY;
2171
2172         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2173         /* for this we just need to flip the 
2174         first it then copy the rest in place */
2175         size = AOP_SIZE(op) - 1;
2176         l = aopGet(AOP(op),3,FALSE,FALSE);
2177         
2178         MOVA(l);          
2179         
2180         pic14_emitcode("cpl","acc.7");
2181         aopPut(AOP(result),"a",3);      
2182         
2183         while(size--) {
2184                 aopPut(AOP(result),
2185                         aopGet(AOP(op),offset,FALSE,FALSE),
2186                         offset);
2187                 offset++;
2188         }                
2189 }
2190
2191 /*-----------------------------------------------------------------*/
2192 /* genUminus - unary minus code generation                                                 */
2193 /*-----------------------------------------------------------------*/
2194 static void genUminus (iCode *ic)
2195 {
2196         int size, i;
2197         sym_link *optype, *rtype;
2198         
2199         FENTRY;
2200         
2201         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2202         /* assign asmops */
2203         aopOp(IC_LEFT(ic),ic,FALSE);
2204         aopOp(IC_RESULT(ic),ic,TRUE);
2205         
2206         /* if both in bit space then special
2207         case */
2208         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2209                 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2210                 
2211                 emitpcode(POC_BCF,       popGet(AOP(IC_RESULT(ic)),0));
2212                 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2213                 emitpcode(POC_BSF,       popGet(AOP(IC_RESULT(ic)),0));
2214                 
2215                 goto release; 
2216         } 
2217         
2218         optype = operandType(IC_LEFT(ic));
2219         rtype = operandType(IC_RESULT(ic));
2220         
2221         /* if float then do float stuff */
2222         if (IS_FLOAT(optype)) {
2223                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2224                 goto release;
2225         }
2226         
2227         /* otherwise subtract from zero by taking the 2's complement */
2228         size = AOP_SIZE(IC_LEFT(ic));
2229         
2230         for(i=0; i<size; i++) {
2231                 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2232                         emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
2233                 else {
2234                         emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2235                         emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2236                 }
2237         }
2238         
2239         emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
2240         for(i=1; i<size; i++) {
2241                 emitSKPNZ;
2242                 emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
2243         }
2244         
2245 release:
2246         /* release the aops */
2247         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2248         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);  
2249 }
2250
2251 /*-----------------------------------------------------------------*/
2252 /* saveRegisters - will look for a call and save the registers     */
2253 /*-----------------------------------------------------------------*/
2254 static void saveRegisters(iCode *lic) 
2255 {
2256         int i;
2257         iCode *ic;
2258         bitVect *rsave;
2259         sym_link *dtype;
2260         
2261         FENTRY;
2262
2263         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2264         /* look for call */
2265         for (ic = lic ; ic ; ic = ic->next) 
2266                 if (ic->op == CALL || ic->op == PCALL)
2267                         break;
2268                 
2269                 if (!ic) {
2270                         fprintf(stderr,"found parameter push with no function call\n");
2271                         return ;
2272                 }
2273                 
2274                 /* if the registers have been saved already then
2275                 do nothing */
2276                 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2277                         return ;
2278                 
2279                         /* find the registers in use at this time 
2280                 and push them away to safety */
2281                 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2282                         ic->rUsed);
2283                 
2284                 ic->regsSaved = 1;
2285                 if (options.useXstack) {
2286                         if (bitVectBitValue(rsave,R0_IDX))
2287                                 pic14_emitcode("mov","b,r0");
2288                         pic14_emitcode("mov","r0,%s",spname);
2289                         for (i = 0 ; i < pic14_nRegs ; i++) {
2290                                 if (bitVectBitValue(rsave,i)) {
2291                                         if (i == R0_IDX)
2292                                                 pic14_emitcode("mov","a,b");
2293                                         else
2294                                                 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2295                                         pic14_emitcode("movx","@r0,a");
2296                                         pic14_emitcode("inc","r0");
2297                                 }
2298                         }
2299                         pic14_emitcode("mov","%s,r0",spname);
2300                         if (bitVectBitValue(rsave,R0_IDX))
2301                                 pic14_emitcode("mov","r0,b");     
2302                 }// else
2303                 //for (i = 0 ; i < pic14_nRegs ; i++) {
2304                 //        if (bitVectBitValue(rsave,i))
2305                 //      pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2306                 //}
2307                 
2308                 dtype = operandType(IC_LEFT(ic));
2309                 if (currFunc && dtype && 
2310                         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2311                         IFFUNC_ISISR(currFunc->type) &&
2312                         !ic->bankSaved) 
2313                         
2314                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2315                 
2316 }
2317 /*-----------------------------------------------------------------*/
2318 /* unsaveRegisters - pop the pushed registers                                      */
2319 /*-----------------------------------------------------------------*/
2320 static void unsaveRegisters (iCode *ic)
2321 {
2322         int i;
2323         bitVect *rsave;
2324         
2325         FENTRY;
2326
2327         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2328         /* find the registers in use at this time 
2329         and push them away to safety */
2330         rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2331                 ic->rUsed);
2332         
2333         if (options.useXstack) {
2334                 pic14_emitcode("mov","r0,%s",spname); 
2335                 for (i =  pic14_nRegs ; i >= 0 ; i--) {
2336                         if (bitVectBitValue(rsave,i)) {
2337                                 pic14_emitcode("dec","r0");
2338                                 pic14_emitcode("movx","a,@r0");
2339                                 if (i == R0_IDX)
2340                                         pic14_emitcode("mov","b,a");
2341                                 else
2342                                         pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2343                         }       
2344                         
2345                 }
2346                 pic14_emitcode("mov","%s,r0",spname);
2347                 if (bitVectBitValue(rsave,R0_IDX))
2348                         pic14_emitcode("mov","r0,b");
2349         } //else
2350         //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2351         //      if (bitVectBitValue(rsave,i))
2352         //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2353         //}
2354         
2355 }  
2356
2357
2358 /*-----------------------------------------------------------------*/
2359 /* pushSide -                            */
2360 /*-----------------------------------------------------------------*/
2361 static void pushSide(operand * oper, int size)
2362 {
2363 #if 0
2364         int offset = 0;
2365         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2366         while (size--) {
2367                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2368                 if (AOP_TYPE(oper) != AOP_REG &&
2369                         AOP_TYPE(oper) != AOP_DIR &&
2370                         strcmp(l,"a") ) {
2371                         pic14_emitcode("mov","a,%s",l);
2372                         pic14_emitcode("push","acc");
2373                 } else
2374                         pic14_emitcode("push","%s",l);
2375         }
2376 #endif
2377 }
2378
2379 /*-----------------------------------------------------------------*/
2380 /* assignResultValue -                           */
2381 /*-----------------------------------------------------------------*/
2382 static void assignResultValue(operand * oper)
2383 {
2384         int size = AOP_SIZE(oper);
2385         int offset = 0;
2386         
2387         FENTRY;
2388
2389         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2390         
2391         DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2392         
2393         /* assign MSB first (passed via WREG) */
2394         while (size--) {
2395                 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2396                 GpsuedoStkPtr++;
2397         }
2398 }
2399
2400
2401 /*-----------------------------------------------------------------*/
2402 /* genIpush - genrate code for pushing this gets a little complex  */
2403 /*-----------------------------------------------------------------*/
2404 static void genIpush (iCode *ic)
2405 {
2406         FENTRY;
2407         
2408         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2409 #if 0
2410         int size, offset = 0 ;
2411         char *l;
2412         
2413         
2414         /* if this is not a parm push : ie. it is spill push 
2415         and spill push is always done on the local stack */
2416         if (!ic->parmPush) {
2417                 
2418                 /* and the item is spilt then do nothing */
2419                 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2420                         return ;
2421                 
2422                 aopOp(IC_LEFT(ic),ic,FALSE);
2423                 size = AOP_SIZE(IC_LEFT(ic));
2424                 /* push it on the stack */
2425                 while(size--) {
2426                         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2427                         if (*l == '#') {
2428                                 MOVA(l);
2429                                 l = "acc";
2430                         }
2431                         pic14_emitcode("push","%s",l);
2432                 }
2433                 return ;                
2434         }
2435         
2436         /* this is a paramter push: in this case we call
2437         the routine to find the call and save those
2438         registers that need to be saved */   
2439         saveRegisters(ic);
2440         
2441         /* then do the push */
2442         aopOp(IC_LEFT(ic),ic,FALSE);
2443         
2444         
2445         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2446         size = AOP_SIZE(IC_LEFT(ic));
2447         
2448         while (size--) {
2449                 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2450                 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2451                         AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2452                         strcmp(l,"a") ) {
2453                         pic14_emitcode("mov","a,%s",l);
2454                         pic14_emitcode("push","acc");
2455                 } else
2456                         pic14_emitcode("push","%s",l);
2457         }         
2458         
2459         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2460 #endif
2461 }
2462
2463 /*-----------------------------------------------------------------*/
2464 /* genIpop - recover the registers: can happen only for spilling   */
2465 /*-----------------------------------------------------------------*/
2466 static void genIpop (iCode *ic)
2467 {
2468         FENTRY;
2469
2470         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2471         assert (!"genIpop -- unimplemented");
2472 #if 0
2473         int size,offset ;
2474         
2475         
2476         /* if the temp was not pushed then */
2477         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2478                 return ;
2479         
2480         aopOp(IC_LEFT(ic),ic,FALSE);
2481         size = AOP_SIZE(IC_LEFT(ic));
2482         offset = (size-1);
2483         while (size--) 
2484                 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2485                 FALSE,TRUE));
2486         
2487         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2488 #endif
2489 }
2490
2491 /*-----------------------------------------------------------------*/
2492 /* unsaverbank - restores the resgister bank from stack                    */
2493 /*-----------------------------------------------------------------*/
2494 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2495 {
2496         FENTRY;
2497
2498         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2499 #if 0
2500         int i;
2501         asmop *aop ;
2502         regs *r = NULL;
2503         
2504         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2505         if (popPsw) {
2506                 if (options.useXstack) {
2507                         aop = newAsmop(0);
2508                         r = getFreePtr(ic,&aop,FALSE);
2509                         
2510                         
2511                         pic14_emitcode("mov","%s,_spx",r->name);
2512                         pic14_emitcode("movx","a,@%s",r->name);
2513                         pic14_emitcode("mov","psw,a");
2514                         pic14_emitcode("dec","%s",r->name);
2515                         
2516                 }else
2517                         pic14_emitcode ("pop","psw");
2518         }
2519         
2520         for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2521                 if (options.useXstack) {           
2522                         pic14_emitcode("movx","a,@%s",r->name);
2523                         //pic14_emitcode("mov","(%s+%d),a",
2524                         //         regspic14[i].base,8*bank+regspic14[i].offset);
2525                         pic14_emitcode("dec","%s",r->name);
2526                         
2527                 } else 
2528                         pic14_emitcode("pop",""); //"(%s+%d)",
2529                 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2530         }
2531         
2532         if (options.useXstack) {
2533                 
2534                 pic14_emitcode("mov","_spx,%s",r->name);
2535                 freeAsmop(NULL,aop,ic,TRUE);
2536                 
2537         }
2538 #endif 
2539 }
2540
2541 /*-----------------------------------------------------------------*/
2542 /* saverbank - saves an entire register bank on the stack                  */
2543 /*-----------------------------------------------------------------*/
2544 static void saverbank (int bank, iCode *ic, bool pushPsw)
2545 {
2546         FENTRY;
2547
2548         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2549 #if 0
2550         int i;
2551         asmop *aop ;
2552         regs *r = NULL;
2553         
2554         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2555         if (options.useXstack) {
2556                 
2557                 aop = newAsmop(0);
2558                 r = getFreePtr(ic,&aop,FALSE);  
2559                 pic14_emitcode("mov","%s,_spx",r->name);
2560                 
2561         }
2562         
2563         for (i = 0 ; i < pic14_nRegs ;i++) {
2564                 if (options.useXstack) {
2565                         pic14_emitcode("inc","%s",r->name);
2566                         //pic14_emitcode("mov","a,(%s+%d)",
2567                         //               regspic14[i].base,8*bank+regspic14[i].offset);
2568                         pic14_emitcode("movx","@%s,a",r->name);                 
2569                 } else 
2570                         pic14_emitcode("push","");// "(%s+%d)",
2571                 //regspic14[i].base,8*bank+regspic14[i].offset);
2572         }
2573         
2574         if (pushPsw) {
2575                 if (options.useXstack) {
2576                         pic14_emitcode("mov","a,psw");
2577                         pic14_emitcode("movx","@%s,a",r->name); 
2578                         pic14_emitcode("inc","%s",r->name);
2579                         pic14_emitcode("mov","_spx,%s",r->name);                 
2580                         freeAsmop (NULL,aop,ic,TRUE);
2581                         
2582                 } else
2583                         pic14_emitcode("push","psw");
2584                 
2585                 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2586         }
2587         ic->bankSaved = 1;
2588 #endif
2589 }
2590
2591 /*-----------------------------------------------------------------*/
2592 /* genCall - generates a call statement                                                    */
2593 /*-----------------------------------------------------------------*/
2594 static void genCall (iCode *ic)
2595 {
2596         sym_link *dtype;         
2597         symbol *sym;
2598         unsigned char *name;
2599         int isExtern;
2600         
2601         FENTRY;
2602
2603         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2604         
2605         /* if caller saves & we have not saved then */
2606         if (!ic->regsSaved)
2607                 saveRegisters(ic);
2608         
2609                 /* if we are calling a function that is not using
2610                 the same register bank then we need to save the
2611         destination registers on the stack */
2612         dtype = operandType(IC_LEFT(ic));
2613         if (currFunc && dtype && 
2614                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2615                 IFFUNC_ISISR(currFunc->type) &&
2616                 !ic->bankSaved) 
2617                 
2618                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2619         
2620         /* if send set is not empty the assign */
2621         if (_G.sendSet) {
2622                 iCode *sic;
2623                 /* For the Pic port, there is no data stack.
2624                 * So parameters passed to functions are stored
2625                 * in registers. (The pCode optimizer will get
2626                 * rid of most of these :).
2627                 */
2628                 int psuedoStkPtr=-1;
2629                 int firstTimeThruLoop = 1;
2630                 
2631                 _G.sendSet = reverseSet(_G.sendSet);
2632                 
2633                 /* First figure how many parameters are getting passed */
2634                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2635                 sic = setNextItem(_G.sendSet)) {
2636                         
2637                         aopOp(IC_LEFT(sic),sic,FALSE);
2638                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2639                         freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2640                 }
2641                 
2642                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2643                 sic = setNextItem(_G.sendSet)) {
2644                         int size, offset = 0;
2645                         
2646                         aopOp(IC_LEFT(sic),sic,FALSE);
2647                         size = AOP_SIZE(IC_LEFT(sic));
2648                         
2649                         while (size--) {
2650                                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2651                                         AopType(AOP_TYPE(IC_LEFT(sic))));
2652                                 
2653                                 if(!firstTimeThruLoop) {
2654                                         /* If this is not the first time we've been through the loop
2655                                         * then we need to save the parameter in a temporary
2656                                         * register. The last byte of the last parameter is
2657                                         * passed in W. */
2658                                         emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2659                                         
2660                                 }
2661                                 firstTimeThruLoop=0;
2662                                 
2663                                 mov2w_op (IC_LEFT(sic),  offset);
2664                                 offset++;
2665                         }
2666                         freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2667                 }
2668                 _G.sendSet = NULL;
2669         }
2670         /* make the call */
2671         sym = OP_SYMBOL(IC_LEFT(ic));
2672         name = sym->rname[0] ? sym->rname : sym->name;
2673         isExtern = IS_EXTERN(sym->etype);
2674         if (isExtern) {
2675                 emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2676         }
2677         emitpcode(POC_CALL,popGetWithString(name,isExtern));
2678         if (isExtern) {
2679                 emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel to restore PCLATH before next goto or call instruction */
2680         }
2681         GpsuedoStkPtr=0;
2682         /* if we need assign a result value */
2683         if ((IS_ITEMP(IC_RESULT(ic)) && 
2684                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2685                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2686                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2687                 
2688                 _G.accInUse++;
2689                 aopOp(IC_RESULT(ic),ic,FALSE);
2690                 _G.accInUse--;
2691                 
2692                 assignResultValue(IC_RESULT(ic));
2693                 
2694                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2695                         AopType(AOP_TYPE(IC_RESULT(ic))));
2696                 
2697                 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2698         }
2699         
2700         /* if register bank was saved then pop them */
2701         if (ic->bankSaved)
2702                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2703         
2704         /* if we hade saved some registers then unsave them */
2705         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2706                 unsaveRegisters (ic);
2707         
2708         
2709 }
2710
2711 /*-----------------------------------------------------------------*/
2712 /* genPcall - generates a call by pointer statement                        */
2713 /*-----------------------------------------------------------------*/
2714 static void genPcall (iCode *ic)
2715 {
2716         sym_link *dtype;
2717         symbol *albl = newiTempLabel(NULL);
2718         symbol *blbl = newiTempLabel(NULL);
2719         PIC_OPCODE poc;
2720         pCodeOp *pcop;
2721         operand *left;
2722         
2723         FENTRY;
2724
2725         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2726         /* if caller saves & we have not saved then */
2727         if (!ic->regsSaved)
2728                 saveRegisters(ic);
2729         
2730                 /* if we are calling a function that is not using
2731                 the same register bank then we need to save the
2732         destination registers on the stack */
2733         dtype = operandType(IC_LEFT(ic));
2734         if (currFunc && dtype && 
2735                 IFFUNC_ISISR(currFunc->type) &&
2736                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2737                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2738         
2739         left = IC_LEFT(ic);
2740         aopOp(left,ic,FALSE);
2741         DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2742         
2743         poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2744         
2745         pushSide(IC_LEFT(ic), FPTRSIZE);
2746         
2747         /* if send set is not empty, assign parameters */
2748         if (_G.sendSet) {
2749                 
2750                 DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2751                 /* no way to pass args - W always gets used to make the call */
2752         }
2753         /* first idea - factor out a common helper function and call it.
2754         But don't know how to get it generated only once in its own block
2755         
2756         if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2757                 char *rname;
2758                 char *buffer;
2759                 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2760                 DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2761                 buffer = Safe_calloc(1,strlen(rname)+16);
2762                 sprintf(buffer, "%s_goto_helper", rname);
2763                 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2764                 free(buffer);
2765         }
2766         */
2767         emitpcode(POC_CALL,popGetLabel(albl->key));
2768         pcop = popGetLabel(blbl->key);
2769         emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
2770         emitpcode(POC_GOTO,pcop);
2771         emitpLabel(albl->key);
2772         
2773         emitpcode(poc,popGetAddr(AOP(left),1,0));
2774         emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2775         emitpcode(poc,popGetAddr(AOP(left),0,0));
2776         emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2777         
2778         emitpLabel(blbl->key);
2779         
2780         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2781         
2782         /* if we need to assign a result value */
2783         if ((IS_ITEMP(IC_RESULT(ic)) &&
2784                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2785                 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2786                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2787                 
2788                 _G.accInUse++;
2789                 aopOp(IC_RESULT(ic),ic,FALSE);
2790                 _G.accInUse--;
2791
2792                 GpsuedoStkPtr = 0;
2793                 
2794                 assignResultValue(IC_RESULT(ic));
2795                 
2796                 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2797         }
2798         
2799         /* if register bank was saved then unsave them */
2800         if (currFunc && dtype && 
2801                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2802                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2803         
2804                 /* if we hade saved some registers then
2805         unsave them */
2806         if (ic->regsSaved)
2807                 unsaveRegisters (ic);
2808         
2809 }
2810
2811 /*-----------------------------------------------------------------*/
2812 /* resultRemat - result  is rematerializable                                       */
2813 /*-----------------------------------------------------------------*/
2814 static int resultRemat (iCode *ic)
2815 {
2816         //      DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2817         FENTRY;
2818
2819         if (SKIP_IC(ic) || ic->op == IFX)
2820                 return 0;
2821         
2822         if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2823                 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2824                 if (sym->remat && !POINTER_SET(ic)) 
2825                         return 1;
2826         }
2827         
2828         return 0;
2829 }
2830
2831 #if defined(__BORLANDC__) || defined(_MSC_VER)
2832 #define STRCASECMP stricmp
2833 #else
2834 #define STRCASECMP strcasecmp
2835 #endif
2836
2837 #if 0
2838 /*-----------------------------------------------------------------*/
2839 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2840 /*-----------------------------------------------------------------*/
2841 static bool inExcludeList(char *s)
2842 {
2843         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2844         int i =0;
2845         
2846         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2847         if (options.excludeRegs[i] &&
2848                 STRCASECMP(options.excludeRegs[i],"none") == 0)
2849                 return FALSE ;
2850         
2851         for ( i = 0 ; options.excludeRegs[i]; i++) {
2852                 if (options.excludeRegs[i] &&
2853                         STRCASECMP(s,options.excludeRegs[i]) == 0)
2854                         return TRUE;
2855         }
2856         return FALSE ;
2857 }
2858 #endif
2859
2860 /*-----------------------------------------------------------------*/
2861 /* genFunction - generated code for function entry                                 */
2862 /*-----------------------------------------------------------------*/
2863 static void genFunction (iCode *ic)
2864 {
2865         symbol *sym;
2866         sym_link *ftype;
2867         
2868         FENTRY;
2869
2870         DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2871         
2872         labelOffset += (max_key+4);
2873         max_key=0;
2874         GpsuedoStkPtr=0;
2875         _G.nRegsSaved = 0;
2876         /* create the function header */
2877         pic14_emitcode(";","-----------------------------------------");
2878         pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2879         pic14_emitcode(";","-----------------------------------------");
2880         
2881         pic14_emitcode("","%s:",sym->rname);
2882         addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2883         
2884         ftype = operandType(IC_LEFT(ic));
2885         
2886         /* if critical function then turn interrupts off */
2887         if (IFFUNC_ISCRITICAL(ftype))
2888                 pic14_emitcode("clr","ea");
2889         
2890                 /* here we need to generate the equates for the
2891         register bank if required */
2892 #if 0
2893         if (FUNC_REGBANK(ftype) != rbank) {
2894                 int i ;
2895                 
2896                 rbank = FUNC_REGBANK(ftype);
2897                 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2898                         if (strcmp(regspic14[i].base,"0") == 0)
2899                                 pic14_emitcode("","%s = 0x%02x",
2900                                 regspic14[i].dname,
2901                                 8*rbank+regspic14[i].offset);
2902                         else
2903                                 pic14_emitcode ("","%s = %s + 0x%02x",
2904                                 regspic14[i].dname,
2905                                 regspic14[i].base,
2906                                 8*rbank+regspic14[i].offset);
2907                 }
2908         }
2909 #endif
2910         
2911         /* if this is an interrupt service routine */
2912         if (IFFUNC_ISISR(sym->type)) {
2913         /*  already done in pic14createInterruptVect() - delete me
2914         addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2915         emitpcodeNULLop(POC_NOP);
2916         emitpcodeNULLop(POC_NOP);
2917         emitpcodeNULLop(POC_NOP);
2918                 */
2919                 emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2920                 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2921                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2922                 emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2923                 emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2924                 emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2925                 emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2926                 
2927                 pBlockConvert2ISR(pb);
2928 #if 0  
2929                 if (!inExcludeList("acc"))              
2930                         pic14_emitcode ("push","acc");  
2931                 if (!inExcludeList("b"))
2932                         pic14_emitcode ("push","b");
2933                 if (!inExcludeList("dpl"))
2934                         pic14_emitcode ("push","dpl");
2935                 if (!inExcludeList("dph"))
2936                         pic14_emitcode ("push","dph");
2937                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2938                 {
2939                         pic14_emitcode ("push", "dpx");
2940                         /* Make sure we're using standard DPTR */
2941                         pic14_emitcode ("push", "dps");
2942                         pic14_emitcode ("mov", "dps, #0x00");
2943                         if (options.stack10bit)
2944                         { 
2945                                 /* This ISR could conceivably use DPTR2. Better save it. */
2946                                 pic14_emitcode ("push", "dpl1");
2947                                 pic14_emitcode ("push", "dph1");
2948                                 pic14_emitcode ("push", "dpx1");
2949                         }
2950                 }
2951                 /* if this isr has no bank i.e. is going to
2952                 run with bank 0 , then we need to save more
2953                 registers :-) */
2954                 if (!FUNC_REGBANK(sym->type)) {
2955                         
2956                 /* if this function does not call any other
2957                 function then we can be economical and
2958                         save only those registers that are used */
2959                         if (! IFFUNC_HASFCALL(sym->type)) {
2960                                 int i;
2961                                 
2962                                 /* if any registers used */
2963                                 if (sym->regsUsed) {
2964                                         /* save the registers used */
2965                                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2966                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2967                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2968                                                         pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);               
2969                                         }
2970                                 }
2971                                 
2972                         } else {
2973                         /* this function has    a function call cannot
2974                         determines register usage so we will have the
2975                                 entire bank */
2976                                 saverbank(0,ic,FALSE);
2977                         }       
2978                 }
2979 #endif
2980         } else {
2981         /* if callee-save to be used for this function
2982                 then save the registers being used in this function */
2983                 if (IFFUNC_CALLEESAVES(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","%s",pic14_regWithIdx(i)->dname);
2993                                                 _G.nRegsSaved++;
2994                                         }
2995                                 }
2996                         }
2997                 }
2998         }
2999         
3000         /* set the register bank to the desired value */
3001         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
3002                 pic14_emitcode("push","psw");
3003                 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);       
3004         }
3005         
3006         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3007                 
3008                 if (options.useXstack) {
3009                         pic14_emitcode("mov","r0,%s",spname);
3010                         pic14_emitcode("mov","a,_bp");
3011                         pic14_emitcode("movx","@r0,a");
3012                         pic14_emitcode("inc","%s",spname);
3013                 }
3014                 else
3015                 {
3016                         /* set up the stack */
3017                         pic14_emitcode ("push","_bp");   /* save the callers stack      */
3018                 }
3019                 pic14_emitcode ("mov","_bp,%s",spname);
3020         }
3021         
3022         /* adjust the stack for the function */
3023         if (sym->stack) {
3024                 
3025                 int i = sym->stack;
3026                 if (i > 256 ) 
3027                         werror(W_STACK_OVERFLOW,sym->name);
3028                 
3029                 if (i > 3 && sym->recvSize < 4) {                
3030                         
3031                         pic14_emitcode ("mov","a,sp");
3032                         pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3033                         pic14_emitcode ("mov","sp,a");
3034                         
3035                 }
3036                 else
3037                         while(i--)
3038                                 pic14_emitcode("inc","sp");
3039         }
3040         
3041         if (sym->xstack) {
3042                 
3043                 pic14_emitcode ("mov","a,_spx");
3044                 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3045                 pic14_emitcode ("mov","_spx,a");
3046         }
3047         
3048 }
3049
3050 /*-----------------------------------------------------------------*/
3051 /* genEndFunction - generates epilogue for functions                       */
3052 /*-----------------------------------------------------------------*/
3053 static void genEndFunction (iCode *ic)
3054 {
3055         symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3056         
3057         FENTRY;
3058
3059         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3060         
3061         if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3062         {
3063                 pic14_emitcode ("mov","%s,_bp",spname);
3064         }
3065         
3066         /* if use external stack but some variables were
3067         added to the local stack then decrement the
3068         local stack */
3069         if (options.useXstack && sym->stack) {    
3070                 pic14_emitcode("mov","a,sp");
3071                 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3072                 pic14_emitcode("mov","sp,a");
3073         }
3074         
3075         
3076         if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3077                 if (options.useXstack) {
3078                         pic14_emitcode("mov","r0,%s",spname);
3079                         pic14_emitcode("movx","a,@r0");
3080                         pic14_emitcode("mov","_bp,a");
3081                         pic14_emitcode("dec","%s",spname);
3082                 }
3083                 else
3084                 {
3085                         pic14_emitcode ("pop","_bp");
3086                 }
3087         }
3088         
3089         /* restore the register bank    */        
3090         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3091                 pic14_emitcode ("pop","psw");
3092         
3093         if (IFFUNC_ISISR(sym->type)) {
3094                 
3095                 /* now we need to restore the registers */
3096                 /* if this isr has no bank i.e. is going to
3097                 run with bank 0 , then we need to save more
3098 registers :-) */
3099                 if (!FUNC_REGBANK(sym->type)) {
3100                         
3101                 /* if this function does not call any other
3102                 function then we can be economical and
3103                         save only those registers that are used */
3104                         if (! IFFUNC_HASFCALL(sym->type)) {
3105                                 int i;
3106                                 
3107                                 /* if any registers used */
3108                                 if (sym->regsUsed) {
3109                                         /* save the registers used */
3110                                         for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3111                                                 if (bitVectBitValue(sym->regsUsed,i) ||
3112                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3113                                                         pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3114                                         }
3115                                 }
3116                                 
3117                         } else {
3118                         /* this function has    a function call cannot
3119                         determines register usage so we will have the
3120                                 entire bank */
3121                                 unsaverbank(0,ic,FALSE);
3122                         }       
3123                 }
3124 #if 0
3125                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3126                 {
3127                         if (options.stack10bit)
3128                         {
3129                                 pic14_emitcode ("pop", "dpx1");
3130                                 pic14_emitcode ("pop", "dph1");
3131                                 pic14_emitcode ("pop", "dpl1");
3132                         } 
3133                         pic14_emitcode ("pop", "dps");
3134                         pic14_emitcode ("pop", "dpx");
3135                 }
3136                 if (!inExcludeList("dph"))
3137                         pic14_emitcode ("pop","dph");
3138                 if (!inExcludeList("dpl"))
3139                         pic14_emitcode ("pop","dpl");
3140                 if (!inExcludeList("b"))
3141                         pic14_emitcode ("pop","b");
3142                 if (!inExcludeList("acc"))
3143                         pic14_emitcode ("pop","acc");
3144                 
3145                 if (IFFUNC_ISCRITICAL(sym->type))
3146                         pic14_emitcode("setb","ea");
3147 #endif
3148                 
3149                 /* if debug then send end of function */
3150                 /*      if (options.debug && currFunc) { */
3151                 if (currFunc) {
3152                         debugFile->writeEndFunction (currFunc, ic, 1);
3153                 }
3154                 
3155                 pic14_emitcode ("reti","");
3156                 emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
3157                 emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
3158                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
3159                 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3160                 emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
3161                 emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
3162                 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3163                 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3164                 emitpcodeNULLop(POC_RETFIE);
3165         }
3166         else {
3167                 if (IFFUNC_ISCRITICAL(sym->type))
3168                         pic14_emitcode("setb","ea");
3169                 
3170                 if (IFFUNC_CALLEESAVES(sym->type)) {
3171                         int i;
3172                         
3173                         /* if any registers used */
3174                         if (sym->regsUsed) {
3175                                 /* save the registers used */
3176                                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3177                                         if (bitVectBitValue(sym->regsUsed,i) ||
3178                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3179                                                 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3180                                 }
3181                         }
3182                         
3183                 }
3184                 
3185                 /* if debug then send end of function */
3186                 if (currFunc) {
3187                         debugFile->writeEndFunction (currFunc, ic, 1);
3188                 }
3189                 
3190                 pic14_emitcode ("return","");
3191                 emitpcodeNULLop(POC_RETURN);
3192                 
3193                 /* Mark the end of a function */
3194                 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3195         }
3196         
3197 }
3198
3199 /*-----------------------------------------------------------------*/
3200 /* genRet - generate code for return statement                                     */
3201 /*-----------------------------------------------------------------*/
3202 static void genRet (iCode *ic)
3203 {
3204         int size,offset = 0;
3205         
3206         FENTRY;
3207
3208         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3209         /* if we have no return value then
3210         just generate the "ret" */
3211         if (!IC_LEFT(ic)) 
3212                 goto jumpret;           
3213         
3214                 /* we have something to return then
3215         move the return value into place */
3216         aopOp(IC_LEFT(ic),ic,FALSE);
3217         size = AOP_SIZE(IC_LEFT(ic));
3218
3219         for (offset = 0; offset < size; offset++)
3220         {
3221                 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3222         }
3223         
3224         freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3225         
3226 jumpret:
3227         /* generate a jump to the return label
3228         if the next is not the return statement */
3229         if (!(ic->next && ic->next->op == LABEL &&
3230                 IC_LABEL(ic->next) == returnLabel)) {
3231                 
3232                 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3233         }
3234         
3235 }
3236
3237 /*-----------------------------------------------------------------*/
3238 /* genLabel - generates a label                                                                    */
3239 /*-----------------------------------------------------------------*/
3240 static void genLabel (iCode *ic)
3241 {
3242         FENTRY;
3243
3244         /* special case never generate */
3245         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3246         if (IC_LABEL(ic) == entryLabel)
3247                 return ;
3248         
3249         emitpLabel(IC_LABEL(ic)->key);
3250         pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3251 }
3252
3253 /*-----------------------------------------------------------------*/
3254 /* genGoto - generates a goto                                                                      */
3255 /*-----------------------------------------------------------------*/
3256 //tsd
3257 static void genGoto (iCode *ic)
3258 {
3259         FENTRY;
3260
3261         emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3262         pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3263 }
3264
3265
3266 /*-----------------------------------------------------------------*/
3267 /* genMultbits :- multiplication of bits                                                   */
3268 /*-----------------------------------------------------------------*/
3269 static void genMultbits (operand *left, 
3270                                                  operand *right, 
3271                                                  operand *result)
3272 {
3273         FENTRY;
3274         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3275         
3276         if(!pic14_sameRegs(AOP(result),AOP(right)))
3277                 emitpcode(POC_BSF,      popGet(AOP(result),0));
3278         
3279         emitpcode(POC_BTFSC,popGet(AOP(right),0));
3280         emitpcode(POC_BTFSS,popGet(AOP(left),0));
3281         emitpcode(POC_BCF,  popGet(AOP(result),0));
3282         
3283 }
3284
3285
3286 /*-----------------------------------------------------------------*/
3287 /* genMultOneByte : 8 bit multiplication & division                        */
3288 /*-----------------------------------------------------------------*/
3289 static void genMultOneByte (operand *left,
3290                                                         operand *right,
3291                                                         operand *result)
3292 {
3293         char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3294         
3295         // symbol *lbl ;
3296         int size,offset,i;
3297         
3298         
3299         FENTRY;
3300         
3301         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3302         DEBUGpic14_AopType(__LINE__,left,right,result);
3303         DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3304         
3305         /* (if two literals, the value is computed before) */
3306         /* if one literal, literal on the right */
3307         if (AOP_TYPE(left) == AOP_LIT){
3308                 operand *t = right;
3309                 right = left;
3310                 left = t;
3311         }
3312
3313         assert (AOP_SIZE(left) == AOP_SIZE(right));
3314         
3315         size = min(AOP_SIZE(result),AOP_SIZE(left));
3316         offset = Gstack_base_addr - (2*size - 1);
3317
3318         /* pass right operand as argument */
3319         for (i=0; i < size; i++)
3320         {
3321                 mov2w (AOP(right), i);
3322                 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3323         } // for
3324         
3325         /* pass left operand as argument */
3326         for (i=0; i < size; i++)
3327         {
3328                 mov2w (AOP(left), i);
3329                 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3330         } // for
3331         assert (offset == Gstack_base_addr);
3332         
3333         /* call library routine */
3334         assert (size > 0 && size <= 4);
3335         call_libraryfunc (func[size]);
3336         
3337         /* assign result */
3338         movwf (AOP(result), size-1);
3339         for (i=0; i < size - 1; i++)
3340         {
3341                 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3342                 movwf (AOP(result), size - 2 - i);
3343         } // for
3344
3345         /* now (zero-/sign) extend the result to its size */
3346         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3347 }
3348
3349 /*-----------------------------------------------------------------*/
3350 /* genMult - generates code for multiplication                                     */
3351 /*-----------------------------------------------------------------*/
3352 static void genMult (iCode *ic)
3353 {
3354         operand *left = IC_LEFT(ic);
3355         operand *right = IC_RIGHT(ic);
3356         operand *result= IC_RESULT(ic); 
3357         
3358         FENTRY;
3359
3360         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3361         /* assign the amsops */
3362         aopOp (left,ic,FALSE);
3363         aopOp (right,ic,FALSE);
3364         aopOp (result,ic,TRUE);
3365         
3366         DEBUGpic14_AopType(__LINE__,left,right,result);
3367         
3368         /* special cases first */
3369         /* both are bits */
3370         if (AOP_TYPE(left) == AOP_CRY &&
3371                 AOP_TYPE(right)== AOP_CRY) {
3372                 genMultbits(left,right,result);
3373                 goto release ;
3374         }
3375         
3376         /* if both are of size == 1 */
3377         if (AOP_SIZE(left) == 1 &&
3378                 AOP_SIZE(right) == 1 ) {
3379                 genMultOneByte(left,right,result);
3380                 goto release ;
3381         }
3382         
3383         /* should have been converted to function call */
3384         assert(0) ;
3385         
3386 release :
3387         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3388         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3389         freeAsmop(result,NULL,ic,TRUE); 
3390 }
3391
3392 /*-----------------------------------------------------------------*/
3393 /* genDivbits :- division of bits                                                                  */
3394 /*-----------------------------------------------------------------*/
3395 static void genDivbits (operand *left, 
3396                                                 operand *right, 
3397                                                 operand *result)
3398 {
3399         
3400         char *l;
3401         
3402         FENTRY;
3403
3404         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3405         /* the result must be bit */      
3406         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3407         l = aopGet(AOP(left),0,FALSE,FALSE);
3408         
3409         MOVA(l);          
3410         
3411         pic14_emitcode("div","ab");
3412         pic14_emitcode("rrc","a");
3413         aopPut(AOP(result),"c",0);
3414 }
3415
3416 /*-----------------------------------------------------------------*/
3417 /* genDivOneByte : 8 bit division                                                                  */
3418 /*-----------------------------------------------------------------*/
3419 static void genDivOneByte (operand *left,
3420                                                    operand *right,
3421                                                    operand *result)
3422 {
3423         int size;
3424         
3425         FENTRY;
3426         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3427         
3428         assert (AOP_SIZE(result) == 1);
3429         assert (AOP_SIZE(right) == 1);
3430         assert (AOP_SIZE(left) == 1);
3431
3432         size = min(AOP_SIZE(result),AOP_SIZE(left));
3433
3434         if (AOP_TYPE(right) == AOP_LIT)
3435         {
3436                 /* XXX: might add specialized code */
3437         }
3438
3439         if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3440         {
3441                 /* unsigned division */
3442         #if 1
3443                 mov2w(AOP(right),0);
3444                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3445                 mov2w(AOP(left),0);
3446                 call_libraryfunc("__divuchar");
3447                 movwf(AOP(result),0);
3448         #else
3449                 pCodeOp *temp;
3450                 symbol *lbl;
3451
3452                 temp = popGetTempReg();
3453                 lbl = newiTempLabel(NULL);
3454                 
3455                 /* XXX: improve this naive approach:
3456                    [result] = [a] / [b]
3457                         ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3458
3459                    In PIC assembler:
3460                    movf  left,W
3461                    movwf temp           // temp <-- left
3462                    movf  right,W        // W <-- right
3463                    clrf  result
3464                    label1:
3465                    incf  result
3466                    subwf temp,F         // temp <-- temp - W
3467                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if temp < W
3468                    goto  label1
3469                    decf result          // we just subtract once too often
3470                  */
3471
3472                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3473                 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3474                 
3475                 mov2w(AOP(left),0);
3476                 emitpcode(POC_MOVWF, temp);
3477                 mov2w(AOP(right),0);
3478                 emitpcode(POC_CLRF, popGet(AOP(result),0));
3479
3480                 emitpLabel(lbl->key);
3481                 emitpcode(POC_INCF, popGet(AOP(result),0));
3482                 emitpcode(POC_SUBWF, temp);
3483                 emitSKPNC;
3484                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3485                 emitpcode(POC_DECF, popGet(AOP(result),0));
3486         #endif
3487         }
3488         else
3489         {
3490                 /* signed division */
3491                 mov2w(AOP(right),0);
3492                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3493                 mov2w(AOP(left),0);
3494                 call_libraryfunc("__divschar");
3495                 movwf(AOP(result),0);
3496         }
3497
3498         /* now performed the signed/unsigned division -- extend result */
3499         addSign(result, 1, !SPEC_USIGN(operandType(result)));
3500 }
3501
3502 /*-----------------------------------------------------------------*/
3503 /* genDiv - generates code for division                            */
3504 /*-----------------------------------------------------------------*/
3505 static void genDiv (iCode *ic)
3506 {
3507         operand *left = IC_LEFT(ic);
3508         operand *right = IC_RIGHT(ic);
3509         operand *result= IC_RESULT(ic); 
3510         
3511         FENTRY;
3512         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3513         /* assign the amsops */
3514         aopOp (left,ic,FALSE);
3515         aopOp (right,ic,FALSE);
3516         aopOp (result,ic,TRUE);
3517         
3518         /* special cases first */
3519         /* both are bits */
3520         if (AOP_TYPE(left) == AOP_CRY &&
3521                 AOP_TYPE(right)== AOP_CRY) {
3522                 genDivbits(left,right,result);
3523                 goto release ;
3524         }
3525         
3526         /* if both are of size == 1 */
3527         if (AOP_SIZE(left) == 1 &&
3528                 AOP_SIZE(right) == 1 ) {
3529                 genDivOneByte(left,right,result);
3530                 goto release ;
3531         }
3532         
3533         /* should have been converted to function call */
3534         assert(0);
3535 release :
3536         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3537         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3538         freeAsmop(result,NULL,ic,TRUE); 
3539 }
3540
3541 /*-----------------------------------------------------------------*/
3542 /* genModbits :- modulus of bits                                                                   */
3543 /*-----------------------------------------------------------------*/
3544 static void genModbits (operand *left, 
3545                                                 operand *right, 
3546                                                 operand *result)
3547 {
3548         
3549         char *l;
3550         
3551         FENTRY;
3552         /* the result must be bit */      
3553         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3554         l = aopGet(AOP(left),0,FALSE,FALSE);
3555         
3556         MOVA(l);
3557         
3558         pic14_emitcode("div","ab");
3559         pic14_emitcode("mov","a,b");
3560         pic14_emitcode("rrc","a");
3561         aopPut(AOP(result),"c",0);
3562 }
3563
3564 /*-----------------------------------------------------------------*/
3565 /* genModOneByte : 8 bit modulus                                                                   */
3566 /*-----------------------------------------------------------------*/
3567 static void genModOneByte (operand *left,
3568                                                    operand *right,
3569                                                    operand *result)
3570 {
3571         int size;
3572         
3573         FENTRY;
3574         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3575         
3576         assert (AOP_SIZE(result) == 1);
3577         assert (AOP_SIZE(right) == 1);
3578         assert (AOP_SIZE(left) == 1);
3579
3580         size = min(AOP_SIZE(result),AOP_SIZE(left));
3581
3582         if (AOP_TYPE(right) == AOP_LIT)
3583         {
3584                 /* XXX: might add specialized code */
3585         }
3586
3587         if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3588         {
3589                 /* unsigned division */
3590         #if 1
3591                 mov2w(AOP(right),0);
3592                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3593                 mov2w(AOP(left),0);
3594                 call_libraryfunc("__moduchar");
3595                 movwf(AOP(result),0);
3596         #else
3597                 pCodeOp *temp;
3598                 symbol *lbl;
3599
3600                 lbl = newiTempLabel(NULL);
3601                 
3602                 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3603
3604                 /* XXX: improve this naive approach:
3605                    [result] = [a] % [b]
3606                         ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3607
3608                    In PIC assembler:
3609                    movf  left,W
3610                    movwf result         // result <-- left
3611                    movf  right,W        // W <-- right
3612                    label1:
3613                    subwf result,F       // result <-- result - W
3614                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if result < W
3615                    goto  label1
3616                    addwf result, F      // we just subtract once too often
3617                  */
3618
3619                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3620                 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3621                 
3622                 if (!pic14_sameRegs(AOP(left), AOP(result)))
3623                 {
3624                         mov2w(AOP(left),0);
3625                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
3626                 }
3627                 mov2w(AOP(right),0);
3628
3629                 emitpLabel(lbl->key);
3630                 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3631                 emitSKPNC;
3632                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3633                 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3634         #endif
3635         }
3636         else
3637         {
3638                 /* signed division */
3639                 mov2w(AOP(right),0);
3640                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3641                 mov2w(AOP(left),0);
3642                 call_libraryfunc("__modschar");
3643                 movwf(AOP(result),0);
3644         }
3645
3646         /* now we performed the signed/unsigned modulus -- extend result */
3647         addSign(result, 1, !SPEC_USIGN(operandType(result)));
3648 }
3649
3650 /*-----------------------------------------------------------------*/
3651 /* genMod - generates code for division                                                    */
3652 /*-----------------------------------------------------------------*/
3653 static void genMod (iCode *ic)
3654 {
3655         operand *left = IC_LEFT(ic);
3656         operand *right = IC_RIGHT(ic);
3657         operand *result= IC_RESULT(ic);  
3658         
3659         FENTRY;
3660         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3661         /* assign the amsops */
3662         aopOp (left,ic,FALSE);
3663         aopOp (right,ic,FALSE);
3664         aopOp (result,ic,TRUE);
3665         
3666         /* special cases first */
3667         /* both are bits */
3668         if (AOP_TYPE(left) == AOP_CRY &&
3669                 AOP_TYPE(right)== AOP_CRY) {
3670                 genModbits(left,right,result);
3671                 goto release ;
3672         }
3673         
3674         /* if both are of size == 1 */
3675         if (AOP_SIZE(left) == 1 &&
3676                 AOP_SIZE(right) == 1 ) {
3677                 genModOneByte(left,right,result);
3678                 goto release ;
3679         }
3680         
3681         /* should have been converted to function call */
3682         assert(0);
3683         
3684 release :
3685         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3686         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3687         freeAsmop(result,NULL,ic,TRUE); 
3688 }
3689
3690 /*-----------------------------------------------------------------*/
3691 /* genIfxJump :- will create a jump depending on the ifx                   */
3692 /*-----------------------------------------------------------------*/
3693 /*
3694 note: May need to add parameter to indicate when a variable is in bit space.
3695 */
3696 static void genIfxJump (iCode *ic, char *jval)
3697 {
3698         
3699         FENTRY;
3700         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3701         /* if true label then we jump if condition
3702         supplied is true */
3703         if ( IC_TRUE(ic) ) {
3704                 
3705                 if(strcmp(jval,"a") == 0)
3706                         emitSKPZ;
3707                 else if (strcmp(jval,"c") == 0)
3708                         emitSKPC;
3709                 else {
3710                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3711                         emitpcode(POC_BTFSC,    newpCodeOpBit(jval,-1,1));
3712                 }
3713                 
3714                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3715                 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3716                 
3717         }
3718         else {
3719                 /* false label is present */
3720                 if(strcmp(jval,"a") == 0)
3721                         emitSKPNZ;
3722                 else if (strcmp(jval,"c") == 0)
3723                         emitSKPNC;
3724                 else {
3725                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3726                         emitpcode(POC_BTFSS,    newpCodeOpBit(jval,-1,1));
3727                 }
3728                 
3729                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3730                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3731                 
3732         }
3733         
3734         
3735         /* mark the icode as generated */
3736         ic->generated = 1;
3737 }
3738
3739 #if 0
3740 /*-----------------------------------------------------------------*/
3741 /* genSkip                                                                                                                 */
3742 /*-----------------------------------------------------------------*/
3743 static void genSkip(iCode *ifx,int status_bit)
3744 {
3745         FENTRY;
3746         if(!ifx)
3747                 return;
3748         
3749         if ( IC_TRUE(ifx) ) {
3750                 switch(status_bit) {
3751                 case 'z':
3752                         emitSKPNZ;
3753                         break;
3754                         
3755                 case 'c':
3756                         emitSKPNC;
3757                         break;
3758                         
3759                 case 'd':
3760                         emitSKPDC;
3761                         break;
3762                         
3763                 }
3764                 
3765                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3766                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3767                 
3768         } else {
3769                 
3770                 switch(status_bit) {
3771                         
3772                 case 'z':
3773                         emitSKPZ;
3774                         break;
3775                         
3776                 case 'c':
3777                         emitSKPC;
3778                         break;
3779                         
3780                 case 'd':
3781                         emitSKPDC;
3782                         break;
3783                 }
3784                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3785                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3786                 
3787         }
3788         
3789 }
3790 #endif
3791
3792 /*-----------------------------------------------------------------*/
3793 /* genSkipc                                                                                                        */
3794 /*-----------------------------------------------------------------*/
3795 static void genSkipc(resolvedIfx *rifx)
3796 {
3797         FENTRY;
3798         if(!rifx)
3799                 return;
3800         
3801         if(rifx->condition)
3802                 emitSKPNC;
3803         else
3804                 emitSKPC;
3805         
3806         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3807         emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3808         rifx->generated = 1;
3809 }
3810
3811 #if 0
3812 /*-----------------------------------------------------------------*/
3813 /* genSkipz2                                                                                                       */
3814 /*-----------------------------------------------------------------*/
3815 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3816 {
3817         FENTRY;
3818         if(!rifx)
3819                 return;
3820         
3821         if( (rifx->condition ^ invert_condition) & 1)
3822                 emitSKPZ;
3823         else
3824                 emitSKPNZ;
3825         
3826         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3827         rifx->generated = 1;
3828 }
3829 #endif
3830
3831 #if 0
3832 /*-----------------------------------------------------------------*/
3833 /* genSkipz                                                        */
3834 /*-----------------------------------------------------------------*/
3835 static void genSkipz(iCode *ifx, int condition)
3836 {
3837         FENTRY;
3838         assert (ifx != NULL);
3839         
3840         if(condition)
3841                 emitSKPNZ;
3842         else
3843                 emitSKPZ;
3844         
3845         if ( IC_TRUE(ifx) )
3846                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3847         else
3848                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3849         
3850         if ( IC_TRUE(ifx) )
3851                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3852         else
3853                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3854         
3855 }
3856 #endif
3857
3858 #if 0
3859 /*-----------------------------------------------------------------*/
3860 /* genSkipCond                                                     */
3861 /*-----------------------------------------------------------------*/
3862 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3863 {
3864         FENTRY;
3865         if(!rifx)
3866                 return;
3867         
3868         if(rifx->condition)
3869                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3870         else
3871                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3872         
3873         
3874         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3875         rifx->generated = 1;
3876 }
3877 #endif
3878
3879 #if 0
3880 /*-----------------------------------------------------------------*/
3881 /* genChkZeroes :- greater or less than comparison                 */
3882 /*     For each byte in a literal that is zero, inclusive or the   */
3883 /*     the corresponding byte in the operand with W                */
3884 /*     returns true if any of the bytes are zero                   */
3885 /*-----------------------------------------------------------------*/
3886 static int genChkZeroes(operand *op, int lit,  int size)
3887 {
3888         
3889         int i;
3890         int flag =1;
3891         
3892         while(size--) {
3893                 i = (lit >> (size*8)) & 0xff;
3894                 
3895                 if(i==0) {
3896                         if(flag) 
3897                                 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3898                         else
3899                                 emitpcode(POC_IORFW, popGet(AOP(op),size));
3900                         flag = 0;
3901                 }
3902         }
3903         
3904         return (flag==0);
3905 }
3906 #endif
3907
3908
3909 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3910 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
3911 #define DEBUGpc           emitpComment
3912
3913 /*-----------------------------------------------------------------*/
3914 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
3915 /*                  aop (if it's NOT a literal) or from lit (if    */
3916 /*                  aop is a literal)                              */
3917 /*-----------------------------------------------------------------*/
3918 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3919   if (aop->type == AOP_LIT) {
3920     emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3921   } else {
3922     emitpcode (POC_MOVFW, popGet (aop, offset));
3923   }
3924 }
3925
3926 /* genCmp performs a left < right comparison, stores
3927  * the outcome in result (if != NULL) and generates
3928  * control flow code for the ifx (if != NULL).
3929  *
3930  * This version leaves in sequences like
3931  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3932  * which should be optmized by the peephole
3933  * optimizer - RN 2005-01-01 */
3934 static void genCmp (operand *left,operand *right,
3935                     operand *result, iCode *ifx, int sign)
3936 {
3937   resolvedIfx rIfx;
3938   int size;
3939   int offs;
3940   symbol *templbl;
3941   operand *dummy;
3942   unsigned long lit;
3943   unsigned long mask;
3944   int performedLt;
3945   int invert_result = 0;
3946
3947   FENTRY;
3948   
3949   assert (AOP_SIZE(left) == AOP_SIZE(right));
3950   assert (left && right);
3951
3952   size = AOP_SIZE(right) - 1;
3953   mask = (0x100UL << (size*8)) - 1;
3954   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3955   performedLt = 1;
3956   templbl = NULL;
3957   lit = 0;
3958   
3959   resolveIfx (&rIfx, ifx);
3960
3961   /**********************************************************************
3962    * handle bits - bit compares are promoted to int compares seemingly! *
3963    **********************************************************************/
3964 #if 0
3965   // THIS IS COMPLETELY UNTESTED!
3966   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3967     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3968     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3969     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3970
3971     emitSETC;
3972     // 1 < {0,1} is false --> clear C by skipping the next instruction
3973     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3974     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3975     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3976     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3977     emitCLRC; // only skipped for left=0 && right=1
3978
3979     goto correct_result_in_carry;
3980   } // if
3981 #endif
3982
3983   /*************************************************
3984    * make sure that left is register (or the like) *
3985    *************************************************/
3986   if (!isAOP_REGlike(left)) {
3987     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3988     assert (isAOP_LIT(left));
3989     assert (isAOP_REGlike(right));
3990     // swap left and right
3991     // left < right <==> right > left <==> (right >= left + 1)
3992     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3993
3994     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
3995       // MAXVALUE < right? always false
3996       if (performedLt) emitCLRC; else emitSETC;
3997       goto correct_result_in_carry;
3998     } // if
3999
4000     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4001     // that's why we handled it above.
4002     lit++;
4003
4004     dummy = left;
4005     left = right;
4006     right = dummy;
4007
4008     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4009   } else if (isAOP_LIT(right)) {
4010     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4011   } // if
4012
4013   assert (isAOP_REGlike(left)); // left must be register or the like
4014   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4015
4016   /*************************************************
4017    * special cases go here                         *
4018    *************************************************/
4019
4020   if (isAOP_LIT(right)) {
4021     if (!sign) {
4022       // unsigned comparison to a literal
4023       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4024       if (lit == 0) {
4025         // unsigned left < 0? always false
4026         if (performedLt) emitCLRC; else emitSETC;
4027         goto correct_result_in_carry;
4028       }
4029     } else {
4030       // signed comparison to a literal
4031       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4032       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4033         // signed left < 0x80000000? always false
4034         if (performedLt) emitCLRC; else emitSETC;
4035         goto correct_result_in_carry;
4036       } else if (lit == 0) {
4037         // compare left < 0; set CARRY if SIGNBIT(left) is set
4038         if (performedLt) emitSETC; else emitCLRC;
4039         emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
4040         if (performedLt) emitCLRC; else emitSETC;
4041         goto correct_result_in_carry;
4042       }
4043     } // if (!sign)
4044   } // right is literal
4045
4046   /*************************************************
4047    * perform a general case comparison             *
4048    * make sure we get CARRY==1 <==> left >= right  *
4049    *************************************************/
4050   // compare most significant bytes
4051   //DEBUGpc ("comparing bytes at offset %d", size);
4052   if (!sign) {
4053     // unsigned comparison
4054     pic14_mov2w_regOrLit (AOP(right), lit, size);
4055     emitpcode (POC_SUBFW, popGet (AOP(left), size));
4056   } else {
4057     // signed comparison
4058     // (add 2^n to both operands then perform an unsigned comparison)
4059     if (isAOP_LIT(right)) {
4060       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4061       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4062
4063       if (litbyte == 0x80) {
4064         // left >= 0x80 -- always true, but more bytes to come
4065         mov2w (AOP(left), size);
4066         emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
4067         emitSETC;
4068       } else {
4069         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4070         mov2w (AOP(left), size);
4071         emitpcode (POC_ADDLW, popGetLit (0x80));
4072         emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4073       } // if
4074     } else {
4075       pCodeOp *pctemp = popGetTempReg();
4076       mov2w (AOP(left), size);
4077       emitpcode (POC_ADDLW, popGetLit (0x80));
4078       emitpcode (POC_MOVWF, pctemp);
4079       mov2w (AOP(right), size);
4080       emitpcode (POC_ADDLW, popGetLit (0x80));
4081       emitpcode (POC_SUBFW, pctemp);
4082       popReleaseTempReg(pctemp);
4083     }
4084   } // if (!sign)
4085
4086   // compare remaining bytes (treat as unsigned case from above)
4087   templbl = newiTempLabel ( NULL );
4088   offs = size;
4089   while (offs--) {
4090     //DEBUGpc ("comparing bytes at offset %d", offs);
4091     emitSKPZ;
4092     emitpcode (POC_GOTO, popGetLabel (templbl->key));
4093     pic14_mov2w_regOrLit (AOP(right), lit, offs);
4094     emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4095   } // while (offs)
4096   emitpLabel (templbl->key);
4097   goto result_in_carry;
4098
4099 result_in_carry:
4100   
4101   /****************************************************
4102    * now CARRY contains the result of the comparison: *
4103    * SUBWF sets CARRY iff                             *
4104    * F-W >= 0 <==> F >= W <==> !(F < W)               *
4105    * (F=left, W=right)                                *
4106    ****************************************************/
4107
4108   if (performedLt) {
4109     invert_result = 1;
4110     // value will be used in the following genSkipc()
4111     rIfx.condition ^= 1;
4112   } // if
4113
4114 correct_result_in_carry:
4115
4116   // assign result to variable (if neccessary)
4117   if (result && AOP_TYPE(result) != AOP_CRY) {
4118     //DEBUGpc ("assign result");
4119     size = AOP_SIZE(result);
4120     while (size--) {
4121       emitpcode (POC_CLRF, popGet (AOP(result), size));
4122     } // while
4123     if (invert_result) {
4124       emitSKPC;
4125       emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4126     } else {
4127       emitpcode (POC_RLF, popGet (AOP(result), 0));
4128     }
4129   } // if (result)
4130
4131   // perform conditional jump
4132   if (ifx) {
4133     //DEBUGpc ("generate control flow");
4134     genSkipc (&rIfx);
4135     ifx->generated = 1;
4136   } // if
4137 }
4138
4139
4140 #if 0
4141 /* OLD VERSION -- BUGGY, DO NOT USE */
4142
4143 /*-----------------------------------------------------------------*/
4144 /* genCmp :- greater or less than comparison                       */
4145 /*-----------------------------------------------------------------*/
4146 static void genCmp (operand *left,operand *right,
4147                                         operand *result, iCode *ifx, int sign)
4148 {
4149         int size; //, offset = 0 ;
4150         unsigned long lit = 0L,i = 0;
4151         resolvedIfx rFalseIfx;
4152         //  resolvedIfx rTrueIfx;
4153         symbol *truelbl;
4154
4155         FENTRY;
4156         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4157         /*
4158         if(ifx) {
4159         DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4160         DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4161         }
4162         */
4163         
4164         resolveIfx(&rFalseIfx,ifx);
4165         truelbl  = newiTempLabel(NULL);
4166         size = max(AOP_SIZE(left),AOP_SIZE(right));
4167         
4168         DEBUGpic14_AopType(__LINE__,left,right,result);
4169         
4170 #define _swapp
4171         
4172         /* if literal is on the right then swap with left */
4173         if ((AOP_TYPE(right) == AOP_LIT)) {
4174                 operand *tmp = right ;
4175                 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4176                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4177 #ifdef _swapp
4178                 
4179                 lit = (lit - 1) & mask;
4180                 right = left;
4181                 left = tmp;
4182                 rFalseIfx.condition ^= 1;
4183 #endif
4184                 
4185         } else if ((AOP_TYPE(left) == AOP_LIT)) {
4186                 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4187         }
4188         
4189         
4190         //if(IC_TRUE(ifx) == NULL)
4191         /* if left & right are bit variables */
4192         if (AOP_TYPE(left) == AOP_CRY &&
4193                 AOP_TYPE(right) == AOP_CRY ) {
4194                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4195                 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4196         } else {
4197         /* subtract right from left if at the
4198         end the carry flag is set then we know that
4199                 left is greater than right */
4200                 
4201                 symbol *lbl  = newiTempLabel(NULL);
4202                 
4203 #ifndef _swapp
4204                 if(AOP_TYPE(right) == AOP_LIT) {
4205                         
4206                         //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4207                         
4208                         DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4209                         
4210                         /* special cases */
4211                         
4212                         if(lit == 0) {
4213                                 
4214                                 if(sign != 0) 
4215                                         genSkipCond(&rFalseIfx,left,size-1,7);
4216                                 else 
4217                                         /* no need to compare to 0...*/
4218                                         /* NOTE: this is a de-generate compare that most certainly 
4219                                         *       creates some dead code. */
4220                                         emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4221                                 
4222                                 if(ifx) ifx->generated = 1;
4223                                 return;
4224                                 
4225                         }
4226                         size--;
4227                         
4228                         if(size == 0) {
4229                                 //i = (lit >> (size*8)) & 0xff;
4230                                 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4231                                 
4232                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4233                                 
4234                                 i = ((0-lit) & 0xff);
4235                                 if(sign) {
4236                                         if( i == 0x81) { 
4237                                         /* lit is 0x7f, all signed chars are less than
4238                                                 * this except for 0x7f itself */
4239                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4240                                                 genSkipz2(&rFalseIfx,0);
4241                                         } else {
4242                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4243                                                 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4244                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4245                                         }
4246                                         
4247                                 } else {
4248                                         if(lit == 1) {
4249                                                 genSkipz2(&rFalseIfx,1);
4250                                         } else {
4251                                                 emitpcode(POC_ADDLW, popGetLit(i));
4252                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4253                                         }
4254                                 }
4255                                 
4256                                 if(ifx) ifx->generated = 1;
4257                                 return;
4258                         }
4259                         
4260                         /* chars are out of the way. now do ints and longs */
4261                         
4262                         
4263                         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4264                         
4265                         /* special cases */
4266                         
4267                         if(sign) {
4268                                 
4269                                 if(lit == 0) {
4270                                         genSkipCond(&rFalseIfx,left,size,7);
4271                                         if(ifx) ifx->generated = 1;
4272                                         return;
4273                                 }
4274                                 
4275                                 if(lit <0x100) {
4276                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4277                                         
4278                                         //rFalseIfx.condition ^= 1;
4279                                         //genSkipCond(&rFalseIfx,left,size,7);
4280                                         //rFalseIfx.condition ^= 1;
4281                                         
4282                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4283                                         if(rFalseIfx.condition)
4284                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4285                                         else
4286                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4287                                         
4288                                         emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4289                                         emitpcode(POC_ADDFW, popGet(AOP(left),0));
4290                                         emitpcode(POC_MOVFW, popGet(AOP(left),1));
4291                                         
4292                                         while(size > 1)
4293                                                 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4294                                         
4295                                         if(rFalseIfx.condition) {
4296                                                 emitSKPZ;
4297                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4298                                                 
4299                                         } else {
4300                                                 emitSKPNZ;
4301                                         }
4302                                         
4303                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4304                                         emitpLabel(truelbl->key);
4305                                         if(ifx) ifx->generated = 1;
4306                                         return;
4307                                         
4308                                 }
4309                                 
4310                                 if(size == 1) {
4311                                         
4312                                         if( (lit & 0xff) == 0) {
4313                                                 /* lower byte is zero */
4314                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4315                                                 i = ((lit >> 8) & 0xff) ^0x80;
4316                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4317                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4318                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4319                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4320                                                 
4321                                                 
4322                                                 if(ifx) ifx->generated = 1;
4323                                                 return;
4324                                                 
4325                                         }
4326                                 } else {
4327                                         /* Special cases for signed longs */
4328                                         if( (lit & 0xffffff) == 0) {
4329                                                 /* lower byte is zero */
4330                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4331                                                 i = ((lit >> 8*3) & 0xff) ^0x80;
4332                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4333                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4334                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4335                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4336                                                 
4337                                                 
4338                                                 if(ifx) ifx->generated = 1;
4339                                                 return;
4340                                                 
4341                                         }
4342                                         
4343                                 }
4344                                 
4345                                 
4346                                 if(lit & (0x80 << (size*8))) {
4347                                         /* lit is negative */
4348                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4349                                         
4350                                         //genSkipCond(&rFalseIfx,left,size,7);
4351                                         
4352                                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4353                                         
4354                                         if(rFalseIfx.condition)
4355                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4356                                         else
4357                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4358                                         
4359                                         
4360                                 } else {
4361                                         /* lit is positive */
4362                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4363                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4364                                         if(rFalseIfx.condition)
4365                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4366                                         else
4367                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4368                                         
4369                                 }
4370                                 
4371                                 /* There are no more special cases, so perform a general compare */
4372                                 
4373                                 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4374                                 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4375                                 
4376                                 while(size--) {
4377                                         
4378                                         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4379                                         emitSKPNZ;
4380                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4381                                 }
4382                                 //rFalseIfx.condition ^= 1;
4383                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4384                                 
4385                                 emitpLabel(truelbl->key);
4386                                 
4387                                 if(ifx) ifx->generated = 1;
4388                                 return;
4389                                 
4390                                 
4391                         }
4392
4393
4394                         /* sign is out of the way. So now do an unsigned compare */
4395                         DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4396
4397
4398                         /* General case - compare to an unsigned literal on the right.*/
4399
4400                         i = (lit >> (size*8)) & 0xff;
4401                         emitpcode(POC_MOVLW, popGetLit(i));
4402                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4403                         while(size--) {
4404                                 i = (lit >> (size*8)) & 0xff;
4405                                 
4406                                 if(i) {
4407                                         emitpcode(POC_MOVLW, popGetLit(i));
4408                                         emitSKPNZ;
4409                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4410                                 } else {
4411                                 /* this byte of the lit is zero, 
4412                                         *if it's not the last then OR in the variable */
4413                                         if(size)
4414                                                 emitpcode(POC_IORFW, popGet(AOP(left),size));
4415                                 }
4416                         }
4417
4418
4419                 emitpLabel(lbl->key);
4420                 //if(emitFinalCheck)
4421                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4422                 if(sign)
4423                         emitpLabel(truelbl->key);
4424
4425                 if(ifx) ifx->generated = 1;
4426                 return;
4427
4428
4429                 }
4430 #endif  // _swapp
4431
4432                 if(AOP_TYPE(left) == AOP_LIT) {
4433                         //symbol *lbl = newiTempLabel(NULL);
4434                         
4435                         //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4436                         
4437                         
4438                         DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4439                         
4440                         /* Special cases */
4441                         if((lit == 0) && (sign == 0)){
4442                                 
4443                                 size--;
4444                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4445                                 while(size) 
4446                                         emitpcode(POC_IORFW, popGet(AOP(right),--size));
4447                                 
4448                                 genSkipz2(&rFalseIfx,0);
4449                                 if(ifx) ifx->generated = 1;
4450                                 return;
4451                         }
4452                         
4453                         if(size==1) {
4454                                 /* Special cases */
4455                                 lit &= 0xff;
4456                                 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4457                                         /* degenerate compare can never be true */
4458                                         if(rFalseIfx.condition == 0)
4459                                                 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4460                                         
4461                                         if(ifx) ifx->generated = 1;
4462                                         return;
4463                                 }
4464                                 
4465                                 if(sign) {
4466                                         /* signed comparisons to a literal byte */
4467                                         
4468                                         int lp1 = (lit+1) & 0xff;
4469                                         
4470                                         DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4471                                         switch (lp1) {
4472                                         case 0:
4473                                                 rFalseIfx.condition ^= 1;
4474                                                 genSkipCond(&rFalseIfx,right,0,7);
4475                                                 break;
4476                                         case 0x7f:
4477                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4478                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4479                                                 genSkipz2(&rFalseIfx,1);
4480                                                 break;
4481                                         default:
4482                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4483                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4484                                                 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4485                                                 rFalseIfx.condition ^= 1;
4486                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4487                                                 break;
4488                                         }
4489                                         if(ifx) ifx->generated = 1;
4490                                 } else {
4491                                         /* unsigned comparisons to a literal byte */
4492                                         
4493                                         switch(lit & 0xff ) {
4494                                         case 0:
4495                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4496                                                 genSkipz2(&rFalseIfx,0);
4497                                                 if(ifx) ifx->generated = 1;
4498                                                 break;
4499                                         case 0x7f:
4500                                                 genSkipCond(&rFalseIfx,right,0,7);
4501                                                 if(ifx) ifx->generated = 1;
4502                                                 break;
4503                                                 
4504                                         default:
4505                                                 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4506                                                 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4507                                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4508                                                 rFalseIfx.condition ^= 1;
4509                                                 if (AOP_TYPE(result) == AOP_CRY) {
4510                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4511                                                         if(ifx) ifx->generated = 1;
4512                                                 } else {
4513                                                         DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4514                                                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4515                                                         emitpcode(POC_RLF, popGet(AOP(result),0));
4516                                                         emitpcode(POC_MOVLW, popGetLit(0x01));
4517                                                         emitpcode(POC_XORWF, popGet(AOP(result),0));
4518                                                 }       
4519                                                 break;
4520                                         }
4521                                 }
4522                                 
4523                                 //goto check_carry;
4524                                 return;
4525                                 
4526                         } else {
4527                                 
4528                                 /* Size is greater than 1 */
4529                                 
4530                                 if(sign) {
4531                                         int lp1 = lit+1;
4532                                         
4533                                         size--;
4534                                         
4535                                         if(lp1 == 0) {
4536                                                 /* this means lit = 0xffffffff, or -1 */
4537                                                 
4538                                                 
4539                                                 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4540                                                 rFalseIfx.condition ^= 1;
4541                                                 genSkipCond(&rFalseIfx,right,size,7);
4542                                                 if(ifx) ifx->generated = 1;
4543                                                 return;
4544                                         }
4545                                         
4546                                         if(lit == 0) {
4547                                                 int s = size;
4548                                                 
4549                                                 if(rFalseIfx.condition) {
4550                                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4551                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4552                                                 }
4553                                                 
4554                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4555                                                 while(size--)
4556                                                         emitpcode(POC_IORFW, popGet(AOP(right),size));
4557                                                 
4558                                                 
4559                                                 emitSKPZ;
4560                                                 if(rFalseIfx.condition) {
4561                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4562                                                         emitpLabel(truelbl->key);
4563                                                 }else {
4564                                                         rFalseIfx.condition ^= 1;
4565                                                         genSkipCond(&rFalseIfx,right,s,7);
4566                                                 }
4567                                                 
4568                                                 if(ifx) ifx->generated = 1;
4569                                                 return;
4570                                         }
4571                                         
4572                                         if((size == 1) &&  (0 == (lp1&0xff))) {
4573                                                 /* lower byte of signed word is zero */
4574                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4575                                                 i = ((lp1 >> 8) & 0xff) ^0x80;
4576                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4577                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4578                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4579                                                 rFalseIfx.condition ^= 1;
4580                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4581                                                 
4582                                                 
4583                                                 if(ifx) ifx->generated = 1;
4584                                                 return;
4585                                         }
4586                                         
4587                                         if(lit & (0x80 << (size*8))) {
4588                                                 /* Lit is less than zero */
4589                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4590                                                 //rFalseIfx.condition ^= 1;
4591                                                 //genSkipCond(&rFalseIfx,left,size,7);
4592                                                 //rFalseIfx.condition ^= 1;
4593                                                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4594                                                 //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4595                                                 
4596                                                 if(rFalseIfx.condition)
4597                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4598                                                 else
4599                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4600                                                 
4601                                                 
4602                                         } else {
4603                                                 /* Lit is greater than or equal to zero */
4604                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4605                                                 //rFalseIfx.condition ^= 1;
4606                                                 //genSkipCond(&rFalseIfx,right,size,7);
4607                                                 //rFalseIfx.condition ^= 1;
4608                                                 
4609                                                 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4610                                                 //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4611                                                 
4612                                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4613                                                 if(rFalseIfx.condition)
4614                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4615                                                 else
4616                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4617                                                 
4618                                         }
4619                                         
4620                                         
4621                                         emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4622                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4623                                         
4624                                         while(size--) {
4625                                                 
4626                                                 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4627                                                 emitSKPNZ;
4628                                                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4629                                         }
4630                                         rFalseIfx.condition ^= 1;
4631                                         //rFalseIfx.condition = 1;
4632                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4633                                         
4634                                         emitpLabel(truelbl->key);
4635                                         
4636                                         if(ifx) ifx->generated = 1;
4637                                         return;
4638                                         // end of if (sign)
4639                                 } else {
4640                                         
4641                                         /* compare word or long to an unsigned literal on the right.*/
4642                                         
4643                                         
4644                                         size--;
4645                                         if(lit < 0xff) {
4646                                                 DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4647                                                 switch (lit) {
4648                                                 case 0:
4649                                                         break; /* handled above */
4650                                                 /*
4651                                                 case 0xff:
4652                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4653                                                         while(size--)
4654                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4655                                                         genSkipz2(&rFalseIfx,0);
4656                                                         break;
4657                                                 */
4658                                                 default:
4659                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4660                                                         while(--size)
4661                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4662                                                         
4663                                                         emitSKPZ;
4664                                                         if(rFalseIfx.condition)
4665                                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4666                                                         else
4667                                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4668                                                         
4669                                                         
4670                                                         emitpcode(POC_MOVLW, popGetLit(lit+1));
4671                                                         emitpcode(POC_SUBFW, popGet(AOP(right),0));
4672                                                         
4673                                                         rFalseIfx.condition ^= 1;
4674                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4675                                                 }
4676                                                 
4677                                                 emitpLabel(truelbl->key);
4678                                                 
4679                                                 if(ifx) ifx->generated = 1;
4680                                                 return;
4681                                         }
4682                                         
4683                                         
4684                                         lit++;
4685                                         DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4686                                         i = (lit >> (size*8)) & 0xff;
4687                                         
4688                                         emitpcode(POC_MOVLW, popGetLit(i));
4689                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4690                                         
4691                                         while(size--) {
4692                                                 i = (lit >> (size*8)) & 0xff;
4693                                                 
4694                                                 if(i) {
4695                                                         emitpcode(POC_MOVLW, popGetLit(i));
4696                                                         emitSKPNZ;
4697                                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4698                                                 } else {
4699                                                 /* this byte of the lit is zero, 
4700                                                         *if it's not the last then OR in the variable */
4701                                                         if(size)
4702                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4703                                                 }
4704                                         }
4705                                         
4706                                         
4707                                         emitpLabel(lbl->key);
4708                                         
4709                                         rFalseIfx.condition ^= 1;
4710                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4711                                 }
4712                                 
4713                                 if(sign)
4714                                         emitpLabel(truelbl->key);
4715                                 if(ifx) ifx->generated = 1;
4716                                 return;
4717                         }
4718                 }
4719                 /* Compare two variables */
4720                 
4721                 DEBUGpic14_emitcode(";sign","%d",sign);
4722                 
4723                 size--;
4724                 if(sign) {
4725                         /* Sigh. thus sucks... */
4726                         if(size) {
4727                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4728                                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4729                                 emitpcode(POC_MOVLW, popGetLit(0x80));
4730                                 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4731                                 emitpcode(POC_XORFW, popGet(AOP(right),size));
4732                                 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4733                         } else {
4734                                 /* Signed char comparison */
4735                                 /* Special thanks to Nikolai Golovchenko for this snippet */
4736                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4737                                 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4738                                 emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4739                                 emitpcode(POC_XORFW, popGet(AOP(left),0));
4740                                 emitpcode(POC_XORFW, popGet(AOP(right),0));
4741                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4742                                 
4743                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4744                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4745                                 
4746                                 if(ifx) ifx->generated = 1;
4747                                 return;
4748                         }
4749                         
4750                 } else {
4751                         
4752                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4753                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4754                 }
4755                 
4756                 
4757                 /* The rest of the bytes of a multi-byte compare */
4758                 while (size) {
4759                         
4760                         emitSKPZ;
4761                         emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4762                         size--;
4763                         
4764                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4765                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4766                         
4767                         
4768                 }
4769                 
4770                 emitpLabel(lbl->key);
4771                 
4772                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4773                 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4774                         (AOP_TYPE(result) == AOP_REG)) {
4775                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4776                         emitpcode(POC_RLF, popGet(AOP(result),0));
4777                 } else {
4778                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4779                 }       
4780                 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4781                 if(ifx) ifx->generated = 1;
4782                 
4783                 return;
4784                 
4785         }
4786         
4787         // check_carry:
4788         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4789                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4790                 pic14_outBitC(result);
4791         } else {
4792                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4793                 /* if the result is used in the next
4794                 ifx conditional branch then generate
4795                 code a little differently */
4796                 if (ifx )
4797                         genIfxJump (ifx,"c");
4798                 else
4799                         pic14_outBitC(result);
4800                 /* leave the result in acc */
4801         }
4802         
4803 }
4804 #endif
4805
4806 /*-----------------------------------------------------------------*/
4807 /* genCmpGt :- greater than comparison                             */
4808 /*-----------------------------------------------------------------*/
4809 static void genCmpGt (iCode *ic, iCode *ifx)
4810 {
4811         operand *left, *right, *result;
4812         sym_link *letype , *retype;
4813         int sign ;
4814         
4815         FENTRY;
4816         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4817         left = IC_LEFT(ic);
4818         right= IC_RIGHT(ic);
4819         result = IC_RESULT(ic);
4820         
4821         letype = getSpec(operandType(left));
4822         retype =getSpec(operandType(right));
4823         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4824         /* assign the amsops */
4825         aopOp (left,ic,FALSE);
4826         aopOp (right,ic,FALSE);
4827         aopOp (result,ic,TRUE);
4828         
4829         genCmp(right, left, result, ifx, sign);
4830         
4831         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4832         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4833         freeAsmop(result,NULL,ic,TRUE); 
4834 }
4835
4836 /*-----------------------------------------------------------------*/
4837 /* genCmpLt - less than comparisons                                */
4838 /*-----------------------------------------------------------------*/
4839 static void genCmpLt (iCode *ic, iCode *ifx)
4840 {
4841         operand *left, *right, *result;
4842         sym_link *letype , *retype;
4843         int sign ;
4844         
4845         FENTRY;
4846         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4847         left = IC_LEFT(ic);
4848         right= IC_RIGHT(ic);
4849         result = IC_RESULT(ic);
4850         
4851         letype = getSpec(operandType(left));
4852         retype =getSpec(operandType(right));
4853         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4854         
4855         /* assign the amsops */
4856         aopOp (left,ic,FALSE);
4857         aopOp (right,ic,FALSE);
4858         aopOp (result,ic,TRUE);
4859         
4860         genCmp(left, right, result, ifx, sign);
4861         
4862         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4863         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4864         freeAsmop(result,NULL,ic,TRUE); 
4865 }
4866
4867 #if 0
4868 /*-----------------------------------------------------------------*/
4869 /* genc16bit2lit - compare a 16 bit value to a literal             */
4870 /*-----------------------------------------------------------------*/
4871 static void genc16bit2lit(operand *op, int lit, int offset)
4872 {
4873         int i;
4874         
4875         FENTRY;
4876         DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4877         if( (lit&0xff) == 0) 
4878                 i=1;
4879         else
4880                 i=0;
4881         
4882         switch( BYTEofLONG(lit,i)) { 
4883         case 0:
4884                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4885                 break;
4886         case 1:
4887                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4888                 break;
4889         case 0xff:
4890                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4891                 break;
4892         default:
4893                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4894                 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4895         }
4896         
4897         i ^= 1;
4898         
4899         switch( BYTEofLONG(lit,i)) { 
4900         case 0:
4901                 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4902                 break;
4903         case 1:
4904                 emitSKPNZ;
4905                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4906                 break;
4907         case 0xff:
4908                 emitSKPNZ;
4909                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4910                 break;
4911         default:
4912                 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4913                 emitSKPNZ;
4914                 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4915                 
4916         }
4917         
4918 }
4919 #endif
4920
4921 #if 0
4922 /*-----------------------------------------------------------------*/
4923 /* gencjneshort - compare and jump if not equal                    */
4924 /*-----------------------------------------------------------------*/
4925 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4926 {
4927         int size = min(AOP_SIZE(left),AOP_SIZE(right));
4928         int offset = 0;
4929         //resolvedIfx rIfx;
4930         symbol *lbl;
4931         
4932         //unsigned long lit = 0L;
4933         FENTRY;
4934         if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4935           emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4936           return;
4937         }
4938         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4939         DEBUGpic14_AopType(__LINE__,left,right,result);
4940         
4941         assert (!pic14_sameRegs (AOP(left), AOP(result)));
4942         assert (!pic14_sameRegs (AOP(right), AOP(result)));
4943         if (AOP_SIZE(result)) {
4944           for (offset = 0; offset < AOP_SIZE(result); offset++)
4945             emitpcode (POC_CLRF, popGet (AOP(result), offset));
4946         }
4947         
4948         assert (AOP_SIZE(left) == AOP_SIZE(right));
4949         //resolveIfx(&rIfx,ifx);
4950         lbl = newiTempLabel (NULL);
4951         while (size--)
4952         {
4953           mov2w (AOP(right),size);
4954           emitpcode (POC_XORFW, popGet (AOP(left), size));
4955           if (size)
4956           {
4957             emitSKPZ;
4958             emitpcode (POC_GOTO, popGetLabel (lbl->key));
4959           }
4960         } // while
4961         emitpLabel (lbl->key);
4962         if (AOP_SIZE(result)) {
4963           emitSKPNZ;
4964           emitpcode (POC_INCF, popGet (AOP(result), 0));
4965         } else {
4966           assert (ifx);
4967           genSkipz (ifx, NULL != IC_TRUE(ifx));
4968           ifx->generated = 1;
4969         }
4970         return;
4971 #if 0   
4972         if(result)
4973         {
4974                 DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4975                 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4976                 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4977                 for (offset=0; offset < AOP_SIZE(result); offset++)
4978                 {
4979                         emitpcode (POC_CLRF, popGet (AOP(result), offset));
4980                 } // for offset
4981         }
4982         
4983         
4984         /* if the left side is a literal or 
4985         if the right is in a pointer register and left 
4986         is not */
4987         if ((AOP_TYPE(left) == AOP_LIT) || 
4988                 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4989                 operand *t = right;
4990                 right = left;
4991                 left = t;
4992         }
4993         if(AOP_TYPE(right) == AOP_LIT)
4994                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4995         
4996         /* if the right side is a literal then anything goes */
4997         if (AOP_TYPE(right) == AOP_LIT &&
4998                 AOP_TYPE(left) != AOP_DIR ) {
4999                 switch(size) {
5000                 case 2:
5001                         genc16bit2lit(left, lit, 0);
5002                         emitSKPNZ;
5003                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
5004                         break;
5005                 default:
5006                         offset = 0;
5007                         while (size--) {
5008                                 if(lit & 0xff) {
5009                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5010                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5011                                 } else {
5012                                         emitpcode(POC_MOVF,popGet(AOP(left),offset));
5013                                 }
5014                                 
5015                                 emitSKPNZ;
5016                                 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5017                                 offset++;
5018                                 lit >>= 8;
5019                         }
5020                         break;
5021                 }
5022         }
5023         
5024         /* if the right side is in a register or in direct space or
5025         if the left is a pointer register & right is not */    
5026         else if (AOP_TYPE(right) == AOP_REG ||
5027                 AOP_TYPE(right) == AOP_DIR || 
5028                 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5029                 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5030                 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5031                 int lbl_key = lbl->key;
5032                 
5033                 if(!result) {
5034                         DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5035                         fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5036                                 __FUNCTION__,__LINE__);
5037                         return;
5038                 }
5039                 
5040                 /*     switch(size) { */
5041                 /*     case 2: */
5042                 /*       genc16bit2lit(left, lit, 0); */
5043                 /*       emitSKPNZ; */
5044                 /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
5045                 /*       break; */
5046                 /*     default: */
5047                 offset = 0;
5048                 while (size--) {
5049                         int emit_skip=1;
5050                         if((AOP_TYPE(left) == AOP_DIR) && 
5051                                 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5052                                 
5053                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5054                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5055                                 
5056                         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5057                                 
5058                                 switch (lit & 0xff) {
5059                                 case 0:
5060                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5061                                         break;
5062                                 case 1:
5063                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5064                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5065                                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
5066                                         emit_skip=0;
5067                                         break;
5068                                 case 0xff:
5069                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5070                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5071                                         //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5072                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5073                                         emit_skip=0;
5074                                         break;
5075                                 default:
5076                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5077                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5078                                 }
5079                                 lit >>= 8;
5080                                 
5081                         } else {
5082                                 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5083                         }
5084                         if(emit_skip) {
5085                                 if(AOP_TYPE(result) == AOP_CRY) {
5086                                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5087                                         if(rIfx.condition)
5088                                                 emitSKPNZ;
5089                                         else
5090                                                 emitSKPZ;
5091                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5092                                 } else {
5093                                         /* fix me. probably need to check result size too */
5094                                         //emitpcode(POC_CLRF,popGet(AOP(result),0));
5095                                         if(rIfx.condition)
5096                                                 emitSKPZ;
5097                                         else
5098                                                 emitSKPNZ;
5099                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5100                                 }
5101                                 if(ifx)
5102                                         ifx->generated=1;
5103                         }
5104                         emit_skip++;
5105                         offset++;
5106                 }
5107                 /*       break; */
5108                 /*     } */
5109         } else if(AOP_TYPE(right) == AOP_REG &&
5110                 AOP_TYPE(left) != AOP_DIR){
5111
5112                 offset = 0;
5113                 while(size--) {
5114                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5115                         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5116                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5117                         if(rIfx.condition)
5118                                 emitSKPNZ;
5119                         else
5120                                 emitSKPZ;
5121                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5122                         offset++;
5123                 }
5124                 
5125         }else{
5126                 /* right is a pointer reg need both a & b */
5127                 offset = 0;
5128                 while(size--) {
5129                         char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5130                         if(strcmp(l,"b"))
5131                                 pic14_emitcode("mov","b,%s",l);
5132                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5133                         pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5134                         offset++;
5135                 }
5136         }
5137         
5138         emitpcode(POC_INCF,popGet(AOP(result),0));
5139         if(!rIfx.condition)
5140                 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5141         
5142         emitpLabel(lbl->key);
5143         
5144         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5145         
5146         if(ifx)
5147                 ifx->generated = 1;
5148 #endif
5149 }
5150 #endif
5151
5152 #if 0
5153 /*-----------------------------------------------------------------*/
5154 /* gencjne - compare and jump if not equal                         */
5155 /*-----------------------------------------------------------------*/
5156 static void gencjne(operand *left, operand *right, iCode *ifx)
5157 {
5158         symbol *tlbl  = newiTempLabel(NULL);
5159         
5160         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5161         gencjneshort(left, right, lbl);
5162         
5163         pic14_emitcode("mov","a,%s",one);
5164         pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5165         pic14_emitcode("","%05d_DS_:",lbl->key+100);
5166         pic14_emitcode("clr","a");
5167         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5168         
5169         emitpLabel(lbl->key);
5170         emitpLabel(tlbl->key);
5171         
5172 }
5173 #endif
5174
5175 /*-----------------------------------------------------------------*/
5176 /* genCmpEq - generates code for equal to                          */
5177 /*-----------------------------------------------------------------*/
5178 static void genCmpEq (iCode *ic, iCode *ifx)
5179 {
5180   operand *left, *right, *result;
5181   int size;
5182   symbol *false_label;
5183
5184   FENTRY;
5185   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5186
5187   if(ifx)
5188     DEBUGpic14_emitcode ("; ifx is non-null","");
5189   else
5190     DEBUGpic14_emitcode ("; ifx is null","");
5191
5192   aopOp((left=IC_LEFT(ic)),ic,FALSE);
5193   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5194   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5195
5196   DEBUGpic14_AopType(__LINE__,left,right,result);
5197
5198   /* if literal, move literal to right */ 
5199   if (op_isLitLike (IC_LEFT(ic))) {
5200     operand *tmp = right ;
5201     right = left;
5202     left = tmp;
5203   }
5204
5205   false_label = NULL;
5206   if (ifx && !IC_TRUE(ifx))
5207   {
5208     assert (IC_FALSE(ifx));
5209     false_label = IC_FALSE(ifx);
5210   }
5211
5212   size = min(AOP_SIZE(left),AOP_SIZE(right));
5213   assert(!pic14_sameRegs(AOP(result),AOP(left)));
5214   assert(!pic14_sameRegs(AOP(result),AOP(right)));
5215
5216   /* assume left != right */
5217   {
5218     int i;
5219     for (i=0; i < AOP_SIZE(result); i++)
5220     {
5221       emitpcode(POC_CLRF, popGet(AOP(result),i));
5222     }
5223   }
5224
5225   if (AOP_TYPE(right) == AOP_LIT)
5226   {
5227     unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5228     int i;
5229     size = AOP_SIZE(left);
5230     assert(!op_isLitLike(left));
5231
5232     switch (lit)
5233     {
5234       case 0:
5235         mov2w(AOP(left), 0);
5236         for (i=1; i < size; i++)
5237           emitpcode(POC_IORFW,popGet(AOP(left),i));
5238         /* now Z is set iff `left == right' */
5239         emitSKPZ;
5240         if (!false_label) false_label = newiTempLabel(NULL);
5241         emitpcode(POC_GOTO, popGetLabel(false_label->key));
5242         break;
5243
5244       default:
5245         for (i=0; i < size; i++)
5246         {
5247           mov2w(AOP(left),i);
5248           emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5249           /* now Z is cleared if `left != right' */
5250           emitSKPZ;
5251           if (!false_label) false_label = newiTempLabel(NULL);
5252           emitpcode(POC_GOTO, popGetLabel(false_label->key));
5253         } // for i
5254         break;
5255     } // switch (lit)
5256   }
5257   else
5258   {
5259     /* right is no literal */
5260     int i;
5261
5262     for (i=0; i < size; i++)
5263     {
5264       mov2w(AOP(right),i);
5265       emitpcode(POC_XORFW,popGet(AOP(left),i));
5266       /* now Z is cleared if `left != right' */
5267       emitSKPZ;
5268       if (!false_label) false_label = newiTempLabel(NULL);
5269       emitpcode(POC_GOTO, popGetLabel(false_label->key));
5270     } // for i
5271   }
5272
5273   /* if we reach here, left == right */
5274
5275   if (AOP_SIZE(result) > 0)
5276   {
5277     emitpcode(POC_INCF, popGet(AOP(result),0));
5278   }
5279
5280   if (ifx && IC_TRUE(ifx))
5281   {
5282     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5283   }
5284
5285   if (false_label && (!ifx || IC_TRUE(ifx)))
5286     emitpLabel(false_label->key);
5287
5288   if (ifx) ifx->generated = 1;
5289
5290   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5291   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5292   freeAsmop(result,NULL,ic,TRUE);
5293 }
5294
5295 /*-----------------------------------------------------------------*/
5296 /* ifxForOp - returns the icode containing the ifx for operand     */
5297 /*-----------------------------------------------------------------*/
5298 static iCode *ifxForOp ( operand *op, iCode *ic )
5299 {
5300         FENTRY;
5301         /* if true symbol then needs to be assigned */
5302         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5303         if (IS_TRUE_SYMOP(op))
5304                 return NULL ;
5305         
5306         /* if this has register type condition and
5307         the next instruction is ifx with the same operand
5308         and live to of the operand is upto the ifx only then */
5309         if (ic->next &&
5310                 ic->next->op == IFX &&
5311                 IC_COND(ic->next)->key == op->key &&
5312                 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5313                 return ic->next;
5314         
5315         if (ic->next &&
5316                 ic->next->op == IFX &&
5317                 IC_COND(ic->next)->key == op->key) {
5318                 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5319                 return ic->next;
5320         }
5321         
5322         DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5323         if (ic->next &&
5324                 ic->next->op == IFX)
5325                 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5326         
5327         if (ic->next &&
5328                 ic->next->op == IFX &&
5329                 IC_COND(ic->next)->key == op->key) {
5330                 DEBUGpic14_emitcode ("; "," key is okay");
5331                 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5332                         OP_SYMBOL(op)->liveTo,
5333                         ic->next->seq);
5334         }
5335         
5336         
5337         return NULL;
5338 }
5339 /*-----------------------------------------------------------------*/
5340 /* genAndOp - for && operation                                     */
5341 /*-----------------------------------------------------------------*/
5342 static void genAndOp (iCode *ic)
5343 {
5344         operand *left,*right, *result;
5345         /*     symbol *tlbl; */
5346         
5347         FENTRY;
5348         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5349         /* note here that && operations that are in an
5350         if statement are taken away by backPatchLabels
5351         only those used in arthmetic operations remain */
5352         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5353         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5354         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5355         
5356         DEBUGpic14_AopType(__LINE__,left,right,result);
5357         
5358         emitpcode(POC_MOVFW,popGet(AOP(left),0));
5359         emitpcode(POC_ANDFW,popGet(AOP(right),0));
5360         emitpcode(POC_MOVWF,popGet(AOP(result),0));
5361         
5362         /* if both are bit variables */
5363         /*     if (AOP_TYPE(left) == AOP_CRY && */
5364         /*         AOP_TYPE(right) == AOP_CRY ) { */
5365         /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5366         /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5367         /*         pic14_outBitC(result); */
5368         /*     } else { */
5369         /*         tlbl = newiTempLabel(NULL); */
5370         /*         pic14_toBoolean(left);     */
5371         /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5372         /*         pic14_toBoolean(right); */
5373         /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5374         /*         pic14_outBitAcc(result); */
5375         /*     } */
5376         
5377         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5378         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5379         freeAsmop(result,NULL,ic,TRUE);
5380 }
5381
5382
5383 /*-----------------------------------------------------------------*/
5384 /* genOrOp - for || operation                                      */
5385 /*-----------------------------------------------------------------*/
5386 /*
5387 tsd pic port -
5388 modified this code, but it doesn't appear to ever get called
5389 */
5390
5391 static void genOrOp (iCode *ic)
5392 {
5393         operand *left,*right, *result;
5394         symbol *tlbl;
5395         int i;
5396         
5397         /* note here that || operations that are in an
5398         if statement are taken away by backPatchLabels
5399         only those used in arthmetic operations remain */
5400         FENTRY;
5401         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5402         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5403         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5404         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5405         
5406         DEBUGpic14_AopType(__LINE__,left,right,result);
5407
5408         for (i=0; i < AOP_SIZE(result); i++)
5409         {
5410                 emitpcode(POC_CLRF, popGet(AOP(result), i));
5411         } // for i
5412
5413         tlbl = newiTempLabel(NULL);
5414         pic14_toBoolean(left);
5415         emitSKPZ;
5416         emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5417         pic14_toBoolean(right);
5418         emitpLabel(tlbl->key);
5419         /* here Z is clear IFF `left || right' */
5420         emitSKPZ;
5421         emitpcode(POC_INCF, popGet(AOP(result), 0));
5422         
5423         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5424         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5425         freeAsmop(result,NULL,ic,TRUE);            
5426 }
5427
5428 /*-----------------------------------------------------------------*/
5429 /* isLiteralBit - test if lit == 2^n                               */
5430 /*-----------------------------------------------------------------*/
5431 static int isLiteralBit(unsigned long lit)
5432 {
5433         unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5434                 0x100L,0x200L,0x400L,0x800L,
5435                 0x1000L,0x2000L,0x4000L,0x8000L,
5436                 0x10000L,0x20000L,0x40000L,0x80000L,
5437                 0x100000L,0x200000L,0x400000L,0x800000L,
5438                 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5439                 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5440         int idx;
5441         
5442         FENTRY;
5443         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5444         for(idx = 0; idx < 32; idx++)
5445                 if(lit == pw[idx])
5446                         return idx+1;
5447                 return 0;
5448 }
5449
5450 /*-----------------------------------------------------------------*/
5451 /* continueIfTrue -                                                */
5452 /*-----------------------------------------------------------------*/
5453 static void continueIfTrue (iCode *ic)
5454 {
5455         FENTRY;
5456         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5457         if(IC_TRUE(ic))
5458                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5459         ic->generated = 1;
5460 }
5461
5462 /*-----------------------------------------------------------------*/
5463 /* jmpIfTrue -                                                     */
5464 /*-----------------------------------------------------------------*/
5465 static void jumpIfTrue (iCode *ic)
5466 {
5467         FENTRY;
5468         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5469         if(!IC_TRUE(ic))
5470                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5471         ic->generated = 1;
5472 }
5473
5474 /*-----------------------------------------------------------------*/
5475 /* jmpTrueOrFalse -                                                */
5476 /*-----------------------------------------------------------------*/
5477 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5478 {
5479         FENTRY;
5480         // ugly but optimized by peephole
5481         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5482         if(IC_TRUE(ic)){
5483                 symbol *nlbl = newiTempLabel(NULL);
5484                 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5485                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5486                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5487                 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5488         }
5489         else{
5490                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5491                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5492         }
5493         ic->generated = 1;
5494 }
5495
5496 /*-----------------------------------------------------------------*/
5497 /* genAnd  - code for and                                          */
5498 /*-----------------------------------------------------------------*/
5499 static void genAnd (iCode *ic, iCode *ifx)
5500 {
5501         operand *left, *right, *result;
5502         int size, offset=0;  
5503         unsigned long lit = 0L;
5504         int bytelit = 0;
5505         resolvedIfx rIfx;
5506         
5507         FENTRY;
5508         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5509         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5510         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5511         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5512         
5513         resolveIfx(&rIfx,ifx);
5514         
5515         /* if left is a literal & right is not then exchange them */
5516         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5517                 AOP_NEEDSACC(left)) {
5518                 operand *tmp = right ;
5519                 right = left;
5520                 left = tmp;
5521         }
5522         
5523         /* if result = right then exchange them */
5524         if(pic14_sameRegs(AOP(result),AOP(right))){
5525                 operand *tmp = right ;
5526                 right = left;
5527                 left = tmp;
5528         }
5529         
5530         /* if right is bit then exchange them */
5531         if (AOP_TYPE(right) == AOP_CRY &&
5532                 AOP_TYPE(left) != AOP_CRY){
5533                 operand *tmp = right ;
5534                 right = left;
5535                 left = tmp;
5536         }
5537         if(AOP_TYPE(right) == AOP_LIT)
5538                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5539         
5540         size = AOP_SIZE(result);
5541         
5542         DEBUGpic14_AopType(__LINE__,left,right,result);
5543         
5544         // if(bit & yy)
5545         // result = bit & yy;
5546         if (AOP_TYPE(left) == AOP_CRY){
5547                 // c = bit & literal;
5548                 if(AOP_TYPE(right) == AOP_LIT){
5549                         if(lit & 1) {
5550                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5551                                         // no change
5552                                         goto release;
5553                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5554                         } else {
5555                                 // bit(result) = 0;
5556                                 if(size && (AOP_TYPE(result) == AOP_CRY)){
5557                                         pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5558                                         goto release;
5559                                 }
5560                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5561                                         jumpIfTrue(ifx);
5562                                         goto release;
5563                                 }
5564                                 pic14_emitcode("clr","c");
5565                         }
5566                 } else {
5567                         if (AOP_TYPE(right) == AOP_CRY){
5568                                 // c = bit & bit;
5569                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5570                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5571                         } else {
5572                                 // c = bit & val;
5573                                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5574                                 // c = lsb
5575                                 pic14_emitcode("rrc","a");
5576                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5577                         }
5578                 }
5579                 // bit = c
5580                 // val = c
5581                 if(size)
5582                         pic14_outBitC(result);
5583                 // if(bit & ...)
5584                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5585                         genIfxJump(ifx, "c");           
5586                 goto release ;
5587         }
5588         
5589         // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5590         // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5591         if((AOP_TYPE(right) == AOP_LIT) &&
5592                 (AOP_TYPE(result) == AOP_CRY) &&
5593                 (AOP_TYPE(left) != AOP_CRY)){
5594                 int posbit = isLiteralBit(lit);
5595                 /* left &  2^n */
5596                 if(posbit){
5597                         posbit--;
5598                         //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5599                         // bit = left & 2^n
5600                         if(size)
5601                                 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5602                         // if(left &  2^n)
5603                         else{
5604                                 if(ifx){
5605                                         int offset = 0;
5606                                         while (posbit > 7) {
5607                                                 posbit -= 8;
5608                                                 offset++;
5609                                         }
5610                                         emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5611                                                 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5612                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5613                                         
5614                                         ifx->generated = 1;
5615                                 }
5616                                 goto release;
5617                         }
5618                 } else {
5619                         symbol *tlbl = newiTempLabel(NULL);
5620                         int sizel = AOP_SIZE(left);
5621                         if(size)
5622                                 pic14_emitcode("setb","c");
5623                         while(sizel--){
5624                                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5625                                         MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5626                                         // byte ==  2^n ?
5627                                         if((posbit = isLiteralBit(bytelit)) != 0)
5628                                                 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5629                                         else{
5630                                                 if(bytelit != 0x0FFL)
5631                                                         pic14_emitcode("anl","a,%s",
5632                                                         aopGet(AOP(right),offset,FALSE,TRUE));
5633                                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5634                                         }
5635                                 }
5636                                 offset++;
5637                         }
5638                         // bit = left & literal
5639                         if(size){
5640                                 pic14_emitcode("clr","c");
5641                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5642                         }
5643                         // if(left & literal)
5644                         else{
5645                                 if(ifx)
5646                                         jmpTrueOrFalse(ifx, tlbl);
5647                                 goto release ;
5648                         }
5649                 }
5650                 pic14_outBitC(result);
5651                 goto release ;
5652         }
5653         
5654         /* if left is same as result */
5655         if(pic14_sameRegs(AOP(result),AOP(left))){
5656                 int know_W = -1;
5657                 for(;size--; offset++,lit>>=8) {
5658                         if(AOP_TYPE(right) == AOP_LIT){
5659                                 switch(lit & 0xff) {
5660                                 case 0x00:
5661                                         /*  and'ing with 0 has clears the result */
5662                                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
5663                                         break;
5664                                 case 0xff:
5665                                         /* and'ing with 0xff is a nop when the result and left are the same */
5666                                         break;
5667                                         
5668                                 default:
5669                                         {
5670                                                 int p = my_powof2( (~lit) & 0xff );
5671                                                 if(p>=0) {
5672                                                         /* only one bit is set in the literal, so use a bcf instruction */
5673                                                         emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5674                                                         
5675                                                 } else {
5676                                                         if(know_W != (int)(lit&0xff))
5677                                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5678                                                         know_W = lit &0xff;
5679                                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5680                                                 }
5681                                         }    
5682                                 }
5683                         } else {
5684                                 if (AOP_TYPE(left) == AOP_ACC) {
5685                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5686                                 } else {        
5687                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5688                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5689                                         
5690                                 }
5691                         }
5692                 }
5693                 
5694         } else {
5695                 // left & result in different registers
5696                 if(AOP_TYPE(result) == AOP_CRY){
5697                         // result = bit
5698                         // if(size), result in bit
5699                         // if(!size && ifx), conditional oper: if(left & right)
5700                         symbol *tlbl = newiTempLabel(NULL);
5701                         int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5702                         if(size)
5703                                 pic14_emitcode("setb","c");
5704                         while(sizer--){
5705                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5706                                 pic14_emitcode("anl","a,%s",
5707                                         aopGet(AOP(left),offset,FALSE,FALSE));
5708                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5709                                 offset++;
5710                         }
5711                         if(size){
5712                                 CLRC;
5713                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5714                                 pic14_outBitC(result);
5715                         } else if(ifx)
5716                                 jmpTrueOrFalse(ifx, tlbl);
5717                 } else {
5718                         for(;(size--);offset++) {
5719                                 // normal case
5720                                 // result = left & right
5721                                 if(AOP_TYPE(right) == AOP_LIT){
5722                                         int t = (lit >> (offset*8)) & 0x0FFL;
5723                                         switch(t) { 
5724                                         case 0x00:
5725                                                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5726                                                 break;
5727                                         case 0xff:
5728                                                 if(AOP_TYPE(left) != AOP_ACC) {
5729                                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5730                                                 }
5731                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5732                                                 break;
5733                                         default:
5734                                                 if(AOP_TYPE(left) == AOP_ACC) {
5735                                                         emitpcode(POC_ANDLW, popGetLit(t));
5736                                                 } else {
5737                                                         emitpcode(POC_MOVLW, popGetLit(t));
5738                                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5739                                                 }
5740                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5741                                         }
5742                                         continue;
5743                                 }
5744                                 
5745                                 if (AOP_TYPE(left) == AOP_ACC) {
5746                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5747                                 } else {
5748                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5749                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5750                                 }
5751                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5752                         }
5753                 }
5754         }
5755         
5756 release :
5757         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5758         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5759         freeAsmop(result,NULL,ic,TRUE);     
5760 }
5761
5762 /*-----------------------------------------------------------------*/
5763 /* genOr  - code for or                                            */
5764 /*-----------------------------------------------------------------*/
5765 static void genOr (iCode *ic, iCode *ifx)
5766 {
5767         operand *left, *right, *result;
5768         int size, offset=0;
5769         unsigned long lit = 0L;
5770         
5771         FENTRY;
5772         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5773         
5774         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5775         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5776         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5777         
5778         DEBUGpic14_AopType(__LINE__,left,right,result);
5779         
5780         /* if left is a literal & right is not then exchange them */
5781         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5782                 AOP_NEEDSACC(left)) {
5783                 operand *tmp = right ;
5784                 right = left;
5785                 left = tmp;
5786         }
5787         
5788         /* if result = right then exchange them */
5789         if(pic14_sameRegs(AOP(result),AOP(right))){
5790                 operand *tmp = right ;
5791                 right = left;
5792                 left = tmp;
5793         }
5794         
5795         /* if right is bit then exchange them */
5796         if (AOP_TYPE(right) == AOP_CRY &&
5797                 AOP_TYPE(left) != AOP_CRY){
5798                 operand *tmp = right ;
5799                 right = left;
5800                 left = tmp;
5801         }
5802         
5803         DEBUGpic14_AopType(__LINE__,left,right,result);
5804         
5805         if(AOP_TYPE(right) == AOP_LIT)
5806                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5807         
5808         size = AOP_SIZE(result);
5809         
5810         // if(bit | yy)
5811         // xx = bit | yy;
5812         if (AOP_TYPE(left) == AOP_CRY){
5813                 if(AOP_TYPE(right) == AOP_LIT){
5814                         // c = bit & literal;
5815                         if(lit){
5816                                 // lit != 0 => result = 1
5817                                 if(AOP_TYPE(result) == AOP_CRY){
5818                                         if(size)
5819                                                 emitpcode(POC_BSF, popGet(AOP(result),0));
5820                                         //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5821                                         //   AOP(result)->aopu.aop_dir,
5822                                         //   AOP(result)->aopu.aop_dir);
5823                                         else if(ifx)
5824                                                 continueIfTrue(ifx);
5825                                         goto release;
5826                                 }
5827                         } else {
5828                                 // lit == 0 => result = left
5829                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5830                                         goto release;
5831                                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5832                         }
5833                 } else {
5834                         if (AOP_TYPE(right) == AOP_CRY){
5835                                 if(pic14_sameRegs(AOP(result),AOP(left))){
5836                                         // c = bit | bit;
5837                                         emitpcode(POC_BCF,   popGet(AOP(result),0));
5838                                         emitpcode(POC_BTFSC, popGet(AOP(right),0));
5839                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5840                                         
5841                                         pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5842                                                 AOP(result)->aopu.aop_dir,
5843                                                 AOP(result)->aopu.aop_dir);
5844                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5845                                                 AOP(right)->aopu.aop_dir,
5846                                                 AOP(right)->aopu.aop_dir);
5847                                         pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5848                                                 AOP(result)->aopu.aop_dir,
5849                                                 AOP(result)->aopu.aop_dir);
5850                                 } else {
5851                                         if( AOP_TYPE(result) == AOP_ACC) {
5852                                                 emitpcode(POC_MOVLW, popGetLit(0));
5853                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5854                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5855                                                 emitpcode(POC_MOVLW, popGetLit(1));
5856                                                 
5857                                         } else {
5858                                                 
5859                                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5860                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5861                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5862                                                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5863                                                 
5864                                                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5865                                                         AOP(result)->aopu.aop_dir,
5866                                                         AOP(result)->aopu.aop_dir);
5867                                                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5868                                                         AOP(right)->aopu.aop_dir,
5869                                                         AOP(right)->aopu.aop_dir);
5870                                                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5871                                                         AOP(left)->aopu.aop_dir,
5872                                                         AOP(left)->aopu.aop_dir);
5873                                                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5874                                                         AOP(result)->aopu.aop_dir,
5875                                                         AOP(result)->aopu.aop_dir);
5876                                         }
5877                                 }
5878                         } else {
5879                                 // c = bit | val;
5880                                 symbol *tlbl = newiTempLabel(NULL);
5881                                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5882                                 
5883                                 
5884                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5885                                 if( AOP_TYPE(right) == AOP_ACC) {
5886                                         emitpcode(POC_IORLW, popGetLit(0));
5887                                         emitSKPNZ;
5888                                         emitpcode(POC_BTFSC, popGet(AOP(left),0));
5889                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5890                                 }
5891                                 
5892                                 
5893                                 
5894                                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5895                                         pic14_emitcode(";XXX setb","c");
5896                                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5897                                         AOP(left)->aopu.aop_dir,tlbl->key+100);
5898                                 pic14_toBoolean(right);
5899                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5900                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5901                                         jmpTrueOrFalse(ifx, tlbl);
5902                                         goto release;
5903                                 } else {
5904                                         CLRC;
5905                                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5906                                 }
5907                         }
5908                 }
5909                 // bit = c
5910                 // val = c
5911                 if(size)
5912                         pic14_outBitC(result);
5913                 // if(bit | ...)
5914                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5915                         genIfxJump(ifx, "c");           
5916                 goto release ;
5917         }
5918
5919         // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5920         // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5921         if((AOP_TYPE(right) == AOP_LIT) &&
5922           (AOP_TYPE(result) == AOP_CRY) &&
5923           (AOP_TYPE(left) != AOP_CRY)){
5924                 if(lit){
5925                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5926                         // result = 1
5927                         if(size)
5928                                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5929                         else 
5930                                 continueIfTrue(ifx);
5931                         goto release;
5932                 } else {
5933                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5934                         // lit = 0, result = boolean(left)
5935                         if(size)
5936                                 pic14_emitcode(";XXX setb","c");
5937                         pic14_toBoolean(right);
5938                         if(size){
5939                                 symbol *tlbl = newiTempLabel(NULL);
5940                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5941                                 CLRC;
5942                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5943                         } else {
5944                                 genIfxJump (ifx,"a");
5945                                 goto release;
5946                         }
5947                 }
5948                 pic14_outBitC(result);
5949                 goto release ;
5950         }
5951
5952         /* if left is same as result */
5953         if(pic14_sameRegs(AOP(result),AOP(left))){
5954                 int know_W = -1;
5955                 for(;size--; offset++,lit>>=8) {
5956                         if(AOP_TYPE(right) == AOP_LIT){
5957                                 if((lit & 0xff) == 0)
5958                                         /*  or'ing with 0 has no effect */
5959                                         continue;
5960                                 else {
5961                                         int p = my_powof2(lit & 0xff);
5962                                         if(p>=0) {
5963                                                 /* only one bit is set in the literal, so use a bsf instruction */
5964                                                 emitpcode(POC_BSF,
5965                                                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5966                                         } else {
5967                                                 if(know_W != (int)(lit & 0xff))
5968                                                         emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5969                                                 know_W = lit & 0xff;
5970                                                 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5971                                         }
5972                                         
5973                                 }
5974                         } else {
5975                                 if (AOP_TYPE(left) == AOP_ACC) {
5976                                         emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5977                                         pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5978                                 } else {        
5979                                         emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5980                                         emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5981                                         
5982                                         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5983                                         pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5984                                         
5985                                 }
5986                         }
5987                 }
5988         } else {
5989                 // left & result in different registers
5990                 if(AOP_TYPE(result) == AOP_CRY){
5991                         // result = bit
5992                         // if(size), result in bit
5993                         // if(!size && ifx), conditional oper: if(left | right)
5994                         symbol *tlbl = newiTempLabel(NULL);
5995                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5996                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5997                         
5998                         
5999                         if(size)
6000                                 pic14_emitcode(";XXX setb","c");
6001                         while(sizer--){
6002                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6003                                 pic14_emitcode(";XXX orl","a,%s",
6004                                         aopGet(AOP(left),offset,FALSE,FALSE));
6005                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6006                                 offset++;
6007                         }
6008                         if(size){
6009                                 CLRC;
6010                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6011                                 pic14_outBitC(result);
6012                         } else if(ifx)
6013                                 jmpTrueOrFalse(ifx, tlbl);
6014                 } else for(;(size--);offset++){
6015                         // normal case
6016                         // result = left | right
6017                         if(AOP_TYPE(right) == AOP_LIT){
6018                                 int t = (lit >> (offset*8)) & 0x0FFL;
6019                                 switch(t) { 
6020                                 case 0x00:
6021                                         if (AOP_TYPE(left) != AOP_ACC) {
6022                                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
6023                                         }
6024                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6025                                         
6026                                         break;
6027                                 default:
6028                                         if (AOP_TYPE(left) == AOP_ACC) {
6029                                                 emitpcode(POC_IORLW,  popGetLit(t));
6030                                         } else {
6031                                                 emitpcode(POC_MOVLW,  popGetLit(t));
6032                                                 emitpcode(POC_IORFW,  popGet(AOP(left),offset));
6033                                         }
6034                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));        
6035                                 }
6036                                 continue;
6037                         }
6038                         
6039                         // faster than result <- left, anl result,right
6040                         // and better if result is SFR
6041                         if (AOP_TYPE(left) == AOP_ACC) {
6042                                 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6043                         } else {
6044                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6045                                 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6046                         }
6047                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6048                 }
6049         }
6050
6051 release :
6052         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6053         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6054         freeAsmop(result,NULL,ic,TRUE);     
6055 }
6056
6057 /*-----------------------------------------------------------------*/
6058 /* genXor - code for xclusive or                                   */
6059 /*-----------------------------------------------------------------*/
6060 static void genXor (iCode *ic, iCode *ifx)
6061 {
6062         operand *left, *right, *result;
6063         int size, offset=0;
6064         unsigned long lit = 0L;
6065         
6066         FENTRY;
6067         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6068         
6069         aopOp((left = IC_LEFT(ic)),ic,FALSE);
6070         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6071         aopOp((result=IC_RESULT(ic)),ic,TRUE);
6072         
6073         /* if left is a literal & right is not ||
6074         if left needs acc & right does not */
6075         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6076                 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6077                 operand *tmp = right ;
6078                 right = left;
6079                 left = tmp;
6080         }
6081         
6082         /* if result = right then exchange them */
6083         if(pic14_sameRegs(AOP(result),AOP(right))){
6084                 operand *tmp = right ;
6085                 right = left;
6086                 left = tmp;
6087         }
6088         
6089         /* if right is bit then exchange them */
6090         if (AOP_TYPE(right) == AOP_CRY &&
6091                 AOP_TYPE(left) != AOP_CRY){
6092                 operand *tmp = right ;
6093                 right = left;
6094                 left = tmp;
6095         }
6096         if(AOP_TYPE(right) == AOP_LIT)
6097                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6098         
6099         size = AOP_SIZE(result);
6100         
6101         // if(bit ^ yy)
6102         // xx = bit ^ yy;
6103         if (AOP_TYPE(left) == AOP_CRY){
6104                 if(AOP_TYPE(right) == AOP_LIT){
6105                         // c = bit & literal;
6106                         if(lit>>1){
6107                                 // lit>>1  != 0 => result = 1
6108                                 if(AOP_TYPE(result) == AOP_CRY){
6109                                         if(size)
6110                                         {emitpcode(POC_BSF,  popGet(AOP(result),offset));
6111                                         pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6112                                         else if(ifx)
6113                                                 continueIfTrue(ifx);
6114                                         goto release;
6115                                 }
6116                                 pic14_emitcode("setb","c");
6117                         } else{
6118                                 // lit == (0 or 1)
6119                                 if(lit == 0){
6120                                         // lit == 0, result = left
6121                                         if(size && pic14_sameRegs(AOP(result),AOP(left)))
6122                                                 goto release;
6123                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6124                                 } else{
6125                                         // lit == 1, result = not(left)
6126                                         if(size && pic14_sameRegs(AOP(result),AOP(left))){
6127                                                 emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
6128                                                 emitpcode(POC_XORWF,  popGet(AOP(result),offset));
6129                                                 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6130                                                 goto release;
6131                                         } else {
6132                                                 assert ( !"incomplete genXor" );
6133                                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6134                                                 pic14_emitcode("cpl","c");
6135                                         }
6136                                 }
6137                         }
6138                         
6139                 } else {
6140                         // right != literal
6141                         symbol *tlbl = newiTempLabel(NULL);
6142                         if (AOP_TYPE(right) == AOP_CRY){
6143                                 // c = bit ^ bit;
6144                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6145                         }
6146                         else{
6147                                 int sizer = AOP_SIZE(right);
6148                                 // c = bit ^ val
6149                                 // if val>>1 != 0, result = 1
6150                                 pic14_emitcode("setb","c");
6151                                 while(sizer){
6152                                         MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6153                                         if(sizer == 1)
6154                                                 // test the msb of the lsb
6155                                                 pic14_emitcode("anl","a,#0xfe");
6156                                         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6157                                         sizer--;
6158                                 }
6159                                 // val = (0,1)
6160                                 pic14_emitcode("rrc","a");
6161                         }
6162                         pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6163                         pic14_emitcode("cpl","c");
6164                         pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6165                 }
6166                 // bit = c
6167                 // val = c
6168                 if(size)
6169                         pic14_outBitC(result);
6170                 // if(bit | ...)
6171                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6172                         genIfxJump(ifx, "c");           
6173                 goto release ;
6174         }
6175         
6176         if(pic14_sameRegs(AOP(result),AOP(left))){
6177                 /* if left is same as result */
6178                 for(;size--; offset++) {
6179                         if(AOP_TYPE(right) == AOP_LIT){
6180                                 int t  = (lit >> (offset*8)) & 0x0FFL;
6181                                 if(t == 0x00L)
6182                                         continue;
6183                                 else
6184                                         if (IS_AOP_PREG(left)) {
6185                                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6186                                                 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6187                                                 aopPut(AOP(result),"a",offset);
6188                                         } else {
6189                                                 emitpcode(POC_MOVLW, popGetLit(t));
6190                                                 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6191                                                 pic14_emitcode("xrl","%s,%s",
6192                                                         aopGet(AOP(left),offset,FALSE,TRUE),
6193                                                         aopGet(AOP(right),offset,FALSE,FALSE));
6194                                         }
6195                         } else {
6196                                 if (AOP_TYPE(left) == AOP_ACC)
6197                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6198                                 else {
6199                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6200                                         emitpcode(POC_XORWF,popGet(AOP(left),offset));
6201                                         /*
6202                                         if (IS_AOP_PREG(left)) {
6203                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6204                                         aopPut(AOP(result),"a",offset);
6205                                         } else
6206                                         pic14_emitcode("xrl","%s,a",
6207                                         aopGet(AOP(left),offset,FALSE,TRUE));
6208                                         */
6209                                 }
6210                         }
6211                 }
6212         } else {
6213                 // left & result in different registers
6214                 if(AOP_TYPE(result) == AOP_CRY){
6215                         // result = bit
6216                         // if(size), result in bit
6217                         // if(!size && ifx), conditional oper: if(left ^ right)
6218                         symbol *tlbl = newiTempLabel(NULL);
6219                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6220                         if(size)
6221                                 pic14_emitcode("setb","c");
6222                         while(sizer--){
6223                                 if((AOP_TYPE(right) == AOP_LIT) &&
6224                                         (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6225                                         MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6226                                 } else {
6227                                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6228                                         pic14_emitcode("xrl","a,%s",
6229                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6230                                 }
6231                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6232                                 offset++;
6233                         }
6234                         if(size){
6235                                 CLRC;
6236                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6237                                 pic14_outBitC(result);
6238                         } else if(ifx)
6239                                 jmpTrueOrFalse(ifx, tlbl);
6240                 } else for(;(size--);offset++){
6241                         // normal case
6242                         // result = left & right
6243                         if(AOP_TYPE(right) == AOP_LIT){
6244                                 int t = (lit >> (offset*8)) & 0x0FFL;
6245                                 switch(t) { 
6246                                 case 0x00:
6247                                         if (AOP_TYPE(left) != AOP_ACC) {
6248                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6249                                         }
6250                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6251                                         pic14_emitcode("movf","%s,w",
6252                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6253                                         pic14_emitcode("movwf","%s",
6254                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6255                                         break;
6256                                 case 0xff:
6257                                         if (AOP_TYPE(left) == AOP_ACC) {
6258                                                 emitpcode(POC_XORLW, popGetLit(t));
6259                                         } else {
6260                                                 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6261                                         }
6262                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6263                                         break;
6264                                 default:
6265                                         if (AOP_TYPE(left) == AOP_ACC) {
6266                                                 emitpcode(POC_XORLW, popGetLit(t));
6267                                         } else {
6268                                                 emitpcode(POC_MOVLW, popGetLit(t));
6269                                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6270                                         }
6271                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6272                                         pic14_emitcode("movlw","0x%x",t);
6273                                         pic14_emitcode("xorwf","%s,w",
6274                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6275                                         pic14_emitcode("movwf","%s",
6276                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6277                                         
6278                                 }
6279                                 continue;
6280                         }
6281                         
6282                         // faster than result <- left, anl result,right
6283                         // and better if result is SFR
6284                         if (AOP_TYPE(left) == AOP_ACC) {
6285                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6286                         } else {
6287                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6288                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6289                         }
6290                         if ( AOP_TYPE(result) != AOP_ACC){
6291                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6292                         }
6293                 }
6294         }
6295         
6296 release :
6297         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6298         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6299         freeAsmop(result,NULL,ic,TRUE);     
6300 }
6301
6302 /*-----------------------------------------------------------------*/
6303 /* genInline - write the inline code out                           */
6304 /*-----------------------------------------------------------------*/
6305 static void genInline (iCode *ic)
6306 {
6307   char *buffer, *bp, *bp1;
6308
6309   FENTRY;
6310   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6311
6312   _G.inLine += (!options.asmpeep);
6313
6314   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6315   strcpy(buffer,IC_INLINE(ic));
6316
6317   /* emit each line as a code */
6318   while (*bp) {
6319     if (*bp == '\n') {
6320       *bp++ = '\0';
6321       
6322       if(*bp1)
6323         addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6324       bp1 = bp;
6325     } else {
6326       if (*bp == ':') {
6327         bp++;
6328         *bp = '\0';
6329         bp++;
6330
6331         /* print label, use this special format with NULL directive
6332          * to denote that the argument should not be indented with tab */
6333         addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6334
6335         bp1 = bp;
6336       } else
6337         bp++;
6338     }
6339   }
6340   if ((bp1 != bp) && *bp1)
6341     addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6342
6343   Safe_free(buffer);
6344
6345   _G.inLine -= (!options.asmpeep);
6346 }
6347
6348 /*-----------------------------------------------------------------*/
6349 /* genRRC - rotate right with carry                                */
6350 /*-----------------------------------------------------------------*/
6351 static void genRRC (iCode *ic)
6352 {
6353         operand *left , *result ;
6354         int size, offset = 0, same;
6355         
6356         FENTRY;
6357         /* rotate right with carry */
6358         left = IC_LEFT(ic);
6359         result=IC_RESULT(ic);
6360         aopOp (left,ic,FALSE);
6361         aopOp (result,ic,FALSE);
6362         
6363         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6364         
6365         same = pic14_sameRegs(AOP(result),AOP(left));
6366         
6367         size = AOP_SIZE(result);    
6368         
6369         /* get the lsb and put it into the carry */
6370         emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6371         
6372         offset = 0 ;
6373         
6374         while(size--) {
6375                 
6376                 if(same) {
6377                         emitpcode(POC_RRF, popGet(AOP(left),offset));
6378                 } else {
6379                         emitpcode(POC_RRFW, popGet(AOP(left),offset));
6380                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6381                 }
6382                 
6383                 offset++;
6384         }
6385         
6386         freeAsmop(left,NULL,ic,TRUE);
6387         freeAsmop(result,NULL,ic,TRUE);
6388 }
6389
6390 /*-----------------------------------------------------------------*/
6391 /* genRLC - generate code for rotate left with carry               */
6392 /*-----------------------------------------------------------------*/
6393 static void genRLC (iCode *ic)
6394 {    
6395         operand *left , *result ;
6396         int size, offset = 0;
6397         int same;
6398         
6399         FENTRY;
6400         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6401         /* rotate right with carry */
6402         left = IC_LEFT(ic);
6403         result=IC_RESULT(ic);
6404         aopOp (left,ic,FALSE);
6405         aopOp (result,ic,FALSE);
6406         
6407         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6408         
6409         same = pic14_sameRegs(AOP(result),AOP(left));
6410         
6411         /* move it to the result */
6412         size = AOP_SIZE(result);    
6413         
6414         /* get the msb and put it into the carry */
6415         emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6416         
6417         offset = 0 ;
6418         
6419         while(size--) {
6420                 
6421                 if(same) {
6422                         emitpcode(POC_RLF, popGet(AOP(left),offset));
6423                 } else {
6424                         emitpcode(POC_RLFW, popGet(AOP(left),offset));
6425                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6426                 }
6427                 
6428                 offset++;
6429         }
6430         
6431         
6432         freeAsmop(left,NULL,ic,TRUE);
6433         freeAsmop(result,NULL,ic,TRUE);
6434 }
6435
6436 /*-----------------------------------------------------------------*/
6437 /* genGetHbit - generates code get highest order bit               */
6438 /*-----------------------------------------------------------------*/
6439 static void genGetHbit (iCode *ic)
6440 {
6441         operand *left, *result;
6442         left = IC_LEFT(ic);
6443         result=IC_RESULT(ic);
6444         aopOp (left,ic,FALSE);
6445         aopOp (result,ic,FALSE);
6446         
6447         FENTRY;
6448         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6449         /* get the highest order byte into a */
6450         MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6451         if(AOP_TYPE(result) == AOP_CRY){
6452                 pic14_emitcode("rlc","a");
6453                 pic14_outBitC(result);
6454         }
6455         else{
6456                 pic14_emitcode("rl","a");
6457                 pic14_emitcode("anl","a,#0x01");
6458                 pic14_outAcc(result);
6459         }
6460         
6461         
6462         freeAsmop(left,NULL,ic,TRUE);
6463         freeAsmop(result,NULL,ic,TRUE);
6464 }
6465
6466 /*-----------------------------------------------------------------*/
6467 /* AccLsh - shift left accumulator by known count                  */
6468 /* MARK: pic14 always rotates through CARRY!                       */
6469 /*-----------------------------------------------------------------*/
6470 static void AccLsh (pCodeOp *pcop,int shCount)
6471 {
6472         FENTRY;
6473         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6474         shCount &= 0x0007;              // shCount : 0..7
6475         switch(shCount){
6476         case 0 :
6477                 return;
6478                 break;
6479         case 1 :
6480                 emitCLRC;
6481                 emitpcode(POC_RLF,pcop);
6482                 return;
6483                 break;
6484         case 2 :
6485                 emitpcode(POC_RLF,pcop);
6486                 emitpcode(POC_RLF,pcop);
6487                 break;
6488         case 3 :
6489                 emitpcode(POC_RLF,pcop);
6490                 emitpcode(POC_RLF,pcop);
6491                 emitpcode(POC_RLF,pcop);
6492                 break;
6493         case 4 :
6494                 emitpcode(POC_SWAPF,pcop);
6495                 break;
6496         case 5 :
6497                 emitpcode(POC_SWAPF,pcop);
6498                 emitpcode(POC_RLF,pcop);
6499                 break;
6500         case 6 :
6501                 emitpcode(POC_SWAPF,pcop);
6502                 emitpcode(POC_RLF,pcop);
6503                 emitpcode(POC_RLF,pcop);
6504                 break;
6505         case 7 :
6506                 emitpcode(POC_RRFW,pcop);
6507                 emitpcode(POC_RRF,pcop);
6508                 break;
6509         }
6510         /* clear invalid bits */
6511         emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6512         emitpcode(POC_ANDWF, pcop);
6513 }
6514
6515 /*-----------------------------------------------------------------*/
6516 /* AccRsh - shift right accumulator by known count                 */
6517 /* MARK: pic14 always rotates through CARRY!                       */
6518 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6519 /*            1: mask out invalid bits (zero-extend)               */
6520 /*            2: sign-extend result (pretty slow)                  */
6521 /*-----------------------------------------------------------------*/
6522 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6523 {
6524         FENTRY;
6525         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6526         shCount &= 0x0007;              // shCount : 0..7
6527         switch(shCount){
6528         case 0 :
6529                 return;
6530                 break;
6531         case 1 :
6532                 /* load sign if needed */
6533                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6534                 else if (mask_mode == 1) emitCLRC;
6535                 emitpcode(POC_RRF,pcop);
6536                 return;
6537                 break;
6538         case 2 :
6539                 /* load sign if needed */
6540                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6541                 emitpcode(POC_RRF,pcop);
6542                 /* load sign if needed */
6543                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6544                 emitpcode(POC_RRF,pcop);
6545                 if (mask_mode == 2) return;
6546                 break;
6547         case 3 :
6548                 /* load sign if needed */
6549                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6550                 emitpcode(POC_RRF,pcop);
6551                 /* load sign if needed */
6552                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6553                 emitpcode(POC_RRF,pcop);
6554                 /* load sign if needed */
6555                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6556                 emitpcode(POC_RRF,pcop);
6557                 if (mask_mode == 2) return;
6558                 break;
6559         case 4 :
6560                 emitpcode(POC_SWAPF,pcop);
6561                 break;
6562         case 5 :
6563                 emitpcode(POC_SWAPF,pcop);
6564                 emitpcode(POC_RRF,pcop);
6565                 break;
6566         case 6 :
6567                 emitpcode(POC_SWAPF,pcop);
6568                 emitpcode(POC_RRF,pcop);
6569                 emitpcode(POC_RRF,pcop);
6570                 break;
6571         case 7 :
6572                 if (mask_mode == 2)
6573                 {
6574                         /* load sign */
6575                         emitpcode(POC_RLFW,pcop);
6576                         emitpcode(POC_CLRF,pcop);
6577                         emitSKPNC;
6578                         emitpcode(POC_COMF,pcop);
6579                         return;
6580                 } else {
6581                         emitpcode(POC_RLFW,pcop);
6582                         emitpcode(POC_RLF,pcop);
6583                 }
6584                 break;
6585         }
6586
6587         if (mask_mode == 0)
6588         {
6589                 /* leave invalid bits undefined */
6590                 return;
6591         }
6592         
6593         /* clear invalid bits -- zero-extend */
6594         emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6595         emitpcode(POC_ANDWF, pcop);
6596
6597         if (mask_mode == 2) {
6598           /* sign-extend */
6599           emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6600           emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6601           emitpcode(POC_IORWF, pcop);
6602         }
6603 }
6604
6605 #if 0
6606 /*-----------------------------------------------------------------*/
6607 /* AccSRsh - signed right shift accumulator by known count                 */
6608 /*-----------------------------------------------------------------*/
6609 static void AccSRsh (int shCount)
6610 {
6611         symbol *tlbl ;
6612         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6613         if(shCount != 0){
6614                 if(shCount == 1){
6615                         pic14_emitcode("mov","c,acc.7");
6616                         pic14_emitcode("rrc","a");
6617                 } else if(shCount == 2){
6618                         pic14_emitcode("mov","c,acc.7");
6619                         pic14_emitcode("rrc","a");
6620                         pic14_emitcode("mov","c,acc.7");
6621                         pic14_emitcode("rrc","a");
6622                 } else {
6623                         tlbl = newiTempLabel(NULL);
6624                         /* rotate right accumulator */
6625                         AccRol(8 - shCount);
6626                         /* and kill the higher order bits */
6627                         pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6628                         pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6629                         pic14_emitcode("orl","a,#0x%02x",
6630                                 (unsigned char)~SRMask[shCount]);
6631                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6632                 }
6633         }
6634 }
6635
6636 /*-----------------------------------------------------------------*/
6637 /* shiftR1Left2Result - shift right one byte from left to result   */
6638 /*-----------------------------------------------------------------*/
6639 static void shiftR1Left2ResultSigned (operand *left, int offl,
6640                                                                           operand *result, int offr,
6641                                                                           int shCount)
6642 {
6643         int same;
6644         
6645         FENTRY;
6646         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6647         
6648         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6649         
6650         switch(shCount) {
6651         case 1:
6652                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6653                 if(same) 
6654                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6655                 else {
6656                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6657                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6658                 }
6659                 
6660                 break;
6661         case 2:
6662                 
6663                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6664                 if(same) 
6665                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6666                 else {
6667                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6668                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6669                 }
6670                 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6671                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6672                 
6673                 break;
6674                 
6675         case 3:
6676                 if(same)
6677                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6678                 else {
6679                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6680                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6681                 }
6682                 
6683                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6684                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6685                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6686                 
6687                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6688                 emitpcode(POC_IORLW, popGetLit(0xe0));
6689                 
6690                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6691                 break;
6692                 
6693         case 4:
6694                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6695                 emitpcode(POC_ANDLW,  popGetLit(0x0f));
6696                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6697                 emitpcode(POC_IORLW,  popGetLit(0xf0));
6698                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6699                 break;
6700         case 5:
6701                 if(same) {
6702                         emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6703                 } else {
6704                         emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6705                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6706                 }
6707                 emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6708                 emitpcode(POC_ANDLW,  popGetLit(0x07));
6709                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6710                 emitpcode(POC_IORLW,  popGetLit(0xf8));
6711                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6712                 break;
6713                 
6714         case 6:
6715                 if(same) {
6716                         emitpcode(POC_MOVLW, popGetLit(0x00));
6717                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6718                         emitpcode(POC_MOVLW, popGetLit(0xfe));
6719                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6720                         emitpcode(POC_IORLW, popGetLit(0x01));
6721                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6722                 } else {
6723                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6724                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6725                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6726                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6727                         emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6728                 }
6729                 break;
6730                 
6731         case 7:
6732                 if(same) {
6733                         emitpcode(POC_MOVLW, popGetLit(0x00));
6734                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6735                         emitpcode(POC_MOVLW, popGetLit(0xff));
6736                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6737                 } else {
6738                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6739                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6740                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6741                 }
6742                 
6743         default:
6744                 break;
6745         }
6746 }
6747
6748 /*-----------------------------------------------------------------*/
6749 /* shiftR1Left2Result - shift right one byte from left to result   */
6750 /*-----------------------------------------------------------------*/
6751 static void shiftR1Left2Result (operand *left, int offl,
6752                                                                 operand *result, int offr,
6753                                                                 int shCount, int sign)
6754 {
6755         int same;
6756         
6757         FENTRY;
6758         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6759         
6760         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6761         
6762         /* Copy the msb into the carry if signed. */
6763         if(sign) {
6764                 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6765                 return;
6766         }
6767         
6768         
6769         
6770         switch(shCount) {
6771         case 1:
6772                 emitCLRC;
6773                 if(same) 
6774                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6775                 else {
6776                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6777                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6778                 }
6779                 break;
6780         case 2:
6781                 emitCLRC;
6782                 if(same) {
6783                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6784                 } else {
6785                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6786                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6787                 }
6788                 emitCLRC;
6789                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6790                 
6791                 break;
6792         case 3:
6793                 if(same)
6794                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6795                 else {
6796                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6797                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6798                 }
6799                 
6800                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6801                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6802                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6803                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6804                 break;
6805                 
6806         case 4:
6807                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6808                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6809                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6810                 break;
6811                 
6812         case 5:
6813                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6814                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6815                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6816                 emitCLRC;
6817                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6818                 
6819                 break;
6820         case 6:
6821                 
6822                 emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6823                 emitpcode(POC_ANDLW, popGetLit(0x80));
6824                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6825                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6826                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6827                 break;
6828                 
6829         case 7:
6830                 
6831                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6832                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6833                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6834                 
6835                 break;
6836                 
6837         default:
6838                 break;
6839         }
6840 }
6841
6842 /*-----------------------------------------------------------------*/
6843 /* shiftL1Left2Result - shift left one byte from left to result    */
6844 /*-----------------------------------------------------------------*/
6845 static void shiftL1Left2Result (operand *left, int offl,
6846                                                                 operand *result, int offr, int shCount)
6847 {
6848         int same;
6849         
6850         //    char *l;
6851         FENTRY;
6852         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6853         
6854         same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6855         DEBUGpic14_emitcode ("; ***","same =  %d",same);
6856         //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6857         //    MOVA(l);
6858         /* shift left accumulator */
6859         //AccLsh(shCount); // don't comment out just yet...
6860         //    aopPut(AOP(result),"a",offr);
6861         
6862         switch(shCount) {
6863         case 1:
6864                 /* Shift left 1 bit position */
6865                 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6866                 if(same) {
6867                         emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6868                 } else {
6869                         emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6870                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6871                 }
6872                 break;
6873         case 2:
6874                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6875                 emitpcode(POC_ANDLW,popGetLit(0x7e));
6876                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6877                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6878                 break;
6879         case 3:
6880                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6881                 emitpcode(POC_ANDLW,popGetLit(0x3e));
6882                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6883                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6884                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6885                 break;
6886         case 4:
6887                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6888                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6889                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6890                 break;
6891         case 5:
6892                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6893                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6894                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6895                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6896                 break;
6897         case 6:
6898                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6899                 emitpcode(POC_ANDLW, popGetLit(0x30));
6900                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6901                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6902                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6903                 break;
6904         case 7:
6905                 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6906                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6907                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6908                 break;
6909                 
6910         default:
6911                 DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6912         }
6913         
6914 }
6915 #endif
6916
6917 /*-----------------------------------------------------------------*/
6918 /* movLeft2Result - move byte from left to result                  */
6919 /*-----------------------------------------------------------------*/
6920 static void movLeft2Result (operand *left, int offl,
6921                                                         operand *result, int offr)
6922 {
6923         char *l;
6924         FENTRY;
6925         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6926         if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6927                 l = aopGet(AOP(left),offl,FALSE,FALSE);
6928                 
6929                 if (*l == '@' && (IS_AOP_PREG(result))) {
6930                         pic14_emitcode("mov","a,%s",l);
6931                         aopPut(AOP(result),"a",offr);
6932                 } else {
6933                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6934                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6935                 }
6936         }
6937 }
6938
6939 /*-----------------------------------------------------------------*/
6940 /* shiftLeft_Left2ResultLit - shift left by known count            */
6941 /*-----------------------------------------------------------------*/
6942
6943 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6944 {
6945         int size, same, offr, i;
6946
6947         size = AOP_SIZE(left);
6948         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6949         
6950         same = pic14_sameRegs (AOP(left), AOP(result));
6951         
6952         offr = shCount / 8;
6953         shCount = shCount & 0x07;
6954
6955         size -= offr;
6956
6957         switch (shCount)
6958         {
6959         case 0: /* takes 0 or 2N cycles (for offr==0) */
6960                 if (!same || offr) {
6961                         for (i=size-1; i >= 0; i--)
6962                                 movLeft2Result (left, i, result, offr + i);
6963                 } // if
6964                 break;
6965                 
6966         case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6967                 if (same && offr) {
6968                         shiftLeft_Left2ResultLit (left, result, 8 * offr);
6969                         shiftLeft_Left2ResultLit (result, result, shCount);
6970                         return; /* prevent clearing result again */
6971                 } else {
6972                         emitCLRC;
6973                         for (i=0; i < size; i++) {
6974                                 if (same && !offr) {
6975                                         emitpcode (POC_RLF, popGet (AOP(left), i));
6976                                 } else {
6977                                         emitpcode (POC_RLFW, popGet (AOP(left), i));
6978                                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6979                                 } // if
6980                         } // for
6981                 } // if (offr)
6982                 break;
6983                 
6984         case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6985                 /* works in-place/with offr as well */
6986                 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6987                 emitpcode (POC_ANDLW, popGetLit (0xF0));
6988                 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6989
6990                 for (i = size - 2; i >= 0; i--)
6991                 {
6992                         emitpcode (POC_SWAPFW, popGet (AOP(left), i));
6993                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6994                         emitpcode (POC_ANDLW, popGetLit (0x0F));
6995                         emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
6996                         emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
6997                 } // for i
6998                 break;
6999                 
7000         case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7001                 /* works in-place/with offr as well */
7002                 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7003                 for (i = size-2; i >= 0; i--) {
7004                         emitpcode (POC_RRFW, popGet (AOP(left), i));
7005                         emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7006                 } // for i
7007                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7008                 emitpcode (POC_RRF, popGet (AOP(result), offr));
7009                 break;
7010         
7011         default:
7012                 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7013                 shiftLeft_Left2ResultLit (result, result, 1);
7014                 return; /* prevent clearing result again */
7015                 break;
7016         } // switch
7017
7018         while (0 < offr--)
7019         {
7020                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7021         } // while
7022 }
7023
7024 /*-----------------------------------------------------------------*/
7025 /* shiftRight_Left2ResultLit - shift right by known count          */
7026 /*-----------------------------------------------------------------*/
7027
7028 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7029 {
7030         int size, same, offr, i;
7031
7032         size = AOP_SIZE(left);
7033         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7034         
7035         same = pic14_sameRegs (AOP(left), AOP(result));
7036         
7037         offr = shCount / 8;
7038         shCount = shCount & 0x07;
7039
7040         size -= offr;
7041
7042         if (size)
7043         {
7044                 switch (shCount)
7045                 {
7046                 case 0: /* takes 0 or 2N cycles (for offr==0) */
7047                         if (!same || offr) {
7048                                 for (i=0; i < size; i++)
7049                                         movLeft2Result (left, i + offr, result, i);
7050                         } // if
7051                         break;
7052                         
7053                 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7054                         emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7055                         if (same && offr) {
7056                                 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7057                                 shiftRight_Left2ResultLit (result, result, shCount, sign);
7058                                 return; /* prevent sign-extending result again */
7059                         } else {
7060                                 emitCLRC;
7061                                 if (sign) {
7062                                         emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7063                                         emitSETC;
7064                                 }
7065                                 for (i = size-1; i >= 0; i--) {
7066                                         if (same && !offr) {
7067                                                 emitpcode (POC_RRF, popGet (AOP(left), i));
7068                                         } else {
7069                                                 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7070                                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7071                                         }
7072                                 } // for i
7073                         } // if (offr)
7074                         break;
7075                         
7076                 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7077                         /* works in-place/with offr as well */
7078                         emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7079                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7080                         emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7081
7082                         for (i = 1; i < size; i++)
7083                         {
7084                                 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7085                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7086                                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7087                                 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7088                                 emitpcode (POC_XORWF, popGet (AOP(result), i));
7089                         } // for i
7090
7091                         if (sign)
7092                         {
7093                                 emitpcode (POC_MOVLW, popGetLit (0xF0));
7094                                 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7095                                 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7096                         } // if
7097                         break;
7098                         
7099                 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7100                         /* works in-place/with offr as well */
7101                         emitpcode (POC_RLFW, popGet (AOP(left), offr));
7102                         for (i = 0; i < size-1; i++) {
7103                                 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7104                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7105                         } // for i
7106                         emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7107                         if (!sign) {
7108                                 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7109                         } else {
7110                                 emitSKPNC;
7111                                 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7112                         }
7113                         break;
7114                 
7115                 default:
7116                         shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7117                         shiftRight_Left2ResultLit (result, result, 1, sign);
7118                         return; /* prevent sign extending result again */
7119                         break;
7120                 } // switch
7121         } // if
7122
7123         addSign (result, size, sign);
7124 }
7125
7126 #if 0
7127 /*-----------------------------------------------------------------*/
7128 /* shiftL2Left2Result - shift left two bytes from left to result   */
7129 /*-----------------------------------------------------------------*/
7130 static void shiftL2Left2Result (operand *left, int offl,
7131                                                                 operand *result, int offr, int shCount)
7132 {
7133         FENTRY;
7134         
7135         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7136         
7137         if(pic14_sameRegs(AOP(result), AOP(left))) {
7138                 switch(shCount) {
7139                 case 0:
7140                         break;
7141                 case 1:
7142                 case 2:
7143                 case 3:
7144                         
7145                         emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7146                         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7147                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7148                         
7149                         while(--shCount) {
7150                                 emitCLRC;
7151                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7152                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7153                         }
7154                         
7155                         break;
7156                 case 4:
7157                 case 5:
7158                         emitpcode(POC_MOVLW, popGetLit(0x0f));
7159                         emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7160                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7161                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7162                         emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7163                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7164                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7165                         if(shCount >=5) {
7166                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7167                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7168                         }
7169                         break;
7170                 case 6:
7171                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7172                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7173                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7174                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7175                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7176                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7177                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7178                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7179                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7180                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7181                         break;
7182                 case 7:
7183                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7184                         emitpcode(POC_RRFW, popGet(AOP(result),offr));
7185                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7186                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7187                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7188                 }
7189                 
7190         } else {
7191                 switch(shCount) {
7192                 case 0:
7193                         break;
7194                 case 1:
7195                 case 2:
7196                 case 3:
7197                 /* note, use a mov/add for the shift since the mov has a
7198                         chance of getting optimized out */
7199                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7200                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7201                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7202                         emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
7203                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7204                         
7205                         while(--shCount) {
7206                                 emitCLRC;
7207                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7208                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7209                         }
7210                         break;
7211                         
7212                 case 4:
7213                 case 5:
7214                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7215                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7216                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7217                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7218                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7219                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7220                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7221                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7222                         
7223                         
7224                         if(shCount == 5) {
7225                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7226                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7227                         }
7228                         break;
7229                 case 6:
7230                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7231                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7232                         emitpcode(POC_RRFW, popGet(AOP(result),offl));
7233                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
7234                         
7235                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7236                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7237                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7238                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7239                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7240                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7241                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7242                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7243                         break;
7244                 case 7:
7245                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7246                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7247                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7248                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7249                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7250                 }
7251         }
7252         
7253 }
7254
7255 /*-----------------------------------------------------------------*/
7256 /* shiftR2Left2Result - shift right two bytes from left to result  */
7257 /*-----------------------------------------------------------------*/
7258 static void shiftR2Left2Result (operand *left, int offl,
7259                                                                 operand *result, int offr,
7260                                                                 int shCount, int sign)
7261 {
7262         int same=0;
7263         
7264         FENTRY;
7265         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7266         same = pic14_sameRegs(AOP(result), AOP(left));
7267         
7268         if(same && ((offl + MSB16) == offr)){
7269                 same=1;
7270                 /* don't crash result[offr] */
7271                 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7272                 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7273         }
7274         /* else {
7275         movLeft2Result(left,offl, result, offr);
7276         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7277         }
7278         */
7279         /* a:x >> shCount (x = lsb(result))*/
7280         /*
7281         if(sign)
7282         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7283         else {
7284         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7285         */
7286         switch(shCount) {
7287         case 0:
7288                 break;
7289         case 1:
7290         case 2:
7291         case 3:
7292                 if(sign)
7293                         emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7294                 else
7295                         emitCLRC;
7296                 
7297                 if(same) {
7298                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7299                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7300                 } else {
7301                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7302                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7303                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7304                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7305                 }
7306                 
7307                 while(--shCount) {
7308                         if(sign)
7309                                 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7310                         else
7311                                 emitCLRC;
7312                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7313                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7314                 }
7315                 break;
7316         case 4:
7317         case 5:
7318                 if(same) {
7319                         
7320                         emitpcode(POC_MOVLW, popGetLit(0xf0));
7321                         emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7322                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7323                         
7324                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7325                         emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7326                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7327                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7328                 } else {
7329                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7330                         emitpcode(POC_ANDLW, popGetLit(0x0f));
7331                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7332                         
7333                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7334                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7335                         emitpcode(POC_ANDLW, popGetLit(0xf0));
7336                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7337                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7338                 }
7339                 
7340                 if(shCount >=5) {
7341                         emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7342                         emitpcode(POC_RRF, popGet(AOP(result),offr));
7343                 }
7344                 
7345                 if(sign) {
7346                         emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7347                         emitpcode(POC_BTFSC, 
7348                                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7349                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7350                 }
7351                 
7352                 break;
7353                 
7354         case 6:
7355                 if(same) {
7356                         
7357                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7358                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7359                         
7360                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7361                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7362                         emitpcode(POC_RLFW, popGet(AOP(result),offr));
7363                         emitpcode(POC_ANDLW,popGetLit(0x03));
7364                         if(sign) {
7365                                 emitpcode(POC_BTFSC, 
7366                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7367                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7368                         }
7369                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7370                         emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7371                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7372                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7373                 } else {
7374                         emitpcode(POC_RLFW, popGet(AOP(left),offl));
7375                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7376                         emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7377                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7378                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7379                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7380                         emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7381                         emitpcode(POC_ANDLW,popGetLit(0x03));
7382                         if(sign) {
7383                                 emitpcode(POC_BTFSC, 
7384                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7385                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7386                         }
7387                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7388                         //emitpcode(POC_RLF,  popGet(AOP(result),offr));
7389                         
7390                         
7391                 }
7392                 
7393                 break;
7394         case 7:
7395                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7396                 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7397                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7398                 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7399                 if(sign) {
7400                         emitSKPNC;
7401                         emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7402                 } else 
7403                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7404   }
7405 }
7406
7407 /*-----------------------------------------------------------------*/
7408 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7409 /*-----------------------------------------------------------------*/
7410 static void shiftLLeftOrResult (operand *left, int offl,
7411                                                                 operand *result, int offr, int shCount)
7412 {
7413         FENTRY;
7414         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7415         
7416         /* shift left accumulator */
7417         AccLsh(left,offl,shCount);
7418         /* or with result */
7419         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7420         assert ( !"broken (modifies left, fails for left==result))" );
7421 }
7422
7423 /*-----------------------------------------------------------------*/
7424 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7425 /*-----------------------------------------------------------------*/
7426 static void shiftRLeftOrResult (operand *left, int offl,
7427                                                                 operand *result, int offr, int shCount)
7428 {
7429         FENTRY;
7430         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7431         
7432         /* shift right accumulator */
7433         AccRsh(left,offl,shCount);
7434         /* or with result */
7435         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7436         assert ( !"broken (modifies left, fails for left==result))" );
7437 }
7438
7439 /*-----------------------------------------------------------------*/
7440 /* genlshOne - left shift a one byte quantity by known count       */
7441 /*-----------------------------------------------------------------*/
7442 static void genlshOne (operand *result, operand *left, int shCount)
7443 {       
7444         FENTRY;
7445         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7446         shiftL1Left2Result(left, LSB, result, LSB, shCount);
7447 }
7448
7449 /*-----------------------------------------------------------------*/
7450 /* genlshTwo - left shift two bytes by known amount != 0           */
7451 /*-----------------------------------------------------------------*/
7452 static void genlshTwo (operand *result,operand *left, int shCount)
7453 {
7454         int size;
7455         
7456         FENTRY;
7457         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7458         size = pic14_getDataSize(result);
7459         
7460         /* if shCount >= 8 */
7461         if (shCount >= 8) {
7462                 shCount -= 8 ;
7463                 
7464                 if (size > 1){
7465                         if (shCount)
7466                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7467                         else 
7468                                 movLeft2Result(left, LSB, result, MSB16);
7469                 }
7470                 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7471         }
7472         
7473         /*  1 <= shCount <= 7 */
7474         else {  
7475                 if(size == 1)
7476                         shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7477                 else 
7478                         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7479         }
7480 }
7481
7482 /*-----------------------------------------------------------------*/
7483 /* shiftLLong - shift left one long from left to result            */
7484 /* offl = LSB or MSB16                                             */
7485 /*-----------------------------------------------------------------*/
7486 static void shiftLLong (operand *left, operand *result, int offr )
7487 {
7488         char *l;
7489         int size = AOP_SIZE(result);
7490         
7491         FENTRY;
7492         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7493         if(size >= LSB+offr){
7494                 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7495                 MOVA(l);
7496                 pic14_emitcode("add","a,acc");
7497                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7498                         size >= MSB16+offr && offr != LSB )
7499                         pic14_emitcode("xch","a,%s",
7500                         aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7501                 else      
7502                         aopPut(AOP(result),"a",LSB+offr);
7503         }
7504         
7505         if(size >= MSB16+offr){
7506                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7507                         l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7508                         MOVA(l);
7509                 }
7510                 pic14_emitcode("rlc","a");
7511                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7512                         size >= MSB24+offr && offr != LSB)
7513                         pic14_emitcode("xch","a,%s",
7514                         aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7515                 else      
7516                         aopPut(AOP(result),"a",MSB16+offr);
7517         }
7518         
7519         if(size >= MSB24+offr){
7520                 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7521                         l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7522                         MOVA(l);
7523                 }
7524                 pic14_emitcode("rlc","a");
7525                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7526                         size >= MSB32+offr && offr != LSB )
7527                         pic14_emitcode("xch","a,%s",
7528                         aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7529                 else      
7530                         aopPut(AOP(result),"a",MSB24+offr);
7531         }
7532         
7533         if(size > MSB32+offr){
7534                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7535                         l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7536                         MOVA(l);  
7537                 }
7538                 pic14_emitcode("rlc","a");
7539                 aopPut(AOP(result),"a",MSB32+offr);
7540         }
7541         if(offr != LSB)
7542                 aopPut(AOP(result),zero,LSB);       
7543 }
7544
7545 /*-----------------------------------------------------------------*/
7546 /* genlshFour - shift four byte by a known amount != 0             */
7547 /*-----------------------------------------------------------------*/
7548 static void genlshFour (operand *result, operand *left, int shCount)
7549 {
7550         int size;
7551         
7552         FENTRY;
7553         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7554         size = AOP_SIZE(result);
7555         
7556         /* if shifting more that 3 bytes */
7557         if (shCount >= 24 ) {
7558                 shCount -= 24;
7559                 if (shCount)
7560                 /* lowest order of left goes to the highest
7561                 order of the destination */
7562                 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7563                 else
7564                         movLeft2Result(left, LSB, result, MSB32);
7565                 aopPut(AOP(result),zero,LSB);
7566                 aopPut(AOP(result),zero,MSB16);
7567                 aopPut(AOP(result),zero,MSB32);
7568                 return;
7569         }
7570         
7571         /* more than two bytes */
7572         else if ( shCount >= 16 ) {
7573                 /* lower order two bytes goes to higher order two bytes */
7574                 shCount -= 16;
7575                 /* if some more remaining */
7576                 if (shCount)
7577                         shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7578                 else {
7579                         movLeft2Result(left, MSB16, result, MSB32);
7580                         movLeft2Result(left, LSB, result, MSB24);
7581                 }
7582                 aopPut(AOP(result),zero,MSB16);
7583                 aopPut(AOP(result),zero,LSB);
7584                 return;
7585         }    
7586         
7587         /* if more than 1 byte */
7588         else if ( shCount >= 8 ) {
7589                 /* lower order three bytes goes to higher order  three bytes */
7590                 shCount -= 8;
7591                 if(size == 2){
7592                         if(shCount)
7593                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7594                         else
7595                                 movLeft2Result(left, LSB, result, MSB16);
7596                 }
7597                 else{   /* size = 4 */
7598                         if(shCount == 0){
7599                                 movLeft2Result(left, MSB24, result, MSB32);
7600                                 movLeft2Result(left, MSB16, result, MSB24);
7601                                 movLeft2Result(left, LSB, result, MSB16);
7602                                 aopPut(AOP(result),zero,LSB);
7603                         }
7604                         else if(shCount == 1)
7605                                 shiftLLong(left, result, MSB16);
7606                         else{
7607                                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7608                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7609                                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7610                                 aopPut(AOP(result),zero,LSB);
7611                         }
7612                 }
7613         }
7614         
7615         /* 1 <= shCount <= 7 */
7616         else if(shCount <= 2){
7617                 shiftLLong(left, result, LSB);
7618                 if(shCount == 2)
7619                         shiftLLong(result, result, LSB);
7620         }
7621         /* 3 <= shCount <= 7, optimize */
7622         else{
7623                 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7624                 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7625                 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7626         }
7627 }
7628 #endif
7629
7630 #if 0
7631 /*-----------------------------------------------------------------*/
7632 /* genLeftShiftLiteral - left shifting by known count              */
7633 /*-----------------------------------------------------------------*/
7634 static void genLeftShiftLiteral (operand *left,
7635                                                                  operand *right,
7636                                                                  operand *result,
7637                                                                  iCode *ic)
7638 {    
7639         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7640         //int size;
7641         
7642         FENTRY;
7643         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7644         freeAsmop(right,NULL,ic,TRUE);
7645         
7646         aopOp(left,ic,FALSE);
7647         aopOp(result,ic,FALSE);
7648
7649         size = getSize(operandType(result));
7650         
7651 #if VIEW_SIZE
7652         pic14_emitcode("; shift left ","result %d, left %d",size,
7653                 AOP_SIZE(left));
7654 #endif
7655         
7656         /* I suppose that the left size >= result size */
7657         if(shCount == 0){
7658                 while(size--){
7659                         movLeft2Result(left, size, result, size);
7660                 }
7661         }
7662         
7663         else if(shCount >= (size * 8))
7664                 while(size--)
7665                         aopPut(AOP(result),zero,size);
7666                 else{
7667                         switch (size) {
7668                         case 1:
7669                                 genlshOne (result,left,shCount);
7670                                 break;
7671                                 
7672                         case 2:
7673                         case 3:
7674                                 genlshTwo (result,left,shCount);
7675                                 break;
7676                                 
7677                         case 4:
7678                                 genlshFour (result,left,shCount);
7679                                 break;
7680                         }
7681                 }
7682                 freeAsmop(left,NULL,ic,TRUE);
7683                 freeAsmop(result,NULL,ic,TRUE);
7684 }
7685 #endif
7686
7687 /*-----------------------------------------------------------------*
7688 * genMultiAsm - repeat assembly instruction for size of register.
7689 * if endian == 1, then the high byte (i.e base address + size of 
7690 * register) is used first else the low byte is used first;
7691 *-----------------------------------------------------------------*/
7692 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7693 {
7694         
7695         int offset = 0;
7696         
7697         FENTRY;
7698         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7699         
7700         if(!reg)
7701                 return;
7702         
7703         if(!endian) {
7704                 endian = 1;
7705         } else {
7706                 endian = -1;
7707                 offset = size-1;
7708         }
7709         
7710         while(size--) {
7711                 emitpcode(poc,    popGet(AOP(reg),offset));
7712                 offset += endian;
7713         }
7714         
7715 }
7716
7717 #if 0
7718 /*-----------------------------------------------------------------*/
7719 /* genLeftShift - generates code for left shifting                 */
7720 /*-----------------------------------------------------------------*/
7721 static void genLeftShift (iCode *ic)
7722 {
7723         operand *left,*right, *result;
7724         int size, offset;
7725         unsigned long lit = 0L;
7726         char *l;
7727         symbol *tlbl , *tlbl1;
7728         pCodeOp *pctemp;
7729         
7730         FENTRY;
7731         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7732         
7733         right = IC_RIGHT(ic);
7734         left  = IC_LEFT(ic);
7735         result = IC_RESULT(ic);
7736         
7737         aopOp(right,ic,FALSE);
7738         aopOp(left,ic,FALSE);
7739         aopOp(result,ic,FALSE);
7740         
7741         
7742         /* if the shift count is known then do it 
7743         as efficiently as possible */
7744         if (AOP_TYPE(right) == AOP_LIT) {
7745                 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7746                 return ;
7747         }
7748         
7749         /* shift count is unknown then we have to form 
7750         a loop get the loop count in B : Note: we take
7751         only the lower order byte since shifting
7752         more that 32 bits make no sense anyway, ( the
7753         largest size of an object can be only 32 bits ) */  
7754         
7755         /* this code fails for RIGHT == RESULT */
7756         assert (!pic14_sameRegs (AOP(right), AOP(result)));
7757         
7758         /* now move the left to the result if they are not the
7759         same */
7760         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7761                 AOP_SIZE(result) > 1) {
7762                 
7763                 size = AOP_SIZE(result);
7764                 offset=0;
7765                 while (size--) {
7766                         l = aopGet(AOP(left),offset,FALSE,TRUE);
7767                         if (*l == '@' && (IS_AOP_PREG(result))) {
7768                                 
7769                                 pic14_emitcode("mov","a,%s",l);
7770                                 aopPut(AOP(result),"a",offset);
7771                         } else {
7772                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7773                                 emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7774                                 //aopPut(AOP(result),l,offset);
7775                         }
7776                         offset++;
7777                 }
7778         }
7779         
7780         if(AOP_TYPE(left) == AOP_LIT)
7781                 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7782
7783         size = AOP_SIZE(result);
7784         
7785         /* if it is only one byte then */
7786         if (size == 1) {
7787                 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7788                         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7789                         emitpcode(POC_ANDLW,  popGetLit(0xf0));
7790                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7791                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7792                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7793                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7794                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7795                         emitpcode(POC_RLFW,   popGet(AOP(result),0));
7796                         emitpcode(POC_ANDLW,  popGetLit(0xfe));
7797                         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7798                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7799                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7800                 } else {
7801                         
7802                         tlbl = newiTempLabel(NULL);
7803                         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7804                                 mov2w (AOP(left), 0);
7805                                 emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7806                         }
7807                         
7808                         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7809                         emitpcode(POC_RRF,    popGet(AOP(result),0));
7810                         emitpLabel(tlbl->key);
7811                         emitpcode(POC_RLF,    popGet(AOP(result),0));
7812                         emitpcode(POC_ADDLW,  popGetLit(1));
7813                         emitSKPC;
7814                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7815                 }
7816                 goto release ;
7817         }
7818         
7819         if (pic14_sameRegs(AOP(left),AOP(result))) {
7820                 
7821                 tlbl = newiTempLabel(NULL);
7822                 emitpcode(POC_COMFW,  popGet(AOP(right),0));
7823                 genMultiAsm(POC_RRF, result, size,1);
7824                 emitpLabel(tlbl->key);
7825                 genMultiAsm(POC_RLF, result, size,0);
7826                 emitpcode(POC_ADDLW,  popGetLit(1));
7827                 emitSKPC;
7828                 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7829                 goto release;
7830         }
7831         
7832         //tlbl = newiTempLabel(NULL);
7833         //offset = 0 ;   
7834         //tlbl1 = newiTempLabel(NULL);
7835         
7836         //reAdjustPreg(AOP(result));    
7837         
7838         //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7839         //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7840         //l = aopGet(AOP(result),offset,FALSE,FALSE);
7841         //MOVA(l);
7842         //pic14_emitcode("add","a,acc");         
7843         //aopPut(AOP(result),"a",offset++);
7844         //while (--size) {
7845         //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7846         //  MOVA(l);
7847         //  pic14_emitcode("rlc","a");         
7848         //  aopPut(AOP(result),"a",offset++);
7849         //}
7850         //reAdjustPreg(AOP(result));
7851         
7852         //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7853         //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7854         
7855         
7856         tlbl = newiTempLabel(NULL);
7857         tlbl1= newiTempLabel(NULL);
7858         
7859         size = AOP_SIZE(result);
7860         offset = 1;
7861         
7862         pctemp = popGetTempReg();  /* grab a temporary working register. */
7863         
7864         emitpcode(POC_MOVFW, popGet(AOP(right),0));
7865         
7866         /* offset should be 0, 1 or 3 */
7867         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7868         emitSKPNZ;
7869         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7870         
7871         emitpcode(POC_MOVWF, pctemp);
7872         
7873         
7874         emitpLabel(tlbl->key);
7875         
7876         emitCLRC;
7877         emitpcode(POC_RLF,  popGet(AOP(result),0));
7878         while(--size)
7879                 emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7880         
7881         emitpcode(POC_DECFSZ,  pctemp);
7882         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7883         emitpLabel(tlbl1->key);
7884         
7885         popReleaseTempReg(pctemp);
7886         
7887         
7888 release:
7889         freeAsmop (right,NULL,ic,TRUE);
7890         freeAsmop(left,NULL,ic,TRUE);
7891         freeAsmop(result,NULL,ic,TRUE);
7892 }
7893 #endif
7894
7895 #if 0
7896 /*-----------------------------------------------------------------*/
7897 /* genrshOne - right shift a one byte quantity by known count      */
7898 /*-----------------------------------------------------------------*/
7899 static void genrshOne (operand *result, operand *left,
7900                                            int shCount, int sign)
7901 {
7902         FENTRY;
7903         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7904         shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7905 }
7906
7907 /*-----------------------------------------------------------------*/
7908 /* genrshTwo - right shift two bytes by known amount != 0          */
7909 /*-----------------------------------------------------------------*/
7910 static void genrshTwo (operand *result,operand *left,
7911                                            int shCount, int sign)
7912 {
7913         FENTRY;
7914         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7915         /* if shCount >= 8 */
7916         if (shCount >= 8) {
7917                 shCount -= 8 ;
7918                 if (shCount)
7919                         shiftR1Left2Result(left, MSB16, result, LSB,
7920                         shCount, sign);
7921                 else
7922                         movLeft2Result(left, MSB16, result, LSB);
7923                 
7924                 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7925                 
7926                 if(sign) {
7927                         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7928                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7929                 }
7930         }
7931         
7932         /*  1 <= shCount <= 7 */
7933         else
7934                 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7935 }
7936
7937 /*-----------------------------------------------------------------*/
7938 /* shiftRLong - shift right one long from left to result           */
7939 /* offl = LSB or MSB16                                             */
7940 /*-----------------------------------------------------------------*/
7941 static void shiftRLong (operand *left, int offl,
7942                                                 operand *result, int sign)
7943 {
7944         int size, same;
7945         
7946         FENTRY;
7947         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7948         
7949         size = AOP_SIZE(left);
7950         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7951         
7952         if (sign)
7953                 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7954         else
7955                 emitCLRC;
7956
7957         assert (offl >= 0 && offl < size);
7958
7959         same = pic14_sameRegs (AOP(left), AOP(result));
7960
7961         /* perform the shift */
7962         while (size--)
7963         {
7964                 if (same && !offl) {
7965                         emitpcode (POC_RRF, popGet (AOP(result), size));
7966                 } else {
7967                         emitpcode (POC_RRFW, popGet (AOP(left), size));
7968                         emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7969                 }
7970         } // while
7971
7972         addSign (result, AOP_SIZE(left) - offl, sign);
7973 }
7974
7975 /*-----------------------------------------------------------------*/
7976 /* genrshFour - shift four byte by a known amount != 0             */
7977 /*-----------------------------------------------------------------*/
7978 static void genrshFour (operand *result, operand *left,
7979                                                 int shCount, int sign)
7980 {
7981         FENTRY;
7982         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7983         /* if shifting more that 3 bytes */
7984         if(shCount >= 24 ) {
7985                 shCount -= 24;
7986                 if(shCount)
7987                         shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7988                 else
7989                         movLeft2Result(left, MSB32, result, LSB);
7990                 
7991                 addSign(result, MSB16, sign);
7992         }
7993         else if(shCount >= 16){
7994                 shCount -= 16;
7995                 if(shCount)
7996                         shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7997                 else{
7998                         movLeft2Result(left, MSB24, result, LSB);
7999                         movLeft2Result(left, MSB32, result, MSB16);
8000                 }
8001                 addSign(result, MSB24, sign);
8002         }
8003         else if(shCount >= 8){
8004                 shCount -= 8;
8005                 if(shCount == 1)
8006                         shiftRLong(left, MSB16, result, sign);
8007                 else if(shCount == 0){
8008                         movLeft2Result(left, MSB16, result, LSB);
8009                         movLeft2Result(left, MSB24, result, MSB16);
8010                         movLeft2Result(left, MSB32, result, MSB24);
8011                         addSign(result, MSB32, sign);
8012                 }
8013                 else{
8014                         shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8015                         shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8016                         /* the last shift is signed */
8017                         shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8018                         addSign(result, MSB32, sign);
8019                 }
8020         }
8021         else{   /* 1 <= shCount <= 7 */
8022                 if(shCount <= 2){
8023                         shiftRLong(left, LSB, result, sign);
8024                         if(shCount == 2)
8025                                 shiftRLong(result, LSB, result, sign);
8026                 }
8027                 else{
8028                         shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8029                         shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8030                         shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8031                 }
8032         }
8033 }
8034
8035 /*-----------------------------------------------------------------*/
8036 /* genRightShiftLiteral - right shifting by known count            */
8037 /*-----------------------------------------------------------------*/
8038 static void genRightShiftLiteral (operand *left,
8039                                                                   operand *right,
8040                                                                   operand *result,
8041                                                                   iCode *ic,
8042                                                                   int sign)
8043 {    
8044         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8045         int lsize,res_size;
8046         
8047         FENTRY;
8048         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8049         freeAsmop(right,NULL,ic,TRUE);
8050         
8051         aopOp(left,ic,FALSE);
8052         aopOp(result,ic,FALSE);
8053         
8054 #if VIEW_SIZE
8055         pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8056                 AOP_SIZE(left));
8057 #endif
8058         
8059         lsize = pic14_getDataSize(left);
8060         res_size = pic14_getDataSize(result);
8061         /* test the LEFT size !!! */
8062         
8063         /* I suppose that the left size >= result size */
8064         if(shCount == 0){
8065                 while(res_size--)
8066                         movLeft2Result(left, res_size, result, res_size);
8067         }
8068         
8069         else if(shCount >= (lsize * 8)){
8070                 
8071                 if(res_size == 1) {
8072                         emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8073                         if(sign) {
8074                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8075                                 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8076                         }
8077                 } else {
8078                         
8079                         if(sign) {
8080                                 emitpcode(POC_MOVLW, popGetLit(0));
8081                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8082                                 emitpcode(POC_MOVLW, popGetLit(0xff));
8083                                 while(res_size--)
8084                                         emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8085                                 
8086                         } else {
8087                                 
8088                                 while(res_size--)
8089                                         emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8090                         }
8091                 }
8092         } else {
8093                 
8094                 switch (res_size) {
8095                 case 1:
8096                         genrshOne (result,left,shCount,sign);
8097                         break;
8098                         
8099                 case 2:
8100                         genrshTwo (result,left,shCount,sign);
8101                         break;
8102                         
8103                 case 4:
8104                         genrshFour (result,left,shCount,sign);
8105                         break;
8106                 default :
8107                         break;
8108                 }
8109                 
8110         }
8111
8112         freeAsmop(left,NULL,ic,TRUE);
8113         freeAsmop(result,NULL,ic,TRUE);
8114 }
8115 #endif
8116
8117 #if 0
8118 /*-----------------------------------------------------------------*/
8119 /* genSignedRightShift - right shift of signed number              */
8120 /*-----------------------------------------------------------------*/
8121 static void genSignedRightShift (iCode *ic)
8122 {
8123         operand *right, *left, *result;
8124         int size, offset;
8125         //  char *l;
8126         symbol *tlbl, *tlbl1 ;
8127         pCodeOp *pctemp;
8128         
8129         //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8130         
8131         /* we do it the hard way put the shift count in b
8132         and loop thru preserving the sign */
8133         FENTRY;
8134         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8135         
8136         right = IC_RIGHT(ic);
8137         left  = IC_LEFT(ic);
8138         result = IC_RESULT(ic);
8139         
8140         aopOp(right,ic,FALSE);  
8141         aopOp(left,ic,FALSE);
8142         aopOp(result,ic,FALSE);
8143         
8144         
8145         if ( AOP_TYPE(right) == AOP_LIT) {
8146                 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8147                 //genRightShiftLiteral (left,right,result,ic,1);
8148                 return ;
8149         }
8150         /* shift count is unknown then we have to form 
8151         a loop get the loop count in B : Note: we take
8152         only the lower order byte since shifting
8153         more that 32 bits make no sense anyway, ( the
8154         largest size of an object can be only 32 bits ) */  
8155         
8156         //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8157         //pic14_emitcode("inc","b");
8158         //freeAsmop (right,NULL,ic,TRUE);
8159         //aopOp(left,ic,FALSE);
8160         //aopOp(result,ic,FALSE);
8161         
8162         /* now move the left to the result if they are not the
8163         same */
8164         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
8165                 AOP_SIZE(result) > 1) {
8166                 
8167                 size = AOP_SIZE(result);
8168                 offset=0;
8169                 while (size--) { 
8170                         /*
8171                         l = aopGet(AOP(left),offset,FALSE,TRUE);
8172                         if (*l == '@' && IS_AOP_PREG(result)) {
8173                                 pic14_emitcode("mov","a,%s",l);
8174                                 aopPut(AOP(result),"a",offset);
8175                         } else
8176                         aopPut(AOP(result),l,offset);
8177                         */
8178                         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
8179                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
8180                         
8181                         offset++;
8182                 }
8183         }
8184         
8185         /* mov the highest order bit to OVR */    
8186         tlbl = newiTempLabel(NULL);
8187         tlbl1= newiTempLabel(NULL);
8188         
8189         size = AOP_SIZE(result);
8190         offset = size - 1;
8191         
8192         pctemp = popGetTempReg();  /* grab a temporary working register. */
8193         
8194         emitpcode(POC_MOVFW, popGet(AOP(right),0));
8195         
8196         /* offset should be 0, 1 or 3 */
8197         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8198         emitSKPNZ;
8199         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
8200         
8201         emitpcode(POC_MOVWF, pctemp);
8202         
8203         
8204         emitpLabel(tlbl->key);
8205         
8206         emitpcode(POC_RLFW,  popGet(AOP(result),offset));
8207         emitpcode(POC_RRF,   popGet(AOP(result),offset));
8208         
8209         while(--size) {
8210                 emitpcode(POC_RRF,   popGet(AOP(result),--offset));
8211         }
8212         
8213         emitpcode(POC_DECFSZ,  pctemp);
8214         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8215         emitpLabel(tlbl1->key);
8216         
8217         popReleaseTempReg(pctemp);
8218 #if 0
8219         size = AOP_SIZE(result);
8220         offset = size - 1;
8221         pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8222         pic14_emitcode("rlc","a");
8223         pic14_emitcode("mov","ov,c");
8224         /* if it is only one byte then */
8225         if (size == 1) {
8226                 l = aopGet(AOP(left),0,FALSE,FALSE);
8227                 MOVA(l);
8228                 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8229                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8230                 pic14_emitcode("mov","c,ov");
8231                 pic14_emitcode("rrc","a");
8232                 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8233                 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8234                 aopPut(AOP(result),"a",0);
8235                 goto release ;
8236         }
8237         
8238         reAdjustPreg(AOP(result));
8239         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8240         pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
8241         pic14_emitcode("mov","c,ov");
8242         while (size--) {
8243                 l = aopGet(AOP(result),offset,FALSE,FALSE);
8244                 MOVA(l);
8245                 pic14_emitcode("rrc","a");         
8246                 aopPut(AOP(result),"a",offset--);
8247         }
8248         reAdjustPreg(AOP(result));
8249         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8250         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8251         
8252 release:
8253 #endif
8254         
8255         freeAsmop(left,NULL,ic,TRUE);
8256         freeAsmop(result,NULL,ic,TRUE);
8257         freeAsmop(right,NULL,ic,TRUE);
8258 }
8259 #endif
8260
8261 /*-----------------------------------------------------------------*/
8262 /* loadSignToC - load the operand's sign bit into CARRY            */
8263 /*-----------------------------------------------------------------*/
8264
8265 static void loadSignToC (operand *op)
8266 {
8267         FENTRY;
8268         assert (op && AOP(op) && AOP_SIZE(op));
8269
8270         emitCLRC;
8271         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8272         emitSETC;
8273 }
8274
8275 /*-----------------------------------------------------------------*/
8276 /* genRightShift - generate code for right shifting                */
8277 /*-----------------------------------------------------------------*/
8278 static void genGenericShift (iCode *ic, int shiftRight)
8279 {
8280         operand *right, *left, *result;
8281         sym_link *retype ;
8282         int size;
8283         symbol *tlbl, *tlbl1, *inverselbl;
8284         
8285         FENTRY;
8286         /* if signed then we do it the hard way preserve the
8287         sign bit moving it inwards */
8288         retype = getSpec(operandType(IC_RESULT(ic)));
8289         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8290         
8291         /* signed & unsigned types are treated the same : i.e. the
8292         signed is NOT propagated inwards : quoting from the
8293         ANSI - standard : "for E1 >> E2, is equivalent to division
8294         by 2**E2 if unsigned or if it has a non-negative value,
8295         otherwise the result is implementation defined ", MY definition
8296         is that the sign does not get propagated */
8297         
8298         right = IC_RIGHT(ic);
8299         left  = IC_LEFT(ic);
8300         result = IC_RESULT(ic);
8301         
8302         aopOp(right,ic,FALSE);
8303         aopOp(left,ic,FALSE);
8304         aopOp(result,ic,FALSE);
8305         
8306         /* if the shift count is known then do it 
8307         as efficiently as possible */
8308         if (AOP_TYPE(right) == AOP_LIT) {
8309                 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8310                 if (lit < 0)
8311                 {
8312                         lit = -lit;
8313                         shiftRight = !shiftRight;
8314                 }
8315                 
8316                 if (shiftRight)
8317                         shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8318                 else
8319                         shiftLeft_Left2ResultLit (left, result, lit);
8320                 //genRightShiftLiteral (left,right,result,ic, 0);
8321                 return ;
8322         }
8323         
8324         /* shift count is unknown then we have to form 
8325         a loop get the loop count in B : Note: we take
8326         only the lower order byte since shifting
8327         more that 32 bits make no sense anyway, ( the
8328         largest size of an object can be only 32 bits ) */  
8329
8330         /* we must not overwrite the shift counter */
8331         assert (!pic14_sameRegs(AOP(right),AOP(result)));
8332         
8333         /* now move the left to the result if they are not the
8334         same */
8335         if (!pic14_sameRegs(AOP(left),AOP(result)))
8336         {
8337                 size = min(AOP_SIZE(result), AOP_SIZE(left));
8338                 while (size--) {
8339                         mov2w(AOP(left), size);
8340                         movwf(AOP(result), size);
8341                 }
8342                 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8343         }
8344         
8345         tlbl = newiTempLabel(NULL);
8346         tlbl1= newiTempLabel(NULL);
8347         inverselbl = NULL;
8348         size = AOP_SIZE(result);
8349
8350         mov2w(AOP(right),0);
8351         if (!SPEC_USIGN(operandType(right)))
8352         {
8353                 inverselbl = newiTempLabel(NULL);
8354                 /* signed shift count -- invert shift direction for c<0 */
8355                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8356                 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8357         } // if
8358         emitpcode(POC_SUBLW, popGetLit(0));     /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8359         /* check for `a = b >> c' with `-c == 0' */
8360         emitSKPNZ;
8361         emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8362         emitpLabel(tlbl->key);
8363         /* propagate the sign bit inwards for SIGNED result */
8364         if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8365         genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8366         emitpcode(POC_ADDLW,  popGetLit(1));    /* clears CARRY (unless W==0 afterwards) */
8367         emitSKPC;
8368         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8369
8370         if (!SPEC_USIGN(operandType(right)))
8371         {
8372                 symbol *inv_loop = newiTempLabel(NULL);
8373
8374                 shiftRight = !shiftRight;       /* invert shift direction */
8375                 
8376                 /* we came here from the code above -- we are done */
8377                 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8378                 
8379                 /* emit code for shifting N<0 steps, count is already in W */
8380                 emitpLabel(inverselbl->key);
8381                 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8382                 emitpLabel(inv_loop->key);
8383                 /* propagate the sign bit inwards for SIGNED result */
8384                 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8385                 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8386                 emitpcode(POC_ADDLW, popGetLit(1));
8387                 emitSKPC;
8388                 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8389         } // if
8390         
8391         emitpLabel(tlbl1->key);
8392         
8393         freeAsmop(left,NULL,ic,TRUE);
8394         freeAsmop (right,NULL,ic,TRUE);
8395         freeAsmop(result,NULL,ic,TRUE);
8396 }
8397
8398 static void genRightShift (iCode *ic)
8399 {
8400         genGenericShift(ic, 1);
8401 }
8402
8403 static void genLeftShift (iCode *ic)
8404 {
8405         genGenericShift(ic, 0);
8406 }
8407
8408 /*-----------------------------------------------------------------*/
8409 /* SetIrp - Set IRP bit                                            */
8410 /*-----------------------------------------------------------------*/
8411 void SetIrp(operand *result) {
8412         FENTRY;
8413         if (AOP_TYPE(result) == AOP_LIT) {
8414                 unsigned lit = (unsigned)operandLitValue(result);
8415                 if (lit&0x100)
8416                         emitSETIRP;
8417                 else
8418                         emitCLRIRP;
8419         } else {
8420                 if (PCOP(AOP(result))->type == PO_LITERAL) {
8421                         int addrs = PCOL(AOP(result))->lit;
8422                         if (addrs & 0x100)
8423                                 emitSETIRP;
8424                         else
8425                                 emitCLRIRP;
8426                 } else {
8427                         emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8428                         if(AOP_SIZE(result) > 1) {
8429                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8430                                 emitSETIRP;
8431                         }
8432                 }
8433         }
8434 }
8435
8436 static void
8437 setup_fsr (operand *ptr)
8438 {
8439   mov2w_op(ptr, 0);
8440   emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8441
8442   /* also setup-up IRP */
8443   SetIrp (ptr);
8444 }
8445
8446 /*-----------------------------------------------------------------*/
8447 /* emitPtrByteGet - emits code to get a byte into WREG from an     */
8448 /*                  arbitrary pointer (__code, __data, generic)    */
8449 /*-----------------------------------------------------------------*/
8450 static void
8451 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8452 {
8453     FENTRY;
8454     switch (p_type)
8455     {
8456     case POINTER:
8457     case FPOINTER:
8458       if (!alreadyAddressed) setup_fsr (src);
8459       emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8460       break;
8461     
8462     case CPOINTER:
8463       assert( AOP_SIZE(src) == 2 );
8464       mov2w_op(src, 0);
8465       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8466       mov2w_op(src, 1);
8467       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8468       emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE));   /* GPOINTER tag for __code space */
8469       call_libraryfunc ("__gptrget1");
8470       break;
8471     
8472     case GPOINTER:
8473       assert( AOP_SIZE(src) == 3 );
8474       mov2w_op(src, 0);
8475       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8476       mov2w_op(src, 1);
8477       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8478       mov2w_op(src, 2);
8479       call_libraryfunc ("__gptrget1");
8480       break;
8481     
8482     default:
8483       assert( !"unhandled pointer type" );
8484       break;
8485     }
8486 }
8487
8488 /*-----------------------------------------------------------------*/
8489 /* emitPtrByteSet - emits code to set a byte from src through a    */
8490 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR).       */
8491 /*-----------------------------------------------------------------*/
8492 static void
8493 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8494 {
8495     FENTRY;
8496     switch (p_type)
8497     {
8498     case POINTER:
8499     case FPOINTER:
8500       if (!alreadyAddressed) setup_fsr (dst);
8501       emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8502       break;
8503     
8504     case CPOINTER:
8505       assert( !"trying to assign to __code pointer" );
8506       break;
8507     
8508     case GPOINTER:
8509       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8510       mov2w_op(dst, 0);
8511       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8512       mov2w_op(dst, 1);
8513       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8514       mov2w_op(dst, 2);
8515       call_libraryfunc ("__gptrput1");
8516       break;
8517
8518     default:
8519       assert( !"unhandled pointer type" );
8520       break;
8521     }
8522 }
8523
8524 /*-----------------------------------------------------------------*/
8525 /* genUnpackBits - generates code for unpacking bits               */
8526 /*-----------------------------------------------------------------*/
8527 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8528 {    
8529   int rsize;            /* result size */
8530   sym_link *etype;      /* bitfield type information */
8531   int blen;             /* bitfield length */
8532   int bstr;             /* bitfield starting bit within byte */
8533
8534   FENTRY;
8535   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8536   etype = getSpec(operandType(result));
8537   rsize = getSize (operandType (result));
8538   blen = SPEC_BLEN (etype);
8539   bstr = SPEC_BSTR (etype);
8540
8541   /* single bit field case */
8542   if (blen == 1) {
8543     if (ifx) { /* that is for an if statement */
8544       pCodeOp *pcop;
8545       resolvedIfx rIfx;
8546       resolveIfx(&rIfx,ifx);
8547       if (ptype == -1) /* direct */
8548         pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8549       else
8550         pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8551       emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8552       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8553       ifx->generated=1;
8554     } else {
8555       int i;
8556       assert (!pic14_sameRegs (AOP(result), AOP(left)));
8557       for (i=0; i < AOP_SIZE(result); i++)
8558         emitpcode (POC_CLRF, popGet (AOP(result), i));
8559
8560       switch (ptype)
8561       {
8562       case -1:
8563         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8564         /* adjust result below */
8565         break;
8566         
8567       case POINTER:
8568       case FPOINTER:
8569       case GPOINTER:
8570       case CPOINTER:
8571         emitPtrByteGet (left, ptype, FALSE);
8572         emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8573         emitSKPZ;
8574         /* adjust result below */
8575         break;
8576         
8577       default:
8578         assert( !"unhandled pointer type" );
8579       } // switch
8580
8581       /* move sign-/zero extended bit to result */
8582       if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8583         emitpcode (POC_INCF, popGet (AOP(result), 0));
8584       } else {
8585         emitpcode (POC_DECF, popGet (AOP(result), 0));
8586       }
8587       addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8588     }
8589     return;
8590   }
8591   else if (blen <= 8 && ((blen + bstr) <= 8))
8592   {
8593     /* blen > 1 */
8594     int i;
8595
8596     for (i=0; i < AOP_SIZE(result); i++)
8597       emitpcode (POC_CLRF, popGet (AOP(result), i));
8598
8599     switch (ptype)
8600     {
8601     case -1:
8602       mov2w(AOP(left), 0);
8603       break;
8604       
8605     case POINTER:
8606     case FPOINTER:
8607     case GPOINTER:
8608     case CPOINTER:
8609       emitPtrByteGet (left, ptype, FALSE);
8610       break;
8611       
8612     default:
8613       assert( !"unhandled pointer type" );
8614     } // switch
8615
8616     if (blen < 8)
8617       emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8618     movwf(AOP(result), 0);
8619     AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8620
8621     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8622     {
8623       /* signed bitfield */
8624       assert (bstr + blen > 0);
8625       emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8626       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8627       emitpcode(POC_IORWF, popGet(AOP(result),0));
8628     }
8629     addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8630     return;
8631   }
8632
8633   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8634 }
8635
8636 #if 1
8637 /*-----------------------------------------------------------------*/
8638 /* genDataPointerGet - generates code when ptr offset is known     */
8639 /*-----------------------------------------------------------------*/
8640 static void genDataPointerGet (operand *left, 
8641         operand *result, 
8642         iCode *ic)
8643 {
8644         int size , offset = 0;
8645                 
8646         FENTRY;
8647         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8648         
8649         
8650         /* optimization - most of the time, left and result are the same
8651         * address, but different types. for the pic code, we could omit
8652         * the following
8653         */
8654         aopOp(result,ic,TRUE);
8655         
8656         if (pic14_sameRegs (AOP(left), AOP(result)))
8657                 return;
8658         
8659         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8660         
8661         //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8662         
8663         size = AOP_SIZE(result);
8664         if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8665         
8666         offset = 0;
8667         while (size--) {
8668                 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8669                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8670                 offset++;
8671         }
8672         
8673         freeAsmop(left,NULL,ic,TRUE);
8674         freeAsmop(result,NULL,ic,TRUE);
8675 }
8676 #endif
8677
8678 /*-----------------------------------------------------------------*/
8679 /* genNearPointerGet - pic14_emitcode for near pointer fetch       */
8680 /*-----------------------------------------------------------------*/
8681 static void genNearPointerGet (operand *left, 
8682                                                            operand *result, 
8683                                                            iCode *ic)
8684 {
8685         asmop *aop = NULL;
8686         sym_link *ltype = operandType(left);
8687         sym_link *rtype = operandType(result);
8688         sym_link *retype= getSpec(rtype);      /* bitfield type information */
8689         int direct = 0;
8690
8691         FENTRY;
8692         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8693         
8694         
8695         aopOp(left,ic,FALSE);
8696         
8697         /* if left is rematerialisable and
8698         result is not bit variable type and
8699         the left is pointer to data space i.e
8700         lower 128 bytes of space */
8701         if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8702                 !IS_BITVAR(retype)         &&
8703                 PIC_IS_DATA_PTR(ltype)) {
8704                 genDataPointerGet (left,result,ic);
8705                 return ;
8706         }
8707         
8708         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8709         aopOp (result,ic,FALSE);
8710         
8711         /* Check if can access directly instead of via a pointer */
8712         if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8713                 && AOP_SIZE(result) == 1)
8714         {
8715                 direct = 1;
8716         }
8717
8718         if (IS_BITFIELD(getSpec(operandType(result)))) 
8719         {
8720                 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8721                 goto release;
8722         }
8723         
8724         /* If the pointer value is not in a the FSR then need to put it in */
8725         /* Must set/reset IRP bit for use with FSR. */
8726         if (!direct)
8727           setup_fsr (left);
8728         
8729 //      sym_link *etype;
8730         /* if bitfield then unpack the bits */
8731         {
8732                 /* we have can just get the values */
8733                 int size = AOP_SIZE(result);
8734                 int offset = 0 ;  
8735                 
8736                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8737                 
8738                 while(size--) {
8739                         if (direct)
8740                                 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8741                         else
8742                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8743                         if (AOP_TYPE(result) == AOP_LIT) {
8744                                 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8745                         } else {
8746                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8747                         }
8748                         if (size && !direct)
8749                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8750                         offset++;
8751                 }
8752         }
8753         
8754         /* now some housekeeping stuff */
8755         if (aop) {
8756                 /* we had to allocate for this iCode */
8757                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8758                 freeAsmop(NULL,aop,ic,TRUE);
8759         } else { 
8760                 /* we did not allocate which means left
8761                 already in a pointer register, then
8762                 if size > 0 && this could be used again
8763                 we have to point it back to where it 
8764                 belongs */
8765                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8766                 if (AOP_SIZE(result) > 1 &&
8767                         !OP_SYMBOL(left)->remat &&
8768                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8769                         ic->depth )) {
8770                         int size = AOP_SIZE(result) - 1;
8771                         while (size--)
8772                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8773                 }
8774         }
8775         
8776 release:
8777         /* done */
8778         freeAsmop(left,NULL,ic,TRUE);
8779         freeAsmop(result,NULL,ic,TRUE);
8780
8781 }
8782
8783 #if 0
8784 /*-----------------------------------------------------------------*/
8785 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8786 /*-----------------------------------------------------------------*/
8787 static void genPagedPointerGet (operand *left, 
8788                                                                 operand *result, 
8789                                                                 iCode *ic)
8790 {
8791         asmop *aop = NULL;
8792         regs *preg = NULL ;
8793         char *rname ;
8794         sym_link *rtype, *retype;    
8795         
8796         FENTRY;
8797         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8798         
8799         rtype = operandType(result);
8800         retype= getSpec(rtype);
8801         
8802         aopOp(left,ic,FALSE);
8803         
8804         /* if the value is already in a pointer register
8805         then don't need anything more */
8806         if (!AOP_INPREG(AOP(left))) {
8807                 /* otherwise get a free pointer register */
8808                 aop = newAsmop(0);
8809                 preg = getFreePtr(ic,&aop,FALSE);
8810                 pic14_emitcode("mov","%s,%s",
8811                         preg->name,
8812                         aopGet(AOP(left),0,FALSE,TRUE));
8813                 rname = preg->name ;
8814         } else
8815                 rname = aopGet(AOP(left),0,FALSE,FALSE);
8816         
8817         freeAsmop(left,NULL,ic,TRUE);
8818         aopOp (result,ic,FALSE);
8819         
8820         /* if bitfield then unpack the bits */
8821         if (IS_BITFIELD(retype)) 
8822                 genUnpackBits (result,left,rname,PPOINTER,0);
8823         else {
8824                 /* we have can just get the values */
8825                 int size = AOP_SIZE(result);
8826                 int offset = 0 ;  
8827                 
8828                 while (size--) {
8829                         
8830                         pic14_emitcode("movx","a,@%s",rname);
8831                         aopPut(AOP(result),"a",offset);
8832                         
8833                         offset++ ;
8834                         
8835                         if (size)
8836                                 pic14_emitcode("inc","%s",rname);
8837                 }
8838         }
8839         
8840         /* now some housekeeping stuff */
8841         if (aop) {
8842                 /* we had to allocate for this iCode */
8843                 freeAsmop(NULL,aop,ic,TRUE);
8844         } else { 
8845         /* we did not allocate which means left
8846         already in a pointer register, then
8847         if size > 0 && this could be used again
8848         we have to point it back to where it 
8849                 belongs */
8850                 if (AOP_SIZE(result) > 1 &&
8851                         !OP_SYMBOL(left)->remat &&
8852                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8853                         ic->depth )) {
8854                         int size = AOP_SIZE(result) - 1;
8855                         while (size--)
8856                                 pic14_emitcode("dec","%s",rname);
8857                 }
8858         }
8859         
8860         /* done */
8861         freeAsmop(result,NULL,ic,TRUE);
8862         
8863         
8864 }
8865
8866 /*-----------------------------------------------------------------*/
8867 /* genFarPointerGet - gget value from far space                    */
8868 /*-----------------------------------------------------------------*/
8869 static void genFarPointerGet (operand *left,
8870                                                           operand *result, iCode *ic)
8871 {
8872         int size, offset ;
8873         sym_link *retype = getSpec(operandType(result));
8874         
8875         FENTRY;
8876         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8877         
8878         aopOp(left,ic,FALSE);
8879         
8880         /* if the operand is already in dptr 
8881         then we do nothing else we move the value to dptr */
8882         if (AOP_TYPE(left) != AOP_STR) {
8883                 /* if this is remateriazable */
8884                 if (AOP_TYPE(left) == AOP_IMMD)
8885                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8886                 else { /* we need to get it byte by byte */
8887                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8888                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8889                         if (options.model == MODEL_FLAT24)
8890                         {
8891                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8892                         }
8893                 }
8894         }
8895         /* so dptr know contains the address */
8896         freeAsmop(left,NULL,ic,TRUE);
8897         aopOp(result,ic,FALSE);
8898         
8899         /* if bit then unpack */
8900         if (IS_BITFIELD(retype)) 
8901                 genUnpackBits(result,left,"dptr",FPOINTER,0);
8902         else {
8903                 size = AOP_SIZE(result);
8904                 offset = 0 ;
8905                 
8906                 while (size--) {
8907                         pic14_emitcode("movx","a,@dptr");
8908                         aopPut(AOP(result),"a",offset++);
8909                         if (size)
8910                                 pic14_emitcode("inc","dptr");
8911                 }
8912         }
8913         
8914         freeAsmop(result,NULL,ic,TRUE);
8915 }
8916 #endif
8917
8918 #if 0
8919 /*-----------------------------------------------------------------*/
8920 /* genCodePointerGet - get value from code space                  */
8921 /*-----------------------------------------------------------------*/
8922 static void genCodePointerGet (operand *left,
8923                                                            operand *result, iCode *ic)
8924 {
8925         int size, offset ;
8926         sym_link *retype = getSpec(operandType(result));
8927         
8928         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8929         
8930         aopOp(left,ic,FALSE);
8931         
8932         /* if the operand is already in dptr 
8933         then we do nothing else we move the value to dptr */
8934         if (AOP_TYPE(left) != AOP_STR) {
8935                 /* if this is remateriazable */
8936                 if (AOP_TYPE(left) == AOP_IMMD)
8937                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8938                 else { /* we need to get it byte by byte */
8939                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8940                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8941                         if (options.model == MODEL_FLAT24)
8942                         {
8943                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8944                         }
8945                 }
8946         }
8947         /* so dptr know contains the address */
8948         freeAsmop(left,NULL,ic,TRUE);
8949         aopOp(result,ic,FALSE);
8950         
8951         /* if bit then unpack */
8952         if (IS_BITFIELD(retype)) 
8953                 genUnpackBits(result,left,"dptr",CPOINTER,0);
8954         else {
8955                 size = AOP_SIZE(result);
8956                 offset = 0 ;
8957                 
8958                 while (size--) {
8959                         pic14_emitcode("clr","a");
8960                         pic14_emitcode("movc","a,@a+dptr");
8961                         aopPut(AOP(result),"a",offset++);
8962                         if (size)
8963                                 pic14_emitcode("inc","dptr");
8964                 }
8965         }
8966         
8967         freeAsmop(result,NULL,ic,TRUE);
8968 }
8969 #endif
8970 /*-----------------------------------------------------------------*/
8971 /* genGenPointerGet - gget value from generic pointer space        */
8972 /*-----------------------------------------------------------------*/
8973 static void genGenPointerGet (operand *left,
8974                                                           operand *result, iCode *ic)
8975 {
8976         FENTRY;
8977         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8978         aopOp(left,ic,FALSE);
8979         aopOp(result,ic,FALSE);
8980         
8981         
8982         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8983
8984         if (IS_BITFIELD(getSpec(operandType(result))))
8985         {
8986           genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
8987           return;
8988         }
8989
8990         {
8991           /* emit call to __gptrget */
8992           char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
8993           int size = AOP_SIZE(result);
8994           int idx = 0;
8995
8996           assert (size > 0 && size <= 4);
8997
8998           /* pass arguments */
8999           assert (AOP_SIZE(left) == 3);
9000           mov2w(AOP(left), 0);
9001           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9002           mov2w(AOP(left), 1);
9003           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9004           mov2w(AOP(left), 2);
9005           call_libraryfunc (func[size]);
9006           
9007           /* save result */
9008           movwf (AOP(result), --size);
9009           while (size--) {
9010             emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
9011             movwf (AOP(result), size);
9012           } // while
9013         }
9014         
9015         freeAsmop(left,NULL,ic,TRUE);
9016         freeAsmop(result,NULL,ic,TRUE);
9017         
9018 }
9019
9020 /*-----------------------------------------------------------------*/
9021 /* genConstPointerGet - get value from const generic pointer space */
9022 /*-----------------------------------------------------------------*/
9023 static void genConstPointerGet (operand *left,
9024                                                                 operand *result, iCode *ic)
9025 {
9026         //sym_link *retype = getSpec(operandType(result));
9027         #if 0
9028         symbol *albl, *blbl;//, *clbl;
9029         pCodeOp *pcop;
9030         #endif
9031         PIC_OPCODE poc;
9032         int i, size, lit;
9033         
9034         FENTRY;
9035         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9036         aopOp(left,ic,FALSE);
9037         aopOp(result,ic,FALSE);
9038         
9039         size = AOP_SIZE(result);
9040         
9041         DEBUGpic14_AopType(__LINE__,left,NULL,result);
9042         
9043         DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9044
9045         lit = op_isLitLike (left);
9046         poc = lit ? POC_MOVLW : POC_MOVFW;
9047
9048         if (IS_BITFIELD(getSpec(operandType(result))))
9049         {
9050                 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9051                 goto release;
9052         }
9053
9054         {
9055                 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9056                 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9057                 assert (size > 0 && size <= 4);
9058                 
9059                 mov2w_op(left, 0);
9060                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9061                 mov2w_op(left, 1);
9062                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9063                 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9064                 call_libraryfunc (func[size]);
9065
9066                 movwf(AOP(result),size-1);
9067                 for (i = 1; i < size; i++)
9068                 {
9069                         emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9070                         movwf(AOP(result),size - 1 - i);
9071                 } // for
9072         }
9073         
9074 release:
9075         freeAsmop(left,NULL,ic,TRUE);
9076         freeAsmop(result,NULL,ic,TRUE);
9077         
9078 }
9079 /*-----------------------------------------------------------------*/
9080 /* genPointerGet - generate code for pointer get                   */
9081 /*-----------------------------------------------------------------*/
9082 static void genPointerGet (iCode *ic)
9083 {
9084         operand *left, *result ;
9085         sym_link *type, *etype;
9086         int p_type = -1;
9087         
9088         FENTRY;
9089         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9090         
9091         left = IC_LEFT(ic);
9092         result = IC_RESULT(ic) ;
9093         
9094         /* depending on the type of pointer we need to
9095         move it to the correct pointer register */
9096         type = operandType(left);
9097         etype = getSpec(type);
9098         
9099         if (IS_PTR_CONST(type))
9100                 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9101         
9102         /* if left is of type of pointer then it is simple */
9103         if (IS_PTR(type) && !IS_FUNC(type->next)) 
9104                 p_type = DCL_TYPE(type);
9105         else {
9106                 /* we have to go by the storage class */
9107                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9108                 
9109                 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9110                 
9111                 if (SPEC_OCLS(etype)->codesp ) {
9112                         DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9113                         //p_type = CPOINTER ; 
9114                 }
9115                 else
9116                         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9117                                 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9118                         /*p_type = FPOINTER ;*/ 
9119                         else
9120                                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9121                                         DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9122                                 /*        p_type = PPOINTER; */
9123                                 else
9124                                         if (SPEC_OCLS(etype) == idata )
9125                                                 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9126                                         /*      p_type = IPOINTER; */
9127                                         else
9128                                                 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9129                                         /*      p_type = POINTER ; */
9130         }
9131         
9132         /* now that we have the pointer type we assign
9133         the pointer values */
9134         switch (p_type) {
9135                 
9136         case POINTER: 
9137         case FPOINTER:
9138         //case IPOINTER:
9139                 genNearPointerGet (left,result,ic);
9140                 break;
9141 /*
9142         case PPOINTER:
9143                 genPagedPointerGet(left,result,ic);
9144                 break;
9145                 
9146         case FPOINTER:
9147                 genFarPointerGet (left,result,ic);
9148                 break;
9149 */              
9150         case CPOINTER:
9151                 genConstPointerGet (left,result,ic);
9152                 break;
9153                 
9154         case GPOINTER:
9155                 genGenPointerGet (left,result,ic);
9156                 break;
9157         default:
9158                 assert ( !"unhandled pointer type" );
9159                 break;
9160         }
9161         
9162 }
9163
9164 /*-----------------------------------------------------------------*/
9165 /* genPackBits - generates code for packed bit storage             */
9166 /*-----------------------------------------------------------------*/
9167 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9168 {
9169   int blen;             /* bitfield length */
9170   int bstr;             /* bitfield starting bit within byte */
9171   int litval;           /* source literal value (if AOP_LIT) */
9172   unsigned char mask;   /* bitmask within current byte */
9173
9174   FENTRY;
9175   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9176
9177   blen = SPEC_BLEN (etype);
9178   bstr = SPEC_BSTR (etype);
9179
9180   /* If the bitfield length is less than a byte and does not cross byte boundaries */
9181   if ((blen <= 8) && ((bstr + blen) <= 8))
9182   {
9183     mask = ((unsigned char) (0xFF << (blen + bstr)) |
9184             (unsigned char) (0xFF >> (8 - bstr)));
9185
9186     if (AOP_TYPE (right) == AOP_LIT)
9187     {
9188       /* Case with a bitfield length <8 and literal source */
9189       int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9190       if (blen == 1) {
9191         pCodeOp *pcop;
9192         
9193         switch (p_type)
9194         {
9195         case -1:
9196           if (AOP(result)->type == AOP_PCODE)
9197             pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9198           else
9199             pcop = popGet(AOP(result),0);
9200           emitpcode(lit?POC_BSF:POC_BCF,pcop);
9201           break;
9202         
9203         case POINTER:
9204         case FPOINTER:
9205           setup_fsr (result);
9206           emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9207           break;
9208         
9209         case CPOINTER:
9210           assert( !"trying to assign to bitfield via pointer to __code space" );
9211           break;
9212         
9213         case GPOINTER:
9214           emitPtrByteGet(result, p_type, FALSE);
9215           if (lit) {
9216             emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9217           } else {
9218             emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9219           }
9220           emitPtrByteSet(result, p_type, TRUE);
9221           break;
9222         
9223         default:
9224           assert( !"unhandled pointer type" );
9225           break;
9226         } // switch (p_type)
9227       } else {
9228         /* blen > 1 */
9229         litval = lit << bstr;
9230         litval &= (~mask) & 0x00ff;
9231         
9232         switch (p_type)
9233         {
9234         case -1:
9235           mov2w (AOP(result), 0);
9236           if ((litval|mask) != 0x00ff)
9237             emitpcode(POC_ANDLW, popGetLit (mask));
9238           if (litval != 0x00)
9239             emitpcode(POC_IORLW, popGetLit (litval));
9240           movwf (AOP(result), 0);
9241           break;
9242         
9243         case POINTER:
9244         case FPOINTER:
9245         case GPOINTER:
9246           emitPtrByteGet(result, p_type, FALSE);
9247           if ((litval|mask) != 0x00ff)
9248             emitpcode(POC_ANDLW, popGetLit (mask));
9249           if (litval != 0x00)
9250             emitpcode(POC_IORLW, popGetLit (litval));
9251           emitPtrByteSet(result, p_type, TRUE);
9252           break;
9253         
9254         case CPOINTER:
9255           assert( !"trying to assign to bitfield via pointer to __code space" );
9256           break;
9257         
9258         default:
9259           assert( !"unhandled pointer type" );
9260           break;
9261         } // switch
9262       } // if (blen > 1)
9263     }
9264     else
9265     {
9266       /* right is no literal */
9267       if (blen==1) {
9268         switch (p_type)
9269         {
9270         case -1:
9271           /* Note more efficient code, of pre clearing bit then only setting it if required,
9272            * can only be done if it is known that the result is not a SFR */
9273           emitpcode(POC_RRFW,popGet(AOP(right),0));
9274           emitSKPC;
9275           emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9276           emitSKPNC;
9277           emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9278           break;
9279         
9280         case POINTER:
9281         case FPOINTER:
9282         case GPOINTER:
9283           emitPtrByteGet (result, p_type, FALSE);
9284           emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9285           emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9286           emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9287           emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9288           emitPtrByteSet (result, p_type, TRUE);
9289           break;
9290         
9291         case CPOINTER:
9292           assert( !"trying to assign to bitfield via pointer to __code space" );
9293           break;
9294         
9295         default:
9296           assert( !"unhandled pointer type" );
9297           break;
9298         } // switch
9299         return;
9300       } else {
9301         /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9302         pCodeOp *temp = popGetTempReg ();
9303
9304         mov2w (AOP(right), 0);
9305         if (blen < 8) {
9306           emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9307         }
9308         emitpcode(POC_MOVWF, temp);
9309         if (bstr) {
9310           AccLsh (temp, bstr);
9311         }
9312         
9313         switch (p_type)
9314         {
9315         case -1:
9316           mov2w (AOP(result), 0);
9317           emitpcode(POC_ANDLW, popGetLit (mask));
9318           emitpcode(POC_IORFW, temp);
9319           movwf (AOP(result), 0);
9320           break;
9321         
9322         case POINTER:
9323         case FPOINTER:
9324         case GPOINTER:
9325           emitPtrByteGet (result, p_type, FALSE);
9326           emitpcode(POC_ANDLW, popGetLit (mask));
9327           emitpcode(POC_IORFW, temp);
9328           emitPtrByteSet (result, p_type, TRUE);
9329           break;
9330         
9331         case CPOINTER:
9332           assert( !"trying to assign to bitfield via pointer to __code space" );
9333           break;
9334         
9335         default:
9336           assert( !"unhandled pointer type" );
9337           break;
9338         } // switch
9339
9340         popReleaseTempReg (temp);
9341       } // if (blen > 1)
9342     } // if (AOP(right)->type != AOP_LIT)
9343     return;
9344   } // if (blen <= 8 && ((blen + bstr) <= 8))
9345
9346   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9347 }
9348
9349 unsigned long
9350 bitpatternFromVal (value *val)
9351 {
9352   union {
9353     float d;
9354     unsigned long l;
9355   } float_long;
9356
9357   assert (sizeof (float) == sizeof (long));
9358
9359   //fprintf (stderr, "%s:%u(%s): val=%lf, type: %d, etype: %d\n", __FILE__, __LINE__, __FUNCTION__, floatFromVal(val), SPEC_NOUN(val->type), SPEC_NOUN(val->etype));
9360
9361   switch (SPEC_NOUN(val->type))
9362   {
9363   case V_INT:
9364   case V_CHAR:
9365     return (unsigned long)floatFromVal (val);
9366     
9367   case V_FLOAT:
9368   case V_DOUBLE:
9369     float_long.d = floatFromVal (val);
9370     return float_long.l;
9371     
9372   default:
9373     assert( !"unhandled value type" );
9374     break;
9375   }
9376
9377   float_long.d = floatFromVal (val);
9378   return float_long.l;
9379 }
9380
9381 /*-----------------------------------------------------------------*/
9382 /* genDataPointerSet - remat pointer to data space                 */
9383 /*-----------------------------------------------------------------*/
9384 static void genDataPointerSet(operand *right,
9385         operand *result,
9386         iCode *ic)
9387 {
9388         int size, offset = 0 ;
9389         int ressize;
9390         
9391         FENTRY;
9392         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9393         aopOp(right,ic,FALSE);
9394         aopOp(result,ic,FALSE);
9395         
9396         assert (IS_SYMOP(result));
9397         assert (IS_PTR(OP_SYM_TYPE(result)));
9398         
9399         size = AOP_SIZE(right);
9400         ressize = getSize(OP_SYM_ETYPE(result));
9401         if (size > ressize) size = ressize;
9402         //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9403         
9404         //assert( !"what's going on here?" );
9405
9406         /*
9407         if ( AOP_TYPE(result) == AOP_PCODE) {
9408         fprintf(stderr,"genDataPointerSet   %s, %d\n",
9409         AOP(result)->aopu.pcop->name,
9410         PCOI(AOP(result)->aopu.pcop)->offset);
9411         }
9412         */
9413         
9414         // tsd, was l+1 - the underline `_' prefix was being stripped
9415         while (size--) {
9416                 emitpComment ("%s:%u: size=%d/%d, offset=%i", __FILE__,__LINE__, size, ressize, offset);
9417                 
9418                 if (AOP_TYPE(right) == AOP_LIT) {
9419                         /* XXX: might be float... */
9420                         unsigned int lit = bitpatternFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9421                         lit = lit >> (8*offset);
9422                         //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9423                         if(lit&0xff) {
9424                                 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9425                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9426                         } else {
9427                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9428                         }
9429                 } else {
9430                         //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9431                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9432                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9433                 }
9434                 
9435                 offset++;
9436         }
9437         
9438         freeAsmop(right,NULL,ic,TRUE);
9439         freeAsmop(result,NULL,ic,TRUE);
9440 }
9441
9442 /*-----------------------------------------------------------------*/
9443 /* genNearPointerSet - pic14_emitcode for near pointer put         */
9444 /*-----------------------------------------------------------------*/
9445 static void genNearPointerSet (operand *right,
9446                                                            operand *result, 
9447                                                            iCode *ic)
9448 {
9449         asmop *aop = NULL;
9450         sym_link *ptype = operandType(result);
9451         sym_link *retype = getSpec(operandType(right));
9452         sym_link *letype = getSpec(ptype);
9453         int direct = 0;
9454         
9455         
9456         FENTRY;
9457         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9458         aopOp(result,ic,FALSE);
9459         
9460 #if 1
9461         /* if the result is rematerializable &
9462         in data space & not a bit variable */
9463         //if (AOP_TYPE(result) == AOP_IMMD &&
9464         if (AOP_TYPE(result) == AOP_PCODE &&
9465                 PIC_IS_DATA_PTR(ptype) &&
9466                 !IS_BITVAR (retype) &&
9467                 !IS_BITVAR (letype)) {
9468                 genDataPointerSet (right,result,ic);
9469                 freeAsmop(result,NULL,ic,TRUE);
9470                 return;
9471         }
9472 #endif
9473
9474         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9475         aopOp(right,ic,FALSE);
9476         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9477         
9478         /* Check if can access directly instead of via a pointer */
9479         if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9480                 direct = 1;
9481         }
9482         
9483         if (IS_BITFIELD (letype))
9484         {
9485           genPackBits (letype, result, right, direct?-1:POINTER);
9486           return;
9487         }
9488         
9489         /* If the pointer value is not in a the FSR then need to put it in */
9490         /* Must set/reset IRP bit for use with FSR. */
9491         /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9492         if (!direct)
9493                 setup_fsr (result);
9494
9495         {
9496                 /* we have can just get the values */
9497                 int size = AOP_SIZE(right);
9498                 int offset = 0 ;    
9499                 
9500                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9501                 while (size--) {
9502                         char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9503                         if (*l == '@' ) {
9504                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9505                         } else {
9506                                 if (AOP_TYPE(right) == AOP_LIT) {
9507                                         emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9508                                 } else {
9509                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9510                                 }
9511                                 if (direct)
9512                                         emitpcode(POC_MOVWF,popGet(AOP(result),0));
9513                                 else
9514                                         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9515                         }
9516                         if (size && !direct)
9517                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9518                         offset++;
9519                 }
9520         }
9521         
9522         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9523         /* now some housekeeping stuff */
9524         if (aop) {
9525                 /* we had to allocate for this iCode */
9526                 freeAsmop(NULL,aop,ic,TRUE);
9527         } else { 
9528                 /* we did not allocate which means left
9529                 already in a pointer register, then
9530                 if size > 0 && this could be used again
9531                 we have to point it back to where it 
9532                 belongs */
9533                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9534                 if (AOP_SIZE(right) > 1 &&
9535                         !OP_SYMBOL(result)->remat &&
9536                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9537                         ic->depth )) {
9538                         int size = AOP_SIZE(right) - 1;
9539                         while (size--)
9540                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9541                 }
9542         }
9543         
9544         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9545         /* done */
9546
9547         freeAsmop(right,NULL,ic,TRUE);
9548         freeAsmop(result,NULL,ic,TRUE);
9549 }
9550
9551 #if 0
9552 /*-----------------------------------------------------------------*/
9553 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
9554 /*-----------------------------------------------------------------*/
9555 static void genPagedPointerSet (operand *right,
9556                                                                 operand *result, 
9557                                                                 iCode *ic)
9558 {
9559         asmop *aop = NULL;
9560         regs *preg = NULL ;
9561         char *rname , *l;
9562         sym_link *retype;
9563         
9564         FENTRY;
9565         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9566         
9567         retype= getSpec(operandType(right));
9568         
9569         aopOp(result,ic,FALSE);
9570         
9571         /* if the value is already in a pointer register
9572         then don't need anything more */
9573         if (!AOP_INPREG(AOP(result))) {
9574                 /* otherwise get a free pointer register */
9575                 aop = newAsmop(0);
9576                 preg = getFreePtr(ic,&aop,FALSE);
9577                 pic14_emitcode("mov","%s,%s",
9578                         preg->name,
9579                         aopGet(AOP(result),0,FALSE,TRUE));
9580                 rname = preg->name ;
9581         } else
9582                 rname = aopGet(AOP(result),0,FALSE,FALSE);
9583         
9584         freeAsmop(result,NULL,ic,TRUE);
9585         aopOp (right,ic,FALSE);
9586         
9587         /* if bitfield then unpack the bits */
9588         if (IS_BITFIELD(retype)) 
9589                 genPackBits (retype,result,right,rname,PPOINTER);
9590         else {
9591                 /* we have can just get the values */
9592                 int size = AOP_SIZE(right);
9593                 int offset = 0 ;  
9594                 
9595                 while (size--) {
9596                         l = aopGet(AOP(right),offset,FALSE,TRUE);
9597                         
9598                         MOVA(l);
9599                         pic14_emitcode("movx","@%s,a",rname);
9600                         
9601                         if (size)
9602                                 pic14_emitcode("inc","%s",rname);
9603                         
9604                         offset++;
9605                 }
9606         }
9607         
9608         /* now some housekeeping stuff */
9609         if (aop) {
9610                 /* we had to allocate for this iCode */
9611                 freeAsmop(NULL,aop,ic,TRUE);
9612         } else { 
9613         /* we did not allocate which means left
9614         already in a pointer register, then
9615         if size > 0 && this could be used again
9616         we have to point it back to where it 
9617                 belongs */
9618                 if (AOP_SIZE(right) > 1 &&
9619                         !OP_SYMBOL(result)->remat &&
9620                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9621                         ic->depth )) {
9622                         int size = AOP_SIZE(right) - 1;
9623                         while (size--)
9624                                 pic14_emitcode("dec","%s",rname);
9625                 }
9626         }
9627         
9628         /* done */
9629         freeAsmop(right,NULL,ic,TRUE);
9630         
9631         
9632 }
9633
9634 /*-----------------------------------------------------------------*/
9635 /* genFarPointerSet - set value from far space                     */
9636 /*-----------------------------------------------------------------*/
9637 static void genFarPointerSet (operand *right,
9638                                                           operand *result, iCode *ic)
9639 {
9640         int size, offset ;
9641         sym_link *retype = getSpec(operandType(right));
9642         
9643         FENTRY;
9644         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9645         aopOp(result,ic,FALSE);
9646         
9647         /* if the operand is already in dptr 
9648         then we do nothing else we move the value to dptr */
9649         if (AOP_TYPE(result) != AOP_STR) {
9650                 /* if this is remateriazable */
9651                 if (AOP_TYPE(result) == AOP_IMMD)
9652                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9653                 else { /* we need to get it byte by byte */
9654                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9655                         pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9656                         if (options.model == MODEL_FLAT24)
9657                         {
9658                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9659                         }
9660                 }
9661         }
9662         /* so dptr know contains the address */
9663         freeAsmop(result,NULL,ic,TRUE);
9664         aopOp(right,ic,FALSE);
9665         
9666         /* if bit then unpack */
9667         if (IS_BITFIELD(retype)) 
9668                 genPackBits(retype,result,right,"dptr",FPOINTER);
9669         else {
9670                 size = AOP_SIZE(right);
9671                 offset = 0 ;
9672                 
9673                 while (size--) {
9674                         char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9675                         MOVA(l);
9676                         pic14_emitcode("movx","@dptr,a");
9677                         if (size)
9678                                 pic14_emitcode("inc","dptr");
9679                 }
9680         }
9681         
9682         freeAsmop(right,NULL,ic,TRUE);
9683 }
9684 #endif
9685
9686 /*-----------------------------------------------------------------*/
9687 /* genGenPointerSet - set value from generic pointer space         */
9688 /*-----------------------------------------------------------------*/
9689 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9690 {
9691         sym_link *retype = getSpec(operandType(result));
9692         
9693         FENTRY;
9694         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9695         aopOp(right,ic,FALSE);
9696         aopOp(result,ic,FALSE);
9697
9698         
9699         DEBUGpic14_AopType(__LINE__,right,NULL,result);
9700
9701         if (IS_BITFIELD(retype))
9702         {
9703           genPackBits (retype, result, right, GPOINTER);
9704           return;
9705         }
9706
9707         {
9708           /* emit call to __gptrput */
9709           char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9710           int size = AOP_SIZE(right);
9711           int idx = 0;
9712
9713           assert (size == getSize(OP_SYM_ETYPE(result)));
9714           assert (size > 0 && size <= 4);
9715
9716           /* pass arguments */
9717           /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9718           {
9719             int off = size;
9720             idx = 2;
9721             while (off--)
9722             {
9723               mov2w_op (right, off);
9724               emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9725             }
9726             idx = 0;
9727           }
9728           /* - address */
9729           assert (AOP_SIZE(result) == 3);
9730           mov2w(AOP(result), 0);
9731           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9732           mov2w(AOP(result), 1);
9733           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9734           mov2w(AOP(result), 2);
9735           call_libraryfunc (func[size]);
9736         }
9737         
9738         freeAsmop(right,NULL,ic,TRUE);
9739         freeAsmop(result,NULL,ic,TRUE);
9740 }
9741
9742 /*-----------------------------------------------------------------*/
9743 /* genPointerSet - stores the value into a pointer location        */
9744 /*-----------------------------------------------------------------*/
9745 static void genPointerSet (iCode *ic)
9746 {    
9747         operand *right, *result ;
9748         sym_link *type, *etype;
9749         int p_type;
9750         
9751         FENTRY;
9752         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9753         
9754         right = IC_RIGHT(ic);
9755         result = IC_RESULT(ic) ;
9756         
9757         /* depending on the type of pointer we need to
9758         move it to the correct pointer register */
9759         type = operandType(result);
9760         etype = getSpec(type);
9761         /* if left is of type of pointer then it is simple */
9762         if (IS_PTR(type) && !IS_FUNC(type->next)) {
9763                 p_type = DCL_TYPE(type);
9764         }
9765         else {
9766                 /* we have to go by the storage class */
9767                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9768                 
9769                 /*  if (SPEC_OCLS(etype)->codesp ) { */
9770                 /*      p_type = CPOINTER ;  */
9771                 /*  } */
9772                 /*  else */
9773                 /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9774                 /*    p_type = FPOINTER ; */
9775                 /*      else */
9776                 /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9777                 /*        p_type = PPOINTER ; */
9778                 /*    else */
9779                 /*        if (SPEC_OCLS(etype) == idata ) */
9780                 /*      p_type = IPOINTER ; */
9781                 /*        else */
9782                 /*      p_type = POINTER ; */
9783         }
9784         
9785         /* now that we have the pointer type we assign
9786         the pointer values */
9787         switch (p_type) {
9788                 
9789         case POINTER:
9790         case FPOINTER:
9791         //case IPOINTER:
9792                 genNearPointerSet (right,result,ic);
9793                 break;
9794 /*
9795         case PPOINTER:
9796                 genPagedPointerSet (right,result,ic);
9797                 break;
9798                 
9799         case FPOINTER:
9800                 genFarPointerSet (right,result,ic);
9801                 break;
9802 */
9803         case GPOINTER:
9804                 genGenPointerSet (right,result,ic);
9805                 break;
9806                 
9807         default:
9808                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9809                         "genPointerSet: illegal pointer type");
9810         }
9811 }
9812
9813 /*-----------------------------------------------------------------*/
9814 /* genIfx - generate code for Ifx statement                        */
9815 /*-----------------------------------------------------------------*/
9816 static void genIfx (iCode *ic, iCode *popIc)
9817 {
9818         operand *cond = IC_COND(ic);
9819         int isbit =0;
9820         
9821         FENTRY;
9822         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9823         
9824         aopOp(cond,ic,FALSE);
9825         
9826         /* get the value into acc */
9827         if (AOP_TYPE(cond) != AOP_CRY)
9828                 pic14_toBoolean(cond);
9829         else
9830                 isbit = 1;
9831         /* the result is now in the accumulator */
9832         freeAsmop(cond,NULL,ic,TRUE);
9833         
9834         /* if there was something to be popped then do it */
9835         if (popIc)
9836                 genIpop(popIc);
9837         
9838         if (isbit)
9839         {
9840                 assert (!"genIfx not implemented for bit variables...");
9841         }
9842         else
9843         {
9844                 /* now Z if set iff !cond */
9845                 if (IC_TRUE(ic))
9846                 {
9847                         assert (!IC_FALSE(ic));
9848                         emitSKPZ;
9849                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9850                 } else {
9851                         emitSKPNZ;
9852                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9853                 }
9854         }
9855         
9856         ic->generated = 1;
9857         
9858 }
9859
9860 /*-----------------------------------------------------------------*/
9861 /* genAddrOf - generates code for address of                       */
9862 /*-----------------------------------------------------------------*/
9863 static void genAddrOf (iCode *ic)
9864 {
9865         operand *right, *result, *left;
9866         int size, offset ;
9867         
9868         FENTRY;
9869         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9870         
9871         
9872         //aopOp(IC_RESULT(ic),ic,FALSE);
9873         
9874         aopOp((left=IC_LEFT(ic)),ic,FALSE);
9875         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9876         aopOp((result=IC_RESULT(ic)),ic,TRUE);
9877         
9878         DEBUGpic14_AopType(__LINE__,left,right,result);
9879         assert (IS_SYMOP (left));
9880         
9881         /* sanity check: generic pointers to code space are not yet supported,
9882          * pionters to codespace must not be assigned addresses of __data values. */
9883  #if 0
9884         fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9885         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)));
9886         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)));
9887         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)));
9888         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)));
9889 #endif
9890
9891         if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9892           fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9893                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9894                 OP_SYMBOL(left)->name);
9895         } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9896           fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9897                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9898                 OP_SYMBOL(left)->name);
9899         }
9900         
9901         size = AOP_SIZE(IC_RESULT(ic));
9902         if (IS_GENPTR(OP_SYM_TYPE(result))) {
9903                 /* strip tag */
9904                 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9905         }
9906         offset = 0;
9907         
9908         while (size--) {
9909                 /* fixing bug #863624, reported from (errolv) */
9910                 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9911                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9912                 
9913 #if 0
9914                 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9915                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9916 #endif
9917                 offset++;
9918         }
9919
9920         if (IS_GENPTR(OP_SYM_TYPE(result)))
9921         {
9922                 /* provide correct tag */
9923                 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9924                 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9925                 movwf (AOP(result), 2);
9926         }
9927         
9928         freeAsmop(left,NULL,ic,FALSE);
9929         freeAsmop(result,NULL,ic,TRUE);
9930         
9931 }
9932
9933 #if 0
9934 /*-----------------------------------------------------------------*/
9935 /* genFarFarAssign - assignment when both are in far space         */
9936 /*-----------------------------------------------------------------*/
9937 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9938 {
9939         int size = AOP_SIZE(right);
9940         int offset = 0;
9941         char *l ;
9942         /* first push the right side on to the stack */
9943         while (size--) {
9944                 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9945                 MOVA(l);
9946                 pic14_emitcode ("push","acc");
9947         }
9948         
9949         freeAsmop(right,NULL,ic,FALSE);
9950         /* now assign DPTR to result */
9951         aopOp(result,ic,FALSE);
9952         size = AOP_SIZE(result);
9953         while (size--) {
9954                 pic14_emitcode ("pop","acc");
9955                 aopPut(AOP(result),"a",--offset);
9956         }
9957         freeAsmop(result,NULL,ic,FALSE);
9958         
9959 }
9960 #endif
9961
9962 /*-----------------------------------------------------------------*/
9963 /* genAssign - generate code for assignment                        */
9964 /*-----------------------------------------------------------------*/
9965 static void genAssign (iCode *ic)
9966 {
9967         operand *result, *right;
9968         int size, offset,know_W;
9969         unsigned long lit = 0L;
9970         
9971         result = IC_RESULT(ic);
9972         right  = IC_RIGHT(ic) ;
9973         
9974         FENTRY;
9975         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9976         
9977         /* if they are the same */
9978         if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9979                 return ;
9980         
9981         aopOp(right,ic,FALSE);
9982         aopOp(result,ic,TRUE);
9983         
9984         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9985         
9986         /* if they are the same registers */
9987         if (pic14_sameRegs(AOP(right),AOP(result)))
9988                 goto release;
9989
9990         /* special case: assign from __code */
9991         if (!IS_ITEMP(right)                            /* --> iTemps never reside in __code */
9992                 && IS_SYMOP (right)                     /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
9993                 && !IS_FUNC(OP_SYM_TYPE(right))         /* --> we would want its address instead of the first instruction */
9994                 && !IS_CODEPTR(OP_SYM_TYPE(right))      /* --> get symbols address instread */
9995                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
9996         {
9997           emitpComment ("genAssign from CODESPACE");
9998           genConstPointerGet (right, result, ic);
9999           goto release;
10000         }
10001         
10002         /* just for symmetry reasons... */
10003         if (!IS_ITEMP(result)
10004                 && IS_SYMOP (result)
10005                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
10006         {
10007           assert ( !"cannot write to CODESPACE" );
10008         }
10009
10010         /* if the result is a bit */
10011         if (AOP_TYPE(result) == AOP_CRY) {
10012                 
10013         /* if the right size is a literal then
10014                 we know what the value is */
10015                 if (AOP_TYPE(right) == AOP_LIT) {
10016                         
10017                         emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10018                                 popGet(AOP(result),0));
10019                         
10020                         if (((int) operandLitValue(right))) 
10021                                 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10022                                 AOP(result)->aopu.aop_dir,
10023                                 AOP(result)->aopu.aop_dir);
10024                         else
10025                                 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10026                                 AOP(result)->aopu.aop_dir,
10027                                 AOP(result)->aopu.aop_dir);
10028                         goto release;
10029                 }
10030                 
10031                 /* the right is also a bit variable */
10032                 if (AOP_TYPE(right) == AOP_CRY) {
10033                         emitpcode(POC_BCF,    popGet(AOP(result),0));
10034                         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10035                         emitpcode(POC_BSF,    popGet(AOP(result),0));
10036                         
10037                         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10038                                 AOP(result)->aopu.aop_dir,
10039                                 AOP(result)->aopu.aop_dir);
10040                         pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10041                                 AOP(right)->aopu.aop_dir,
10042                                 AOP(right)->aopu.aop_dir);
10043                         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10044                                 AOP(result)->aopu.aop_dir,
10045                                 AOP(result)->aopu.aop_dir);
10046                         goto release ;
10047                 }
10048                 
10049                 /* we need to or */
10050                 emitpcode(POC_BCF,    popGet(AOP(result),0));
10051                 pic14_toBoolean(right);
10052                 emitSKPZ;
10053                 emitpcode(POC_BSF,    popGet(AOP(result),0));
10054                 //aopPut(AOP(result),"a",0);
10055                 goto release ;
10056         }
10057         
10058         /* bit variables done */
10059         /* general case */
10060         size = AOP_SIZE(result);
10061         offset = 0 ;
10062         if(AOP_TYPE(right) == AOP_LIT)
10063                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10064         
10065         if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10066                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10067                 if(aopIdx(AOP(result),0) == 4) {
10068                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10069                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10070                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10071                         goto release;
10072                 } else
10073                         DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10074         }
10075         
10076         know_W=-1;
10077         while (size--) {
10078                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10079                 if(AOP_TYPE(right) == AOP_LIT) {
10080                         if(lit&0xff) {
10081                                 if(know_W != (int)(lit&0xff))
10082                                         emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10083                                 know_W = lit&0xff;
10084                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10085                         } else
10086                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10087                         
10088                         lit >>= 8;
10089                         
10090                 } else if (AOP_TYPE(right) == AOP_CRY) {
10091                         emitpcode(POC_CLRF, popGet(AOP(result),offset));
10092                         if(offset == 0) {
10093                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10094                                 emitpcode(POC_INCF, popGet(AOP(result),0));
10095                         }
10096                 } else {
10097                         mov2w_op (right, offset);
10098                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10099                 }
10100                 
10101                 offset++;
10102         }
10103         
10104         
10105 release:
10106         freeAsmop (right,NULL,ic,FALSE);
10107         freeAsmop (result,NULL,ic,TRUE);
10108 }   
10109
10110 /*-----------------------------------------------------------------*/
10111 /* genJumpTab - genrates code for jump table                       */
10112 /*-----------------------------------------------------------------*/
10113 static void genJumpTab (iCode *ic)
10114 {
10115         symbol *jtab;
10116         char *l;
10117         
10118         FENTRY;
10119         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10120         
10121         aopOp(IC_JTCOND(ic),ic,FALSE);
10122         /* get the condition into accumulator */
10123         l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10124         MOVA(l);
10125         /* multiply by three */
10126         pic14_emitcode("add","a,acc");
10127         pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10128         
10129         jtab = newiTempLabel(NULL);
10130         pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10131         pic14_emitcode("jmp","@a+dptr");
10132         pic14_emitcode("","%05d_DS_:",jtab->key+100);
10133         
10134         emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10135         emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10136         emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10137         emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10138         emitSKPNC;
10139         emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10140         emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10141         emitpLabel(jtab->key);
10142         
10143         freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10144         
10145         /* now generate the jump labels */
10146         for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10147         jtab = setNextItem(IC_JTLABELS(ic))) {
10148                 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10149                 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10150                 
10151         }
10152         
10153 }
10154
10155 /*-----------------------------------------------------------------*/
10156 /* genMixedOperation - gen code for operators between mixed types  */
10157 /*-----------------------------------------------------------------*/
10158 /*
10159 TSD - Written for the PIC port - but this unfortunately is buggy.
10160 This routine is good in that it is able to efficiently promote 
10161 types to different (larger) sizes. Unfortunately, the temporary
10162 variables that are optimized out by this routine are sometimes
10163 used in other places. So until I know how to really parse the 
10164 iCode tree, I'm going to not be using this routine :(.
10165 */
10166 static int genMixedOperation (iCode *ic)
10167 {
10168         FENTRY;
10169 #if 0
10170         operand *result = IC_RESULT(ic);
10171         sym_link *ctype = operandType(IC_LEFT(ic));
10172         operand *right = IC_RIGHT(ic);
10173         int ret = 0;
10174         int big,small;
10175         int offset;
10176         
10177         iCode *nextic;
10178         operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10179         
10180         pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10181         
10182         nextic = ic->next;
10183         if(!nextic)
10184                 return 0;
10185         
10186         nextright = IC_RIGHT(nextic);
10187         nextleft  = IC_LEFT(nextic);
10188         nextresult = IC_RESULT(nextic);
10189         
10190         aopOp(right,ic,FALSE);
10191         aopOp(result,ic,FALSE);
10192         aopOp(nextright,  nextic, FALSE);
10193         aopOp(nextleft,   nextic, FALSE);
10194         aopOp(nextresult, nextic, FALSE);
10195         
10196         if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10197                 
10198                 operand *t = right;
10199                 right = nextright;
10200                 nextright = t; 
10201                 
10202                 pic14_emitcode(";remove right +","");
10203                 
10204         } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10205         /*
10206         operand *t = right;
10207         right = nextleft;
10208         nextleft = t; 
10209                 */
10210                 pic14_emitcode(";remove left +","");
10211         } else
10212                 return 0;
10213         
10214         big = AOP_SIZE(nextleft);
10215         small = AOP_SIZE(nextright);
10216         
10217         switch(nextic->op) {
10218                 
10219         case '+':
10220                 pic14_emitcode(";optimize a +","");
10221                 /* if unsigned or not an integral type */
10222                 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10223                         pic14_emitcode(";add a bit to something","");
10224                 } else {
10225                         
10226                         pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10227                         
10228                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10229                                 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10230                                 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10231                         } else
10232                                 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10233                         
10234                         offset = 0;
10235                         while(--big) {
10236                                 
10237                                 offset++;
10238                                 
10239                                 if(--small) {
10240                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10241                                                 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10242                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10243                                         }
10244                                         
10245                                         pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10246                                         emitSKPNC;
10247                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10248                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10249                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10250                                         pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10251                                         pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10252                                         
10253                                 } else {
10254                                         pic14_emitcode("rlf","known_zero,w");
10255                                         
10256                                         /*
10257                                         if right is signed
10258                                         btfsc  right,7
10259                                         addlw ff
10260                                         */
10261                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10262                                                 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10263                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10264                                         } else {
10265                                                 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10266                                         }
10267                                 }
10268                         }
10269                         ret = 1;
10270                 }
10271         }
10272         ret = 1;
10273         
10274 release:
10275         freeAsmop(right,NULL,ic,TRUE);
10276         freeAsmop(result,NULL,ic,TRUE);
10277         freeAsmop(nextright,NULL,ic,TRUE);
10278         freeAsmop(nextleft,NULL,ic,TRUE);
10279         if(ret)
10280                 nextic->generated = 1;
10281         
10282         return ret;
10283 #else
10284         return 0;
10285 #endif
10286 }
10287 /*-----------------------------------------------------------------*/
10288 /* genCast - gen code for casting                                  */
10289 /*-----------------------------------------------------------------*/
10290 static void genCast (iCode *ic)
10291 {
10292         operand *result = IC_RESULT(ic);
10293         sym_link *restype = operandType(result);
10294         sym_link *rtype = operandType(IC_RIGHT(ic));
10295         operand *right = IC_RIGHT(ic);
10296         int size, offset ;
10297         
10298         FENTRY;
10299         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10300         /* if they are equivalent then do nothing */
10301         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10302                 return ;
10303         
10304         aopOp(right,ic,FALSE) ;
10305         aopOp(result,ic,FALSE);
10306         
10307         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10308         
10309         /* if the result is a bit */
10310         if (AOP_TYPE(result) == AOP_CRY) {
10311                 assert(!"assigning to bit variables is not supported");
10312         }
10313         
10314         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10315                 int offset = 1;
10316                 size = AOP_SIZE(result);
10317                 
10318                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10319                 
10320                 emitpcode(POC_CLRF,   popGet(AOP(result),0));
10321                 emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10322                 emitpcode(POC_INCF,   popGet(AOP(result),0));
10323                 
10324                 while (size--)
10325                         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
10326                 
10327                 goto release;
10328         }
10329         
10330         if (IS_PTR(restype))
10331         {
10332           operand *result = IC_RESULT(ic);
10333           //operand *left = IC_LEFT(ic);
10334           operand *right = IC_RIGHT(ic);
10335           int tag = 0xff;
10336           
10337           /* copy common part */
10338           int max, size = AOP_SIZE(result);
10339           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10340           DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10341
10342           /* warn if we discard generic opinter tag */
10343           if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10344           {
10345             //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10346           } // if
10347
10348           max = size;
10349           while (size--)
10350           {
10351             mov2w_op (right, size);
10352             movwf (AOP(result), size);
10353           } // while
10354
10355           /* upcast into generic pointer type? */
10356           if (IS_GENPTR(restype)
10357                 && (size < AOP_SIZE(result))
10358                 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10359           {
10360             //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10361             if (IS_PTR(rtype))
10362             {
10363               switch (DCL_TYPE(rtype))
10364               {
10365               case POINTER:     /* __data */
10366               case FPOINTER:    /* __data */
10367                 assert (AOP_SIZE(right) == 2);
10368                 tag = GPTRTAG_DATA;
10369                 break;
10370
10371               case CPOINTER:    /* __code */
10372                 assert (AOP_SIZE(right) == 2);
10373                 tag = GPTRTAG_CODE;
10374                 break;
10375                 
10376               case GPOINTER:    /* unknown destination, __data or __code */
10377                 /* assume __data space (address of immediate) */
10378                 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10379                 if (AOP(right)->code)
10380                   tag = GPTRTAG_CODE;
10381                 else
10382                   tag = GPTRTAG_DATA;
10383                 break;
10384                 
10385               default:
10386                 assert (!"unhandled pointer type");
10387               } // switch
10388             } else {
10389               /* convert other values into pointers to __data space */
10390               tag = GPTRTAG_DATA;
10391             }
10392
10393             assert (AOP_SIZE(result) == 3);
10394             if (tag == 0) {
10395               emitpcode(POC_CLRF, popGet(AOP(result), 2));
10396             } else {
10397               emitpcode(POC_MOVLW, popGetLit(tag));
10398               movwf(AOP(result), 2);
10399             }
10400           } else {
10401             addSign(result, max, 0);
10402           } // if
10403           goto release;
10404         }
10405         
10406         /* if they are the same size : or less */
10407         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10408                 
10409                 /* if they are in the same place */
10410                 if (pic14_sameRegs(AOP(right),AOP(result)))
10411                         goto release;
10412                 
10413                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10414                 if (IS_PTR_CONST(rtype))
10415                         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10416                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10417                         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10418                 
10419                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10420                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10421                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
10422                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10423                         emitpcode(POC_MOVWF, popGet(AOP(result),1));
10424                         if(AOP_SIZE(result) <2)
10425                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10426                         
10427                 } else {
10428                         
10429                         /* if they in different places then copy */
10430                         size = AOP_SIZE(result);
10431                         offset = 0 ;
10432                         while (size--) {
10433                                 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10434                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10435                                 
10436                                 //aopPut(AOP(result),
10437                                 // aopGet(AOP(right),offset,FALSE,FALSE),
10438                                 // offset);
10439                                 
10440                                 offset++;
10441                         }
10442                 }
10443                 goto release;
10444         }
10445         
10446         /* so we now know that the size of destination is greater
10447         than the size of the source.
10448         Now, if the next iCode is an operator then we might be
10449         able to optimize the operation without performing a cast.
10450         */
10451         if(0 && genMixedOperation(ic)) {
10452                 /* XXX: cannot optimize: must copy regs! */
10453                 goto release;
10454         }
10455         
10456         /* we move to result for the size of source */
10457         size = AOP_SIZE(right);
10458         offset = 0 ;
10459         while (size--) {
10460                 emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
10461                 emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
10462                 offset++;
10463         }
10464
10465         addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10466
10467 release:
10468         freeAsmop(right,NULL,ic,TRUE);
10469         freeAsmop(result,NULL,ic,TRUE);
10470         
10471 }
10472
10473 /*-----------------------------------------------------------------*/
10474 /* genDjnz - generate decrement & jump if not zero instrucion      */
10475 /*-----------------------------------------------------------------*/
10476 static int genDjnz (iCode *ic, iCode *ifx)
10477 {
10478         symbol *lbl, *lbl1;
10479         FENTRY;
10480         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10481         
10482         if (!ifx)
10483                 return 0;
10484         
10485                 /* if the if condition has a false label
10486         then we cannot save */
10487         if (IC_FALSE(ifx))
10488                 return 0;
10489         
10490                 /* if the minus is not of the form 
10491         a = a - 1 */
10492         if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10493                 !IS_OP_LITERAL(IC_RIGHT(ic)))
10494                 return 0;
10495         
10496         if (operandLitValue(IC_RIGHT(ic)) != 1)
10497                 return 0;
10498         
10499                 /* if the size of this greater than one then no
10500         saving */
10501         if (getSize(operandType(IC_RESULT(ic))) > 1)
10502                 return 0;
10503         
10504         /* otherwise we can save BIG */
10505         lbl = newiTempLabel(NULL);
10506         lbl1= newiTempLabel(NULL);
10507         
10508         aopOp(IC_RESULT(ic),ic,FALSE);
10509         
10510         if (IS_AOP_PREG(IC_RESULT(ic))) {
10511                 pic14_emitcode("dec","%s",
10512                         aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10513                 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10514                 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10515         } else {  
10516                 
10517                 
10518                 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10519                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10520                 
10521                 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10522                 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10523                 
10524         }
10525         /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10526         /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10527         /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10528         /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10529         
10530         
10531         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10532         ifx->generated = 1;
10533         return 1;
10534 }
10535
10536 /*-----------------------------------------------------------------*/
10537 /* genReceive - generate code for a receive iCode                  */
10538 /*-----------------------------------------------------------------*/
10539 static void genReceive (iCode *ic)
10540 {
10541         FENTRY;
10542         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10543         
10544         if (isOperandInFarSpace(IC_RESULT(ic)) &&
10545                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10546                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10547                 
10548                 int size = getSize(operandType(IC_RESULT(ic)));
10549                 int offset =  fReturnSizePic - size;
10550                 while (size--) {
10551                         pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10552                                 fReturn[fReturnSizePic - offset - 1] : "acc"));
10553                         offset++;
10554                 }
10555                 aopOp(IC_RESULT(ic),ic,FALSE);
10556                 size = AOP_SIZE(IC_RESULT(ic));
10557                 offset = 0;
10558                 while (size--) {
10559                         pic14_emitcode ("pop","acc");
10560                         aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10561                 }
10562                 
10563         } else {
10564                 _G.accInUse++;
10565                 aopOp(IC_RESULT(ic),ic,FALSE);
10566                 _G.accInUse--;
10567                 assignResultValue(IC_RESULT(ic));
10568         }
10569         
10570         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10571 }
10572
10573 /*-----------------------------------------------------------------*/
10574 /* genDummyRead - generate code for dummy read of volatiles        */
10575 /*-----------------------------------------------------------------*/
10576 static void
10577 genDummyRead (iCode * ic)
10578 {
10579         FENTRY;
10580         pic14_emitcode ("; genDummyRead","");
10581         pic14_emitcode ("; not implemented","");
10582         
10583         ic = ic;
10584 }
10585
10586 /*-----------------------------------------------------------------*/
10587 /* genpic14Code - generate code for pic14 based controllers        */
10588 /*-----------------------------------------------------------------*/
10589 /*
10590 * At this point, ralloc.c has gone through the iCode and attempted
10591 * to optimize in a way suitable for a PIC. Now we've got to generate
10592 * PIC instructions that correspond to the iCode.
10593 *
10594 * Once the instructions are generated, we'll pass through both the
10595 * peep hole optimizer and the pCode optimizer.
10596 *-----------------------------------------------------------------*/
10597
10598 void genpic14Code (iCode *lic)
10599 {
10600         iCode *ic;
10601         int cln = 0;
10602         const char *cline;
10603         
10604         FENTRY;
10605         lineHead = lineCurr = NULL;
10606         
10607         pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10608         addpBlock(pb);
10609         
10610         /* if debug information required */
10611         if (options.debug && currFunc) { 
10612                 if (currFunc) {
10613                         debugFile->writeFunction (currFunc, lic);
10614                 }
10615         }
10616         
10617         
10618         for (ic = lic ; ic ; ic = ic->next ) {
10619                 
10620                 //DEBUGpic14_emitcode(";ic","");
10621                 //fprintf (stderr, "in ic loop\n");
10622                 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10623                 //ic->lineno, printCLine(ic->filename, ic->lineno));
10624                 
10625                 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10626                   cln = ic->lineno;
10627                   //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10628                   cline = printCLine (ic->filename, ic->lineno);
10629                   if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10630                   addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10631                   //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10632                 }
10633                 
10634                 if (options.iCodeInAsm) {
10635                   emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10636                 }
10637                 /* if the result is marked as
10638                 spilt and rematerializable or code for
10639                 this has already been generated then
10640                 do nothing */
10641                 if (resultRemat(ic) || ic->generated ) 
10642                         continue ;
10643                 
10644                 /* depending on the operation */
10645                 switch (ic->op) {
10646                 case '!' :
10647                         genNot(ic);
10648                         break;
10649                         
10650                 case '~' :
10651                         genCpl(ic);
10652                         break;
10653                         
10654                 case UNARYMINUS:
10655                         genUminus (ic);
10656                         break;
10657                         
10658                 case IPUSH:
10659                         genIpush (ic);
10660                         break;
10661                         
10662                 case IPOP:
10663                         /* IPOP happens only when trying to restore a 
10664                         spilt live range, if there is an ifx statement
10665                         following this pop then the if statement might
10666                         be using some of the registers being popped which
10667                         would destory the contents of the register so
10668                         we need to check for this condition and handle it */
10669                         if (ic->next            && 
10670                                 ic->next->op == IFX &&
10671                                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10672                                 genIfx (ic->next,ic);
10673                         else
10674                                 genIpop (ic);
10675                         break; 
10676                         
10677                 case CALL:
10678                         genCall (ic);
10679                         break;
10680                         
10681                 case PCALL:
10682                         genPcall (ic);
10683                         break;
10684                         
10685                 case FUNCTION:
10686                         genFunction (ic);
10687                         break;
10688                         
10689                 case ENDFUNCTION:
10690                         genEndFunction (ic);
10691                         break;
10692                         
10693                 case RETURN:
10694                         genRet (ic);
10695                         break;
10696                         
10697                 case LABEL:
10698                         genLabel (ic);
10699                         break;
10700                         
10701                 case GOTO:
10702                         genGoto (ic);
10703                         break;
10704                         
10705                 case '+' :
10706                         genPlus (ic) ;
10707                         break;
10708                         
10709                 case '-' :
10710                         if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10711                                 genMinus (ic);
10712                         break;
10713                         
10714                 case '*' :
10715                         genMult (ic);
10716                         break;
10717                         
10718                 case '/' :
10719                         genDiv (ic) ;
10720                         break;
10721                         
10722                 case '%' :
10723                         genMod (ic);
10724                         break;
10725                         
10726                 case '>' :
10727                         genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));         
10728                         break;
10729                         
10730                 case '<' :
10731                         genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10732                         break;
10733                         
10734                 case LE_OP:
10735                 case GE_OP:
10736                 case NE_OP:
10737                         
10738                         /* note these two are xlated by algebraic equivalence
10739                         during parsing SDCC.y */
10740                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10741                                 "got '>=' or '<=' shouldn't have come here");
10742                         break;  
10743                         
10744                 case EQ_OP:
10745                         genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10746                         break;      
10747                         
10748                 case AND_OP:
10749                         genAndOp (ic);
10750                         break;
10751                         
10752                 case OR_OP:
10753                         genOrOp (ic);
10754                         break;
10755                         
10756                 case '^' :
10757                         genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10758                         break;
10759                         
10760                 case '|' :
10761                         genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10762                         break;
10763                         
10764                 case BITWISEAND:
10765                         genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10766                         break;
10767                         
10768                 case INLINEASM:
10769                         genInline (ic);
10770                         break;
10771                         
10772                 case RRC:
10773                         genRRC (ic);
10774                         break;
10775                         
10776                 case RLC:
10777                         genRLC (ic);
10778                         break;
10779                         
10780                 case GETHBIT:
10781                         genGetHbit (ic);
10782                         break;
10783                         
10784                 case LEFT_OP:
10785                         genLeftShift (ic);
10786                         break;
10787                         
10788                 case RIGHT_OP:
10789                         genRightShift (ic);
10790                         break;
10791                         
10792                 case GET_VALUE_AT_ADDRESS:
10793                         genPointerGet(ic);
10794                         break;
10795                         
10796                 case '=' :
10797                         if (POINTER_SET(ic))
10798                                 genPointerSet(ic);
10799                         else
10800                                 genAssign(ic);
10801                         break;
10802                         
10803                 case IFX:
10804                         genIfx (ic,NULL);
10805                         break;
10806                         
10807                 case ADDRESS_OF:
10808                         genAddrOf (ic);
10809                         break;
10810                         
10811                 case JUMPTABLE:
10812                         genJumpTab (ic);
10813                         break;
10814                         
10815                 case CAST:
10816                         genCast (ic);
10817                         break;
10818                         
10819                 case RECEIVE:
10820                         genReceive(ic);
10821                         break;
10822                         
10823                 case SEND:
10824                         addSet(&_G.sendSet,ic);
10825                         break;
10826                         
10827                 case DUMMY_READ_VOLATILE:
10828                         genDummyRead (ic);
10829                         break;
10830                         
10831                 default :
10832                         fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10833                         ic = ic;
10834                         break;
10835                 }
10836         }
10837
10838         
10839         /* now we are ready to call the
10840         peep hole optimizer */
10841         if (!options.nopeep) {
10842                 peepHole (&lineHead);
10843         }
10844         /* now do the actual printing */
10845         printLine (lineHead,codeOutFile);
10846         
10847 #ifdef PCODE_DEBUG
10848         DFPRINTF((stderr,"printing pBlock\n\n"));
10849         printpBlock(stdout,pb);
10850 #endif
10851         
10852         return;
10853 }
10854
10855 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10856  * (meaning: representing its own address) or not (referencing its contents).
10857  * This can only be decided based on the operand's type. */
10858 int
10859 aop_isLitLike (asmop *aop)
10860 {
10861   assert (aop);
10862   if (aop->type == AOP_LIT) return 1;
10863 if (aop->type == AOP_IMMD) return 1;
10864   if ((aop->type == AOP_PCODE) &&
10865                 ((aop->aopu.pcop->type == PO_LITERAL)))
10866   {
10867     /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10868      * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10869     return 1;
10870   }
10871   return 0;
10872 }
10873
10874 int
10875 op_isLitLike (operand *op)
10876 {
10877   assert (op);
10878   if (aop_isLitLike (AOP(op))) return 1;
10879   if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10880   if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;
10881   return 0;
10882 }