* src/pic/glue.h,src/pic16/glue.h: added prototypes
[fw/sdcc] / src / pic / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for pic
3   
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8     cont'd   -  Raphael Neider <rneider AT web.de> (2005)
9   
10   This program is free software; you can redistribute it and/or modify it
11   under the terms of the GNU General Public License as published by the
12   Free Software Foundation; either version 2, or (at your option) any
13   later version.
14   
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License for more details.
19   
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23   
24   In other words, you are welcome to use, share and improve this program.
25   You are forbidden to forbid anyone else to use, share and improve
26   what you give them.   Help stamp out software-hoarding!
27   
28   Notes:
29   000123 mlh  Moved aopLiteral to SDCCglue.c to help the split
30       Made everything static
31 -------------------------------------------------------------------------*/
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include "SDCCglobl.h"
38 #include "newalloc.h" 
39
40 #include "common.h"
41 #include "SDCCpeeph.h"
42 #include "ralloc.h"
43 #include "pcode.h"
44 #include "gen.h"
45 #include "glue.h"
46
47 /* When changing these, you must also update the assembler template
48  * in device/lib/libsdcc/macros.inc */
49 #define GPTRTAG_DATA    0x00
50 #define GPTRTAG_CODE    0x80
51
52 /* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
53 #define PIC_IS_DATA_PTR(x)      (IS_DATA_PTR(x) || IS_FARPTR(x))
54 #define PIC_IS_FARPTR(x)        (PIC_IS_DATA_PTR(x))
55
56 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
57 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
58 void genMult8X8_8 (operand *, operand *,operand *);
59 extern void printpBlock(FILE *of, pBlock *pb);
60
61 static int labelOffset=0;
62 extern int debug_verbose;
63 extern int pic14_hasInterrupt;
64 //static int optimized_for_speed = 0;
65
66 /* max_key keeps track of the largest label number used in 
67 a function. This is then used to adjust the label offset
68 for the next function.
69 */
70 static int max_key=0;
71 static int GpsuedoStkPtr=0;
72
73 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
74 extern char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
75 const char *AopType(short type);
76
77 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
78
79 /* this is the down and dirty file with all kinds of 
80 kludgy & hacky stuff. This is what it is all about
81 CODE GENERATION for a specific MCU . some of the
82 routines may be reusable, will have to see */
83
84 static char *zero = "#0x00";
85 static char *one  = "#0x01";
86 static char *spname = "sp";
87
88 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
89 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
90 static char **fReturn = fReturnpic14;
91
92 //static char *accUse[] = {"a","b"};
93
94 //static short rbank = -1;
95
96 static struct {
97         short r0Pushed;
98         short r1Pushed;
99         short accInUse;
100         short inLine;
101         short debugLine;
102         short nRegsSaved;
103         set *sendSet;
104 } _G;
105
106 /* Resolved ifx structure. This structure stores information
107 about an iCode ifx that makes it easier to generate code.
108 */
109 typedef struct resolvedIfx {
110         symbol *lbl;     /* pointer to a label */
111         int condition;   /* true or false ifx */
112         int generated;   /* set true when the code associated with the ifx
113                           * is generated */
114 } resolvedIfx;
115
116 extern int pic14_ptrRegReq ;
117 extern int pic14_nRegs;
118 extern FILE *codeOutFile;
119 static void saverbank (int, iCode *,bool);
120
121 static lineNode *lineHead = NULL;
122 static lineNode *lineCurr = NULL;
123
124 #if 0
125 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
126 0xE0, 0xC0, 0x80, 0x00};
127 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
128 0x07, 0x03, 0x01, 0x00};
129 #endif
130
131 static  pBlock *pb;
132
133 /*-----------------------------------------------------------------*/
134 /*      my_powof2(n) - If `n' is an integaer power of 2, then the          */
135 /*                                 exponent of 2 is returned, otherwise -1 is      */
136 /*                                 returned.                                                                       */
137 /* note that this is similar to the function `powof2' in SDCCsymt  */
138 /* if(n == 2^y)                                                                                                    */
139 /*       return y;                                                                                                         */
140 /* return -1;                                                                                                      */
141 /*-----------------------------------------------------------------*/
142 static int my_powof2 (unsigned long num)
143 {
144         if(num) {
145                 if( (num & (num-1)) == 0) {
146                         int nshifts = -1;
147                         while(num) {
148                                 num>>=1;
149                                 nshifts++;
150                         }
151                         return nshifts;
152                 }
153         }
154         
155         return -1;
156 }
157
158 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
159 {
160         
161         DEBUGpic14_emitcode ("; ","line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
162                 line_no,
163                 ((result) ? AopType(AOP_TYPE(result)) : "-"),
164                 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
165                 ((result) ? AOP_SIZE(result) : 0),
166                 ((left)   ? AopType(AOP_TYPE(left)) : "-"),
167                 ((left)   ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
168                 ((left)   ? AOP_SIZE(left) : 0),
169                 ((right)  ? AopType(AOP_TYPE(right)) : "-"),
170                 ((right)  ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
171                 ((right)  ? AOP_SIZE(right) : 0));
172         
173 }
174
175 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
176 {
177         
178         DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
179                 line_no,
180                 ((result) ? AopType(AOP_TYPE(result)) : "-"),
181                 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
182                 ((left)   ? AopType(AOP_TYPE(left)) : "-"),
183                 ((left)   ? (SPEC_USIGN(operandType(left))       ? 'u' : 's') : '-'),
184                 ((right)  ? AopType(AOP_TYPE(right)) : "-"),
185                 ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
186         
187 }
188
189 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
190 {
191         va_list ap;
192         char lb[INITIAL_INLINEASM];  
193         unsigned char *lbp = (unsigned char *)lb;
194         
195         if(!debug_verbose && !options.debug)
196                 return;
197         
198         va_start(ap,fmt);   
199         
200         if (inst && *inst) {
201                 if (fmt && *fmt)
202                         sprintf(lb,"%s\t",inst);
203                 else
204                         sprintf(lb,"%s",inst);
205                 vsprintf(lb+(strlen(lb)),fmt,ap);
206         }  else
207                 vsprintf(lb,fmt,ap);
208         
209         while (isspace(*lbp)) lbp++;
210         
211         if (lbp && *lbp) 
212                 lineCurr = (lineCurr ?
213                 connectLine(lineCurr,newLineNode(lb)) :
214         (lineHead = newLineNode(lb)));
215         lineCurr->isInline = _G.inLine;
216         lineCurr->isDebug  = _G.debugLine;
217         
218         addpCode2pBlock(pb,newpCodeCharP(lb));
219         
220         va_end(ap);
221 }
222
223 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
224 {
225 #if defined (HAVE_VSNPRINTF)
226   vsnprintf (buf, size, fmt, ap);
227 #elif defined (HAVE_VSPRINTF)
228   vsprintf (buf, size, fmt, ap);
229   if (strlen (buf) >= size)
230   {
231     fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
232   }
233 #elif defined (HAVE_SNPRINTF)
234   snprintf (buf, size, "vs(n)printf required");
235 #elif defined (HAVE_SRINTF)
236   sprintf (buf, "vs(n)printf required");
237   if (strlen (buf) >= size)
238   {
239     fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
240   }
241 #else
242   assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
243 #endif
244 }
245
246 void emitpComment (const char *fmt, ...)
247 {
248   va_list va;
249   char buffer[4096];
250   
251   va_start (va, fmt);
252   if (pb) {
253     Safe_vsnprintf (buffer, 4096, fmt, va);
254     //fprintf (stderr, "%s\n" ,buffer);
255     addpCode2pBlock (pb, newpCodeCharP (buffer));
256 #if 0
257   } else {
258     Safe_vsnprintf (buffer, 4096, fmt, va);
259     fprintf (stderr, "No current pBlock -- discarding comment [%s]\n", buffer);
260 #endif
261   }
262   va_end (va);
263 }
264
265 void emitpLabel(int key)
266 {
267         addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
268 }
269
270 /* gen.h defines a macro emitpcode that should be used to call emitpcode
271  * as this allows for easy debugging (ever asked the question: where was
272  * this instruction geenrated? Here is the answer... */
273 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
274 {
275         if(pcop)
276                 addpCode2pBlock(pb,newpCode(poc,pcop));
277         else
278                 DEBUGpic14_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
279 }
280
281 void emitpcodeNULLop(PIC_OPCODE poc)
282 {
283         
284         addpCode2pBlock(pb,newpCode(poc,NULL));
285         
286 }
287
288
289 /*-----------------------------------------------------------------*/
290 /* pic14_emitcode - writes the code into a file : for now it is simple    */
291 /*-----------------------------------------------------------------*/
292 void pic14_emitcode (char *inst,char *fmt, ...)
293 {
294         va_list ap;
295         char lb[INITIAL_INLINEASM];  
296         unsigned char *lbp = (unsigned char *)lb;
297         
298         va_start(ap,fmt);   
299         
300         if (inst && *inst) {
301                 if (fmt && *fmt)
302                         sprintf(lb,"%s\t",inst);
303                 else
304                         sprintf(lb,"%s",inst);
305                 vsprintf(lb+(strlen(lb)),fmt,ap);
306         }  else
307                 vsprintf(lb,fmt,ap);
308         
309         while (isspace(*lbp)) lbp++;
310         
311         if (lbp && *lbp) 
312                 lineCurr = (lineCurr ?
313                 connectLine(lineCurr,newLineNode(lb)) :
314         (lineHead = newLineNode(lb)));
315         lineCurr->isInline = _G.inLine;
316         lineCurr->isDebug  = _G.debugLine;
317         
318         if(debug_verbose)
319                 addpCode2pBlock(pb,newpCodeCharP(lb));
320         
321         va_end(ap);
322 }
323
324 /*-----------------------------------------------------------------*/
325 /* pic14_emitDebuggerSymbol - associate the current code location  */
326 /*       with a debugger symbol                                                                            */
327 /*-----------------------------------------------------------------*/
328 void
329 pic14_emitDebuggerSymbol (char * debugSym)
330 {
331         _G.debugLine = 1;
332         pic14_emitcode ("", ";%s ==.", debugSym);
333         _G.debugLine = 0;
334 }
335
336 #if 0
337 /*-----------------------------------------------------------------*/
338 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
339 /*-----------------------------------------------------------------*/
340 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
341 {
342         bool r0iu = FALSE , r1iu = FALSE;
343         bool r0ou = FALSE , r1ou = FALSE;
344         
345         /* the logic: if r0 & r1 used in the instruction
346         then we are in trouble otherwise */
347         
348         /* first check if r0 & r1 are used by this
349         instruction, in which case we are in trouble */
350         if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
351                 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
352         {
353                 goto endOfWorld;          
354         }
355         
356         r0ou = bitVectBitValue(ic->rMask,R0_IDX);
357         r1ou = bitVectBitValue(ic->rMask,R1_IDX);
358         
359         /* if no usage of r0 then return it */
360         if (!r0iu && !r0ou) {
361                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
362                 (*aopp)->type = AOP_R0;
363                 
364                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
365         }
366         
367         /* if no usage of r1 then return it */
368         if (!r1iu && !r1ou) {
369                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
370                 (*aopp)->type = AOP_R1;
371                 
372                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
373         }    
374         
375         /* now we know they both have usage */
376         /* if r0 not used in this instruction */
377         if (!r0iu) {
378                 /* push it if not already pushed */
379                 if (!_G.r0Pushed) {
380                         //pic14_emitcode ("push","%s",
381                         //                pic14_regWithIdx(R0_IDX)->dname);
382                         _G.r0Pushed++ ;
383                 }
384                 
385                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
386                 (*aopp)->type = AOP_R0;
387                 
388                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
389         }
390         
391         /* if r1 not used then */
392         
393         if (!r1iu) {
394                 /* push it if not already pushed */
395                 if (!_G.r1Pushed) {
396                         //pic14_emitcode ("push","%s",
397                         //                pic14_regWithIdx(R1_IDX)->dname);
398                         _G.r1Pushed++ ;
399                 }
400                 
401                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
402                 (*aopp)->type = AOP_R1;
403                 return pic14_regWithIdx(R1_IDX);
404         }
405         
406 endOfWorld :
407         /* I said end of world but not quite end of world yet */
408         /* if this is a result then we can push it on the stack*/
409         if (result) {
410                 (*aopp)->type = AOP_STK;        
411                 return NULL;
412         }
413         
414         /* other wise this is true end of the world */
415         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
416                 "getFreePtr should never reach here");
417         exit(0);
418 }
419 #endif
420
421 /*-----------------------------------------------------------------*/
422 /* newAsmop - creates a new asmOp                                                                  */
423 /*-----------------------------------------------------------------*/
424 asmop *newAsmop (short type)
425 {
426         asmop *aop;
427         
428         aop = Safe_calloc(1,sizeof(asmop));
429         aop->type = type;
430         return aop;
431 }
432
433 static void genSetDPTR(int n)
434 {
435         if (!n)
436         {
437                 pic14_emitcode(";", "Select standard DPTR");
438                 pic14_emitcode("mov", "dps, #0x00");
439         }
440         else
441         {
442                 pic14_emitcode(";", "Select alternate DPTR");
443                 pic14_emitcode("mov", "dps, #0x01");
444         }
445 }
446
447 /*-----------------------------------------------------------------*/
448 /* resolveIfx - converts an iCode ifx into a form more useful for  */
449 /*                              generating code                                                                    */
450 /*-----------------------------------------------------------------*/
451 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
452 {
453         if(!resIfx) 
454                 return;
455         
456         //  DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
457         
458         resIfx->condition = 1;  /* assume that the ifx is true */
459         resIfx->generated = 0;  /* indicate that the ifx has not been used */
460         
461         if(!ifx) {
462                 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL);      / * oops, there is no ifx. so create a label */
463                                                                                         /*
464                                                                                         DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
465                                                                                         __FUNCTION__,__LINE__,resIfx->lbl->key);
466                 */
467         } else {
468                 if(IC_TRUE(ifx)) {
469                         resIfx->lbl = IC_TRUE(ifx);
470                 } else {
471                         resIfx->lbl = IC_FALSE(ifx);
472                         resIfx->condition = 0;
473                 }
474                 /*
475                 if(IC_TRUE(ifx)) 
476                 DEBUGpic14_emitcode("; ***","ifx true is non-null");
477                 if(IC_FALSE(ifx)) 
478                 DEBUGpic14_emitcode("; ***","ifx false is non-null");
479                 */
480         }
481         
482         //  DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
483         
484 }
485 /*-----------------------------------------------------------------*/
486 /* pointerCode - returns the code for a pointer type                       */
487 /*-----------------------------------------------------------------*/
488 #if 0
489 static int pointerCode (sym_link *etype)
490 {
491         
492         return PTR_TYPE(SPEC_OCLS(etype));
493         
494 }
495 #endif
496
497 /*-----------------------------------------------------------------*/
498 /* aopForSym - for a true symbol                                                                   */
499 /*-----------------------------------------------------------------*/
500 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
501 {
502         asmop *aop;
503         memmap *space= SPEC_OCLS(sym->etype);
504         
505         DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
506         /* if already has one */
507         if (sym->aop)
508                 return sym->aop;
509         
510 #if 0
511         /* assign depending on the storage class */
512         /* if it is on the stack or indirectly addressable */
513         /* space we need to assign either r0 or r1 to it         */    
514         if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
515                 sym->aop = aop = newAsmop(0);
516                 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
517                 aop->size = getSize(sym->type);
518                 
519                 /* now assign the address of the variable to 
520                 the pointer register */
521                 if (aop->type != AOP_STK) {
522                         
523                         if (sym->onStack) {
524                                 if ( _G.accInUse )
525                                         pic14_emitcode("push","acc");
526                                 
527                                 pic14_emitcode("mov","a,_bp");
528                                 pic14_emitcode("add","a,#0x%02x",
529                                         ((sym->stack < 0) ?
530                                         ((char)(sym->stack - _G.nRegsSaved )) :
531                                 ((char)sym->stack)) & 0xff);
532                                 pic14_emitcode("mov","%s,a",
533                                         aop->aopu.aop_ptr->name);
534                                 
535                                 if ( _G.accInUse )
536                                         pic14_emitcode("pop","acc");
537                         } else
538                                 pic14_emitcode("mov","%s,#%s",
539                                 aop->aopu.aop_ptr->name,
540                                 sym->rname);
541                         aop->paged = space->paged;
542                 } else
543                         aop->aopu.aop_stk = sym->stack;
544                 return aop;
545         }
546         
547         if (sym->onStack && options.stack10bit)
548         {
549                 /* It's on the 10 bit stack, which is located in
550                 * far data space.
551                 */
552                 
553                 //DEBUGpic14_emitcode(";","%d",__LINE__);
554                 
555                 if ( _G.accInUse )
556                         pic14_emitcode("push","acc");
557                 
558                 pic14_emitcode("mov","a,_bp");
559                 pic14_emitcode("add","a,#0x%02x",
560                         ((sym->stack < 0) ?
561                         ((char)(sym->stack - _G.nRegsSaved )) :
562                 ((char)sym->stack)) & 0xff);
563                 
564                 genSetDPTR(1);
565                 pic14_emitcode ("mov","dpx1,#0x40");
566                 pic14_emitcode ("mov","dph1,#0x00");
567                 pic14_emitcode ("mov","dpl1, a");
568                 genSetDPTR(0);
569                 
570                 if ( _G.accInUse )
571                         pic14_emitcode("pop","acc");
572                 
573                 sym->aop = aop = newAsmop(AOP_DPTR2);
574                 aop->size = getSize(sym->type); 
575                 return aop;
576         }
577 #endif
578
579         //DEBUGpic14_emitcode(";","%d",__LINE__);
580         /* if in bit space */
581         if (IN_BITSPACE(space)) {
582                 sym->aop = aop = newAsmop (AOP_CRY);
583                 aop->aopu.aop_dir = sym->rname ;
584                 aop->size = getSize(sym->type);
585                 //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
586                 return aop;
587         }
588         /* if it is in direct space */
589         if (IN_DIRSPACE(space)) {
590                 sym->aop = aop = newAsmop (AOP_DIR);
591                 aop->aopu.aop_dir = sym->rname ;
592                 aop->size = getSize(sym->type);
593                 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
594                 return aop;
595         }
596         
597         /* special case for a function */
598         if (IS_FUNC(sym->type)) {   
599                 
600                 sym->aop = aop = newAsmop(AOP_PCODE);
601                 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
602                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
603                 PCOI(aop->aopu.pcop)->_function = 1;
604                 PCOI(aop->aopu.pcop)->index = 0;
605                 aop->size = FPTRSIZE; 
606                 /*
607                 sym->aop = aop = newAsmop(AOP_IMMD);    
608                 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
609                 strcpy(aop->aopu.aop_immd,sym->rname);
610                 aop->size = FPTRSIZE; 
611                 */
612                 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
613                 return aop;
614         }
615         
616         if (IS_ARRAY(sym->type)) {
617                 sym->aop = aop = newAsmop(AOP_PCODE);
618                 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
619                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
620                 PCOI(aop->aopu.pcop)->_function = 0;
621                 PCOI(aop->aopu.pcop)->index = 0;
622                 aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
623                 
624                 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
625                 return aop;
626         }
627         
628         /* only remaining is far space */
629         /* in which case DPTR gets the address */
630         sym->aop = aop = newAsmop(AOP_PCODE);
631         
632         aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
633         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
634         PCOI(aop->aopu.pcop)->index = 0;
635         
636         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
637                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
638         
639         allocDirReg (IC_LEFT(ic));
640         
641         aop->size = FPTRSIZE;
642         /*
643         DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
644         sym->aop = aop = newAsmop(AOP_DPTR);
645         pic14_emitcode ("mov","dptr,#%s", sym->rname);
646         aop->size = getSize(sym->type);
647         
648           DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
649         */
650         
651         /* if it is in code space */
652         if (IN_CODESPACE(space))
653                 aop->code = 1;
654         
655         return aop;       
656 }
657
658 /*-----------------------------------------------------------------*/
659 /* aopForRemat - rematerialzes an object                                                   */
660 /*-----------------------------------------------------------------*/
661 static asmop *aopForRemat (operand *op) // x symbol *sym)
662 {
663         symbol *sym = OP_SYMBOL(op);
664         iCode *ic = NULL;
665         asmop *aop = newAsmop(AOP_PCODE);
666         int val = 0;
667         int offset = 0;
668         
669         ic = sym->rematiCode;
670
671         DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
672         if(IS_OP_POINTER(op)) {
673                 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
674         }
675         for (;;) {
676                 if (ic->op == '+') {
677                         val += (int) operandLitValue(IC_RIGHT(ic));
678                 } else if (ic->op == '-') {
679                         val -= (int) operandLitValue(IC_RIGHT(ic));
680                 } else
681                         break;
682                 
683                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
684         }
685         
686         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
687         aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
688         PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
689         PCOI(aop->aopu.pcop)->index = val;
690         
691         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
692                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
693                 val, IS_PTR_CONST(operandType(op)));
694         
695         //      DEBUGpic14_emitcode(";","aop type  %s",AopType(AOP_TYPE(IC_LEFT(ic))));
696         
697         allocDirReg (IC_LEFT(ic));
698         
699         return aop;              
700 }
701
702 int aopIdx (asmop *aop, int offset)
703 {
704         if(!aop)
705                 return -1;
706         
707         if(aop->type !=  AOP_REG)
708                 return -2;
709         
710         return aop->aopu.aop_reg[offset]->rIdx;
711         
712 }
713 /*-----------------------------------------------------------------*/
714 /* regsInCommon - two operands have some registers in common       */
715 /*-----------------------------------------------------------------*/
716 static bool regsInCommon (operand *op1, operand *op2)
717 {
718         symbol *sym1, *sym2;
719         int i;
720         
721         /* if they have registers in common */
722         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
723                 return FALSE ;
724         
725         sym1 = OP_SYMBOL(op1);
726         sym2 = OP_SYMBOL(op2);
727         
728         if (sym1->nRegs == 0 || sym2->nRegs == 0)
729                 return FALSE ;
730         
731         for (i = 0 ; i < sym1->nRegs ; i++) {
732                 int j;
733                 if (!sym1->regs[i])
734                         continue ;
735                 
736                 for (j = 0 ; j < sym2->nRegs ;j++ ) {
737                         if (!sym2->regs[j])
738                                 continue ;
739                         
740                         if (sym2->regs[j] == sym1->regs[i])
741                                 return TRUE ;
742                 }
743         }
744         
745         return FALSE ;
746 }
747
748 /*-----------------------------------------------------------------*/
749 /* operandsEqu - equivalent                                                                        */
750 /*-----------------------------------------------------------------*/
751 static bool operandsEqu ( operand *op1, operand *op2)
752 {
753         symbol *sym1, *sym2;
754         
755         /* if they not symbols */
756         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
757                 return FALSE;
758         
759         sym1 = OP_SYMBOL(op1);
760         sym2 = OP_SYMBOL(op2);
761         
762         /* if both are itemps & one is spilt
763         and the other is not then false */
764         if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
765                 sym1->isspilt != sym2->isspilt )
766                 return FALSE ;
767         
768         /* if they are the same */
769         if (sym1 == sym2)
770                 return TRUE ;
771         
772         if (sym1->rname[0] && sym2->rname[0]
773                 && strcmp (sym1->rname, sym2->rname) == 0)
774                 return TRUE;
775         
776         
777         /* if left is a tmp & right is not */
778         if (IS_ITEMP(op1)  && 
779                 !IS_ITEMP(op2) &&
780                 sym1->isspilt  &&
781                 (sym1->usl.spillLoc == sym2))
782                 return TRUE;
783         
784         if (IS_ITEMP(op2)  && 
785                 !IS_ITEMP(op1) &&
786                 sym2->isspilt  &&
787                 sym1->level > 0 &&
788                 (sym2->usl.spillLoc == sym1))
789                 return TRUE ;
790         
791         return FALSE ;
792 }
793
794 /*-----------------------------------------------------------------*/
795 /* pic14_sameRegs - two asmops have the same registers             */
796 /*-----------------------------------------------------------------*/
797 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
798 {
799         int i;
800         
801         if (aop1 == aop2)
802                 return TRUE ;
803         
804         if (aop1->type != AOP_REG ||
805                 aop2->type != AOP_REG )
806                 return FALSE ;
807         
808         if (aop1->size != aop2->size )
809                 return FALSE ;
810         
811         for (i = 0 ; i < aop1->size ; i++ )
812                 if (aop1->aopu.aop_reg[i] !=
813                         aop2->aopu.aop_reg[i] )
814                         return FALSE ;
815                 
816                 return TRUE ;
817 }
818
819 /*-----------------------------------------------------------------*/
820 /* aopOp - allocates an asmop for an operand  :                    */
821 /*-----------------------------------------------------------------*/
822 void aopOp (operand *op, iCode *ic, bool result)
823 {
824         asmop *aop;
825         symbol *sym;
826         int i;
827         
828         if (!op)
829                 return ;
830         
831         /* if this a literal */
832         if (IS_OP_LITERAL(op)) {
833                 op->aop = aop = newAsmop(AOP_LIT);
834                 aop->aopu.aop_lit = op->operand.valOperand;
835                 aop->size = getSize(operandType(op));
836                 return;
837         }
838         
839         {
840                 sym_link *type = operandType(op);
841                 if(IS_PTR_CONST(type))
842                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
843         }
844         
845         /* if already has a asmop then continue */
846         if (op->aop)
847                 return ;
848         
849         /* if the underlying symbol has a aop */
850         if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
851                 DEBUGpic14_emitcode(";","%d",__LINE__);
852                 op->aop = OP_SYMBOL(op)->aop;
853                 return;
854         }
855         
856         /* if this is a true symbol */
857         if (IS_TRUE_SYMOP(op)) {          
858                 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
859                 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
860                 return ;
861         }
862         
863         /* this is a temporary : this has
864         only four choices :
865         a) register
866         b) spillocation
867         c) rematerialize 
868         d) conditional   
869         e) can be a return use only */
870         
871         sym = OP_SYMBOL(op);
872         
873         
874         /* if the type is a conditional */
875         if (sym->regType == REG_CND) {
876                 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
877                 aop->size = 0;
878                 return;
879         }
880         
881         /* if it is spilt then two situations
882         a) is rematerialize 
883         b) has a spill location */
884         if (sym->isspilt || sym->nRegs == 0) {
885                 
886                 DEBUGpic14_emitcode(";","%d",__LINE__);
887                 /* rematerialize it NOW */
888                 if (sym->remat) {
889                         
890                         sym->aop = op->aop = aop = aopForRemat (op);
891                         aop->size = getSize(sym->type);
892                         //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
893                         return;
894                 }
895                 
896 #if 0
897                 /* WREG is not usable as an ordinary operand with PIC architecture,
898                  * one might introduce a scratch register that can be used to make
899                  * WREG accesible as an operand... disable WREG for now */
900                 if (sym->accuse) {
901                         int i;
902                         aop = op->aop = sym->aop = newAsmop(AOP_ACC);
903                         aop->size = getSize(sym->type);
904                         for ( i = 0 ; i < 2 ; i++ )
905                                 aop->aopu.aop_str[i] = accUse[i];
906                         DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
907                         return;  
908                 }
909 #endif
910                 
911                 if (sym->ruonly ) {
912                         if(sym->isptr) {        // && sym->uptr 
913                                 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
914                                 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
915                                 
916                                 //PCOI(aop->aopu.pcop)->_const = 0;
917                                 //PCOI(aop->aopu.pcop)->index = 0;
918                                 /*
919                                 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
920                                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
921                                 */
922                                 //allocDirReg (IC_LEFT(ic));
923                                 
924                                 aop->size = getSize(sym->type);
925                                 DEBUGpic14_emitcode(";","%d",__LINE__);
926                                 return;
927                                 
928                         } else {
929                                 
930                                 unsigned i;
931                                 
932                                 aop = op->aop = sym->aop = newAsmop(AOP_STR);
933                                 aop->size = getSize(sym->type);
934                                 for ( i = 0 ; i < fReturnSizePic ; i++ )
935                                         aop->aopu.aop_str[i] = fReturn[i];
936                                 
937                                 DEBUGpic14_emitcode(";","%d",__LINE__);
938                                 return;
939                         }
940                 }
941                 
942                 /* else spill location  */
943                 if (sym->usl.spillLoc)
944                 {
945                         asmop *oldAsmOp = NULL;
946
947                         if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
948                         {
949                                 /* force a new aop if sizes differ */
950                                 oldAsmOp = sym->usl.spillLoc->aop;
951                                 sym->usl.spillLoc->aop = NULL;
952                         }
953                         DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
954                                 __FUNCTION__,__LINE__,
955                                 sym->usl.spillLoc->rname,
956                                 sym->rname, sym->usl.spillLoc->offset);
957                 
958                         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
959                         if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
960                         {
961                                 /* Don't reuse the new aop, go with the last one */
962                                 sym->usl.spillLoc->aop = oldAsmOp;
963                         }
964                         //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
965                         aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
966                                 getSize(sym->type), 
967                                 sym->usl.spillLoc->offset);
968                         aop->size = getSize(sym->type);
969                 
970                         return;
971                 }
972         }
973         
974         {
975                 sym_link *type = operandType(op);
976                 if(IS_PTR_CONST(type)) 
977                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
978         }
979         
980         /* must be in a register */
981         DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
982         sym->aop = op->aop = aop = newAsmop(AOP_REG);
983         aop->size = sym->nRegs;
984         for ( i = 0 ; i < sym->nRegs ;i++)
985                 aop->aopu.aop_reg[i] = sym->regs[i];
986 }
987
988 /*-----------------------------------------------------------------*/
989 /* freeAsmop - free up the asmop given to an operand                       */
990 /*----------------------------------------------------------------*/
991 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
992 {       
993         asmop *aop ;
994         
995         if (!op)
996                 aop = aaop;
997         else 
998                 aop = op->aop;
999         
1000         if (!aop)
1001                 return ;
1002         
1003         if (aop->freed)
1004                 goto dealloc; 
1005         
1006         aop->freed = 1;
1007         
1008         /* depending on the asmop type only three cases need work AOP_RO
1009         , AOP_R1 && AOP_STK */
1010 #if 0
1011         switch (aop->type) {
1012         case AOP_R0 :
1013                 if (_G.r0Pushed ) {
1014                         if (pop) {
1015                                 pic14_emitcode ("pop","ar0");     
1016                                 _G.r0Pushed--;
1017                         }
1018                 }
1019                 bitVectUnSetBit(ic->rUsed,R0_IDX);
1020                 break;
1021                 
1022         case AOP_R1 :
1023                 if (_G.r1Pushed ) {
1024                         if (pop) {
1025                                 pic14_emitcode ("pop","ar1");
1026                                 _G.r1Pushed--;
1027                         }
1028                 }
1029                 bitVectUnSetBit(ic->rUsed,R1_IDX);                      
1030                 break;
1031                 
1032         case AOP_STK :
1033                 {
1034                         int sz = aop->size;      
1035                         int stk = aop->aopu.aop_stk + aop->size;
1036                         bitVectUnSetBit(ic->rUsed,R0_IDX);
1037                         bitVectUnSetBit(ic->rUsed,R1_IDX);                
1038                         
1039                         getFreePtr(ic,&aop,FALSE);
1040                         
1041                         if (options.stack10bit)
1042                         {
1043                                 /* I'm not sure what to do here yet... */
1044                                 /* #STUB */
1045                                 fprintf(stderr, 
1046                                         "*** Warning: probably generating bad code for "
1047                                         "10 bit stack mode.\n");
1048                         }
1049                         
1050                         if (stk) {
1051                                 pic14_emitcode ("mov","a,_bp");
1052                                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1053                                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1054                         } else {
1055                                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1056                         }
1057                         
1058                         while (sz--) {
1059                                 pic14_emitcode("pop","acc");
1060                                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1061                                 if (!sz) break;
1062                                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1063                         }
1064                         op->aop = aop;
1065                         freeAsmop(op,NULL,ic,TRUE);
1066                         if (_G.r0Pushed) {
1067                                 pic14_emitcode("pop","ar0");
1068                                 _G.r0Pushed--;
1069                         }
1070                         
1071                         if (_G.r1Pushed) {
1072                                 pic14_emitcode("pop","ar1");
1073                                 _G.r1Pushed--;
1074                         }         
1075                 }
1076         }
1077 #endif
1078         
1079 dealloc:
1080         /* all other cases just dealloc */
1081         if (op ) {
1082                 op->aop = NULL;
1083                 if (IS_SYMOP(op)) {
1084                         OP_SYMBOL(op)->aop = NULL;      
1085                         /* if the symbol has a spill */
1086                         if (SPIL_LOC(op))
1087                                 SPIL_LOC(op)->aop = NULL;
1088                 }
1089         }
1090 }
1091
1092 /*-----------------------------------------------------------------*/
1093 /* aopGet - for fetching value of the aop                                                  */
1094 /*-----------------------------------------------------------------*/
1095 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1096 {
1097         char *s = buffer ;
1098         char *rs;
1099         
1100         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1101         /* offset is greater than
1102         size then zero */
1103         if (offset > (aop->size - 1) &&
1104                 aop->type != AOP_LIT)
1105                 return zero;
1106         
1107         /* depending on type */
1108         switch (aop->type) {
1109                 
1110         case AOP_R0:
1111         case AOP_R1:
1112                 DEBUGpic14_emitcode(";","%d",__LINE__);
1113                 /* if we need to increment it */           
1114                 while (offset > aop->coff) {            
1115                         pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);    
1116                         aop->coff++;
1117                 }
1118                 
1119                 while (offset < aop->coff) {
1120                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1121                         aop->coff--;
1122                 }
1123                 
1124                 aop->coff = offset ;
1125                 if (aop->paged) {
1126                         pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1127                         return (dname ? "acc" : "a");
1128                 }               
1129                 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1130                 rs = Safe_calloc(1,strlen(s)+1);
1131                 strcpy(rs,s);   
1132                 return rs;
1133                 
1134         case AOP_DPTR:
1135         case AOP_DPTR2:
1136                 DEBUGpic14_emitcode(";","%d",__LINE__);
1137                 if (aop->type == AOP_DPTR2)
1138                 {
1139                         genSetDPTR(1);
1140                 }
1141                 
1142                 while (offset > aop->coff) {
1143                         pic14_emitcode ("inc","dptr");
1144                         aop->coff++;
1145                 }
1146                 
1147                 while (offset < aop->coff) {            
1148                         pic14_emitcode("lcall","__decdptr");
1149                         aop->coff--;
1150                 }
1151                 
1152                 aop->coff = offset;
1153                 if (aop->code) {
1154                         pic14_emitcode("clr","a");
1155                         pic14_emitcode("movc","a,@a+dptr");
1156                 }
1157                 else {
1158                         pic14_emitcode("movx","a,@dptr");
1159                 }
1160                 
1161                 if (aop->type == AOP_DPTR2)
1162                 {
1163                         genSetDPTR(0);
1164                 }
1165                 
1166                 return (dname ? "acc" : "a");
1167                 
1168                 
1169         case AOP_IMMD:
1170                 if (bit16) 
1171                         sprintf (s,"%s",aop->aopu.aop_immd);
1172                 else
1173                         if (offset) 
1174                                 sprintf(s,"(%s >> %d)",
1175                                 aop->aopu.aop_immd,
1176                                 offset*8);
1177                         else
1178                                 sprintf(s,"%s",
1179                                 aop->aopu.aop_immd);
1180                         DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1181                         rs = Safe_calloc(1,strlen(s)+1);
1182                         strcpy(rs,s);   
1183                         return rs;
1184                         
1185         case AOP_DIR:
1186                 if (offset) {
1187                         sprintf(s,"(%s + %d)",
1188                                 aop->aopu.aop_dir,
1189                                 offset);
1190                         DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1191                 } else
1192                         sprintf(s,"%s",aop->aopu.aop_dir);
1193                 rs = Safe_calloc(1,strlen(s)+1);
1194                 strcpy(rs,s);   
1195                 return rs;
1196                 
1197         case AOP_REG:
1198                 //if (dname) 
1199                 //        return aop->aopu.aop_reg[offset]->dname;
1200                 //else
1201                 return aop->aopu.aop_reg[offset]->name;
1202                 
1203         case AOP_CRY:
1204                 //pic14_emitcode(";","%d",__LINE__);
1205                 return aop->aopu.aop_dir;
1206                 
1207         case AOP_ACC:
1208                 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1209                 return "AOP_accumulator_bug";
1210                 
1211         case AOP_LIT:
1212                 sprintf(s, "0x%02x", pic14aopLiteral (aop->aopu.aop_lit, offset));
1213                 rs = Safe_strdup(s);
1214                 return rs;
1215                 
1216         case AOP_STR:
1217                 aop->coff = offset ;
1218                 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1219                         dname)
1220                         return "acc";
1221                 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1222                 
1223                 return aop->aopu.aop_str[offset];
1224                 
1225         case AOP_PCODE:
1226                 {
1227                         pCodeOp *pcop = aop->aopu.pcop;
1228                         DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1229                         if(pcop->name) {
1230                                 if (offset) {
1231                                         DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1232                                         sprintf(s,"(%s+%d)", pcop->name,offset);
1233                                 } else {
1234                                         DEBUGpic14_emitcode(";","%s",pcop->name);
1235                                         sprintf(s,"%s", pcop->name);
1236                                 }
1237                         } else
1238                                 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1239                         
1240                 }
1241                 rs = Safe_calloc(1,strlen(s)+1);
1242                 strcpy(rs,s);   
1243                 return rs;
1244                 
1245   }
1246   
1247   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1248           "aopget got unsupported aop->type");
1249   exit(0);
1250 }
1251
1252
1253 /*-----------------------------------------------------------------*/
1254 /* popGetTempReg - create a new temporary pCodeOp                                  */
1255 /*-----------------------------------------------------------------*/
1256 pCodeOp *popGetTempReg(void)
1257 {
1258         
1259         pCodeOp *pcop;
1260         
1261         pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1262         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1263                 PCOR(pcop)->r->wasUsed=1;
1264                 PCOR(pcop)->r->isFree=0;
1265         }
1266         
1267         return pcop;
1268 }
1269
1270 /*-----------------------------------------------------------------*/
1271 /* popReleaseTempReg - create a new temporary pCodeOp                              */
1272 /*-----------------------------------------------------------------*/
1273 void popReleaseTempReg(pCodeOp *pcop)
1274 {
1275         
1276         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1277                 PCOR(pcop)->r->isFree = 1;
1278         
1279 }
1280 /*-----------------------------------------------------------------*/
1281 /* popGetLabel - create a new pCodeOp of type PO_LABEL                     */
1282 /*-----------------------------------------------------------------*/
1283 pCodeOp *popGetLabel(unsigned int key)
1284 {
1285         
1286         DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1287         
1288         if(key>(unsigned int)max_key)
1289                 max_key = key;
1290         
1291         return newpCodeOpLabel(NULL,key+100+labelOffset);
1292 }
1293
1294 /*-------------------------------------------------------------------*/
1295 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1296 /*-------------------------------------------------------------------*/
1297 pCodeOp *popGetHighLabel(unsigned int key)
1298 {
1299         pCodeOp *pcop;
1300         pcop = popGetLabel(key);
1301         PCOLAB(pcop)->offset = 1;
1302         return pcop;
1303 }
1304
1305 /*-----------------------------------------------------------------*/
1306 /* popGetLit - asm operator to pcode operator conversion                           */
1307 /*-----------------------------------------------------------------*/
1308 pCodeOp *popGetLit(unsigned int lit)
1309 {
1310         
1311         return newpCodeOpLit((unsigned char)lit);
1312 }
1313
1314 /*-----------------------------------------------------------------*/
1315 /* popGetImmd - asm operator to pcode immediate conversion                 */
1316 /*-----------------------------------------------------------------*/
1317 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1318 {
1319         
1320         return newpCodeOpImmd(name, offset,index, 0, is_func);
1321 }
1322
1323 extern set *externs;
1324
1325 /*-----------------------------------------------------------------*/
1326 /* popGetWithString - asm operator to pcode operator conversion                    */
1327 /*-----------------------------------------------------------------*/
1328 pCodeOp *popGetWithString(char *str, int isExtern)
1329 {
1330         pCodeOp *pcop;
1331         
1332         
1333         if(!str) {
1334                 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1335                 exit (1);
1336         }
1337         
1338         pcop = newpCodeOp(str,PO_STR);
1339         PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1340
1341         return pcop;
1342 }
1343
1344 pCodeOp *popGetExternal (char *str)
1345 {
1346         pCodeOp *pcop = popGetWithString (str, 1);
1347         
1348         if (str) {
1349           symbol *sym;
1350           bool found = 0;
1351
1352           for (sym = setFirstItem (externs); !found && sym; sym = setNextItem (externs))
1353           {
1354             if (!strcmp (str, sym->rname))
1355               found = 1;
1356           }
1357           
1358           if (!found)
1359           {
1360             sym = newSymbol(str, 0);
1361             strncpy(sym->rname, str, SDCC_NAME_MAX);
1362             addSet (&externs, sym);
1363           } // if
1364         }
1365         return pcop;
1366 }
1367
1368 /*-----------------------------------------------------------------*/
1369 /* popRegFromString -                                                                                      */
1370 /*-----------------------------------------------------------------*/
1371 pCodeOp *popRegFromString(char *str, int size, int offset)
1372 {
1373         
1374         pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1375         pcop->type = PO_DIR;
1376         
1377         DEBUGpic14_emitcode(";","%d",__LINE__);
1378         
1379         if(!str)
1380                 str = "BAD_STRING";
1381         
1382         pcop->name = Safe_calloc(1,strlen(str)+1);
1383         strcpy(pcop->name,str);
1384         
1385         //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1386         
1387         PCOR(pcop)->r = dirregWithName(pcop->name);
1388         if(PCOR(pcop)->r == NULL) {
1389                 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1390                 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1391                 DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1392         } else {
1393                 DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1394         }
1395         PCOR(pcop)->instance = offset;
1396         
1397         return pcop;
1398 }
1399
1400 /*-----------------------------------------------------------------*/
1401 /*-----------------------------------------------------------------*/
1402 pCodeOp *popRegFromIdx(int rIdx)
1403 {
1404         pCodeOp *pcop;
1405         
1406         DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1407                 __FUNCTION__,__LINE__,rIdx);
1408         
1409         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1410         
1411         PCOR(pcop)->rIdx = rIdx;
1412         PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1413         PCOR(pcop)->r->isFree = 0;
1414         PCOR(pcop)->r->wasUsed = 1;
1415         
1416         pcop->type = PCOR(pcop)->r->pc_type;
1417         
1418         
1419         return pcop;
1420 }
1421
1422 /*-----------------------------------------------------------------*/
1423 /* popGet - asm operator to pcode operator conversion                      */
1424 /*-----------------------------------------------------------------*/
1425 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1426 {
1427         //char *s = buffer ;
1428         //char *rs;
1429         
1430         pCodeOp *pcop;
1431         
1432         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1433         /* offset is greater than
1434         size then zero */
1435
1436         assert (aop);
1437
1438         /* XXX: still needed for BIT operands (AOP_CRY) */
1439         if (offset > (aop->size - 1) &&
1440                 aop->type != AOP_LIT)
1441                 return NULL;  //zero;
1442         
1443         /* depending on type */
1444         switch (aop->type) {
1445                 
1446         case AOP_R0:
1447         case AOP_R1:
1448         case AOP_DPTR:
1449         case AOP_DPTR2:
1450         case AOP_ACC:
1451                 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1452                 return NULL;
1453                 
1454         case AOP_IMMD:
1455                 DEBUGpic14_emitcode(";","%d",__LINE__);
1456                 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1457                 
1458         case AOP_DIR:
1459                 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1460 #if 0
1461                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1462                 pcop->type = PO_DIR;
1463                 
1464                 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1465                 strcpy(pcop->name,aop->aopu.aop_dir);   
1466                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1467                 if(PCOR(pcop)->r == NULL) {
1468                         //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1469                         PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1470                         DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1471                 } else {
1472                         DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1473                 }
1474                 PCOR(pcop)->instance = offset;
1475                 
1476                 return pcop;
1477 #endif
1478                 
1479         case AOP_REG:
1480                 {
1481                         int rIdx;
1482                         assert (offset < aop->size);
1483                         rIdx = aop->aopu.aop_reg[offset]->rIdx;
1484                         
1485                         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1486                         PCOR(pcop)->rIdx = rIdx;
1487                         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1488                         PCOR(pcop)->r->wasUsed=1;
1489                         PCOR(pcop)->r->isFree=0;
1490                         
1491                         PCOR(pcop)->instance = offset;
1492                         pcop->type = PCOR(pcop)->r->pc_type;
1493                         //rs = aop->aopu.aop_reg[offset]->name;
1494                         DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1495                         return pcop;
1496                 }
1497                 
1498         case AOP_CRY:
1499                 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1500                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1501                 //if(PCOR(pcop)->r == NULL)
1502                 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1503                 return pcop;
1504                 
1505         case AOP_LIT:
1506                 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1507                 
1508         case AOP_STR:
1509                 DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1510                 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1511                 /*
1512                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1513                 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1514                 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1515                 pcop->type = PCOR(pcop)->r->pc_type;
1516                 pcop->name = PCOR(pcop)->r->name;
1517                 
1518                   return pcop;
1519                 */
1520                 
1521         case AOP_PCODE:
1522                 pcop = NULL;
1523                 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1524                         __LINE__, 
1525                         ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1526                 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1527                 switch (aop->aopu.pcop->type)
1528                 {
1529                 case PO_IMMEDIATE:
1530                   pcop = pCodeOpCopy (aop->aopu.pcop);
1531                   /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1532                    * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1533                   PCOI(pcop)->index += offset;
1534                   //PCOI(pcop)->offset = 0;
1535                   break;
1536                 case PO_DIR:
1537                   pcop = pCodeOpCopy (aop->aopu.pcop);
1538                   PCOR(pcop)->instance = offset;
1539                   break;
1540                 default:
1541                   assert ( !"unhandled pCode type" );
1542                   break;
1543                 } // switch
1544                 return pcop;
1545         }
1546         
1547         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1548                 "popGet got unsupported aop->type");
1549         exit(0);
1550 }
1551
1552 /*-----------------------------------------------------------------*/
1553 /* popGetAddr - access the low/high word of a symbol (immediate)   */
1554 /*              (for non-PO_IMMEDIATEs this is the same as popGet) */
1555 /*-----------------------------------------------------------------*/
1556 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1557 {
1558   if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1559   {
1560     pCodeOp *pcop = aop->aopu.pcop;
1561     assert (offset <= GPTRSIZE);
1562
1563     /* special case: index >= 2 should return GPOINTER-style values */
1564     if (offset == 2)
1565     {
1566       pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1567       return pcop;
1568     }
1569     
1570     pcop = pCodeOpCopy (pcop);
1571     /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1572      * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1573     PCOI(pcop)->offset += offset;
1574     PCOI(pcop)->index += index;
1575     //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);
1576     return pcop;
1577   } else {
1578     return popGet (aop, offset + index);
1579   }
1580 }
1581
1582 /*-----------------------------------------------------------------*/
1583 /* aopPut - puts a string for a aop                                                        */
1584 /*-----------------------------------------------------------------*/
1585 void aopPut (asmop *aop, char *s, int offset)
1586 {
1587         char *d = buffer ;
1588         symbol *lbl ;
1589         
1590         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1591         
1592         if (aop->size && offset > ( aop->size - 1)) {
1593                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1594                         "aopPut got offset > aop->size");
1595                 exit(0);
1596         }
1597         
1598         /* will assign value to value */
1599         /* depending on where it is ofcourse */
1600         switch (aop->type) {
1601         case AOP_DIR:
1602                 if (offset) {
1603                         sprintf(d,"(%s + %d)",
1604                                 aop->aopu.aop_dir,offset);
1605                         fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1606                         
1607                 } else
1608                         sprintf(d,"%s",aop->aopu.aop_dir);
1609                 
1610                 if (strcmp(d,s)) {
1611                         DEBUGpic14_emitcode(";","%d",__LINE__);
1612                         if(strcmp(s,"W"))
1613                                 pic14_emitcode("movf","%s,w",s);
1614                         pic14_emitcode("movwf","%s",d);
1615                         
1616                         if(strcmp(s,"W")) {
1617                                 pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1618                                 if(offset >= aop->size) {
1619                                         emitpcode(POC_CLRF,popGet(aop,offset));
1620                                         break;
1621                                 } else {
1622                                         emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1623                                 }
1624                         }
1625                         emitpcode(POC_MOVWF,popGet(aop,offset));
1626                 
1627                 }
1628                 break;
1629                 
1630         case AOP_REG:
1631                 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1632                         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1633                         /*
1634                         if (*s == '@'             ||
1635                         strcmp(s,"r0") == 0 ||
1636                         strcmp(s,"r1") == 0 ||
1637                         strcmp(s,"r2") == 0 ||
1638                         strcmp(s,"r3") == 0 ||
1639                         strcmp(s,"r4") == 0 ||
1640                         strcmp(s,"r5") == 0 ||
1641                         strcmp(s,"r6") == 0 || 
1642                         strcmp(s,"r7") == 0 )
1643                         pic14_emitcode("mov","%s,%s  ; %d",
1644                         aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1645                         else
1646                         */
1647                         
1648                         if(strcmp(s,"W")==0 )
1649                                 pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1650                         
1651                         pic14_emitcode("movwf","%s",
1652                                 aop->aopu.aop_reg[offset]->name);
1653                         
1654                         if(strcmp(s,zero)==0) {
1655                                 emitpcode(POC_CLRF,popGet(aop,offset));
1656                                 
1657                         } else if(strcmp(s,"W")==0) {
1658                                 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1659                                 pcop->type = PO_GPR_REGISTER;
1660                                 
1661                                 PCOR(pcop)->rIdx = -1;
1662                                 PCOR(pcop)->r = NULL;
1663                                 
1664                                 DEBUGpic14_emitcode(";","%d",__LINE__);
1665                                 pcop->name = Safe_strdup(s);
1666                                 emitpcode(POC_MOVFW,pcop);
1667                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1668                         } else if(strcmp(s,one)==0) {
1669                                 emitpcode(POC_CLRF,popGet(aop,offset));
1670                                 emitpcode(POC_INCF,popGet(aop,offset));
1671                         } else {
1672                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1673                         }
1674                 }
1675                 break;
1676                 
1677         case AOP_DPTR:
1678         case AOP_DPTR2:
1679                 
1680                 if (aop->type == AOP_DPTR2)
1681                 {
1682                         genSetDPTR(1);
1683                 }
1684                 
1685                 if (aop->code) {
1686                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1687                                 "aopPut writting to code space");
1688                         exit(0);
1689                 }
1690                 
1691                 while (offset > aop->coff) {
1692                         aop->coff++;
1693                         pic14_emitcode ("inc","dptr");
1694                 }
1695                 
1696                 while (offset < aop->coff) {
1697                         aop->coff-- ;
1698                         pic14_emitcode("lcall","__decdptr");
1699                 }
1700                 
1701                 aop->coff = offset;
1702                 
1703                 /* if not in accumulater */
1704                 MOVA(s);
1705                 
1706                 pic14_emitcode ("movx","@dptr,a");
1707                 
1708                 if (aop->type == AOP_DPTR2)
1709                 {
1710                         genSetDPTR(0);
1711                 }
1712                 break;
1713                 
1714         case AOP_R0:
1715         case AOP_R1:
1716                 while (offset > aop->coff) {
1717                         aop->coff++;
1718                         pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1719                 }
1720                 while (offset < aop->coff) {
1721                         aop->coff-- ;
1722                         pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1723                 }
1724                 aop->coff = offset;
1725                 
1726                 if (aop->paged) {
1727                         MOVA(s);                         
1728                         pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1729                         
1730                 } else
1731                         if (*s == '@') {
1732                                 MOVA(s);
1733                                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1734                         } else
1735                                 if (strcmp(s,"r0") == 0 ||
1736                                         strcmp(s,"r1") == 0 ||
1737                                         strcmp(s,"r2") == 0 ||
1738                                         strcmp(s,"r3") == 0 ||
1739                                         strcmp(s,"r4") == 0 ||
1740                                         strcmp(s,"r5") == 0 ||
1741                                         strcmp(s,"r6") == 0 || 
1742                                         strcmp(s,"r7") == 0 ) {
1743                                         char buffer[10];
1744                                         sprintf(buffer,"a%s",s);
1745                                         pic14_emitcode("mov","@%s,%s",
1746                                                 aop->aopu.aop_ptr->name,buffer);
1747                                 } else
1748                                         pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1749                                 
1750                                 break;
1751                                 
1752         case AOP_STK:
1753                 if (strcmp(s,"a") == 0)
1754                         pic14_emitcode("push","acc");
1755                 else
1756                         pic14_emitcode("push","%s",s);
1757                 
1758                 break;
1759                 
1760         case AOP_CRY:
1761                 /* if bit variable */
1762                 if (!aop->aopu.aop_dir) {
1763                         pic14_emitcode("clr","a");
1764                         pic14_emitcode("rlc","a");
1765                 } else {
1766                         if (s == zero) 
1767                                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1768                         else
1769                                 if (s == one)
1770                                         pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1771                                 else
1772                                         if (!strcmp(s,"c"))
1773                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1774                                         else {
1775                                                 lbl = newiTempLabel(NULL);
1776                                                 
1777                                                 if (strcmp(s,"a")) {
1778                                                         MOVA(s);
1779                                                 }
1780                                                 pic14_emitcode("clr","c");
1781                                                 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1782                                                 pic14_emitcode("cpl","c");
1783                                                 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1784                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1785                                         }
1786                 }
1787                 break;
1788                 
1789         case AOP_STR:
1790                 aop->coff = offset;
1791                 if (strcmp(aop->aopu.aop_str[offset],s))
1792                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1793                 break;
1794                 
1795         case AOP_ACC:
1796                 aop->coff = offset;
1797                 if (!offset && (strcmp(s,"acc") == 0))
1798                         break;
1799                 
1800                 if (strcmp(aop->aopu.aop_str[offset],s))
1801                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1802                 break;
1803                 
1804         default :
1805                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1806                         "aopPut got unsupported aop->type");
1807                 exit(0);
1808         }
1809         
1810 }
1811
1812 /*-----------------------------------------------------------------*/
1813 /* mov2w_op - generate either a MOVLW or MOVFW based operand type  */
1814 /*-----------------------------------------------------------------*/
1815 static void mov2w_op (operand *op, int offset)
1816 {
1817         assert (op);
1818         FENTRY;
1819
1820         /* for PO_IMMEDIATEs: use address or value? */
1821         if (op_isLitLike (op))
1822         {
1823                 /* access address of op */
1824                 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1825                 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1826                 {
1827                         if (offset == GPTRSIZE-1)
1828                                 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1829                         else
1830                                 emitpcode (POC_MOVLW, popGetLit (0));
1831                 }
1832                 else
1833                         emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1834         } else {
1835                 /* access value stored in op */
1836                 mov2w (AOP(op), offset);
1837         }
1838 }
1839
1840
1841 /*-----------------------------------------------------------------*/
1842 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1843 /*-----------------------------------------------------------------*/
1844 void mov2w (asmop *aop, int offset)
1845 {
1846         
1847         if(!aop)
1848                 return;
1849         
1850         DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1851         
1852         if ( aop_isLitLike (aop) )
1853                 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1854         else
1855                 emitpcode(POC_MOVFW,popGet(aop,offset));
1856         
1857 }
1858
1859 static void movwf (asmop *op, int offset)
1860 {
1861         emitpcode (POC_MOVWF, popGet(op, offset));
1862 }
1863
1864 static pCodeOp *get_argument_pcop (int idx)
1865 {
1866         assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1867         return popRegFromIdx (Gstack_base_addr - (idx - 1));
1868 }
1869
1870 static pCodeOp *get_return_val_pcop (int offset)
1871 {
1872         assert (offset > 0 && "the most significant byte is returned via WREG");
1873         return popRegFromIdx (Gstack_base_addr - (offset - 1));
1874 }
1875
1876 static void pass_argument (operand *op, int offset, int idx)
1877 {
1878         if (op)
1879                 mov2w_op (op, offset);
1880         if (idx != 0)
1881                 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1882 }
1883
1884 static void get_returnvalue (operand *op, int offset, int idx)
1885 {
1886         if (idx != 0)
1887                 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1888         movwf(AOP(op), offset);
1889 }
1890
1891 static void call_libraryfunc (char *name)
1892 {
1893   /* library code might reside in different page... */
1894   emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1895   /* call the library function */
1896   emitpcode (POC_CALL, popGetExternal (name));
1897   /* might return from different page... */
1898   emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1899 }
1900 #if 0
1901 /*-----------------------------------------------------------------*/
1902 /* reAdjustPreg - points a register back to where it should        */
1903 /*-----------------------------------------------------------------*/
1904 static void reAdjustPreg (asmop *aop)
1905 {
1906         int size ;
1907         
1908         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1909         aop->coff = 0;
1910         if ((size = aop->size) <= 1)
1911                 return ;
1912         size-- ;
1913         switch (aop->type) {
1914         case AOP_R0 :
1915         case AOP_R1 :
1916                 while (size--)
1917                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1918                 break;                  
1919         case AOP_DPTR :
1920         case AOP_DPTR2:
1921                 if (aop->type == AOP_DPTR2)
1922                 {
1923                         genSetDPTR(1);
1924                 } 
1925                 while (size--)
1926                 {
1927                         pic14_emitcode("lcall","__decdptr");
1928                 }
1929                 
1930                 if (aop->type == AOP_DPTR2)
1931                 {
1932                         genSetDPTR(0);
1933                 }
1934                 break;
1935                 
1936         }
1937         
1938 }
1939 #endif
1940
1941
1942 #if 0
1943 /*-----------------------------------------------------------------*/
1944 /* opIsGptr: returns non-zero if the passed operand is             */
1945 /* a generic pointer type.                                         */
1946 /*-----------------------------------------------------------------*/ 
1947 static int opIsGptr(operand *op)
1948 {
1949         sym_link *type = operandType(op);
1950         
1951         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1952         if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1953         {
1954                 return 1;
1955         }
1956         return 0;          
1957 }
1958 #endif
1959
1960 /*-----------------------------------------------------------------*/
1961 /* pic14_getDataSize - get the operand data size                   */
1962 /*-----------------------------------------------------------------*/
1963 int pic14_getDataSize(operand *op)
1964 {
1965         int size;
1966         
1967         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1968         
1969 #if 0
1970         size = getSize(OP_SYM_ETYPE(op));
1971         return size;
1972         //return AOP_SIZE(op);
1973         
1974         // tsd- in the pic port, the genptr size is 1, so this code here
1975         // fails. ( in the 8051 port, the size was 4).
1976 #else
1977         size = AOP_SIZE(op);
1978         if (IS_GENPTR(OP_SYM_TYPE(op)))
1979         {
1980                 sym_link *type = operandType(op);
1981                 if (IS_GENPTR(type))
1982                 {
1983                         /* generic pointer; arithmetic operations
1984                         * should ignore the high byte (pointer type).
1985                         */
1986                         size--;
1987                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1988                 }
1989         }
1990         return size;
1991 #endif
1992 }
1993
1994 /*-----------------------------------------------------------------*/
1995 /* pic14_outAcc - output Acc                                       */
1996 /*-----------------------------------------------------------------*/
1997 void pic14_outAcc(operand *result)
1998 {
1999         int size,offset;
2000         DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2001         DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
2002         
2003         
2004         size = pic14_getDataSize(result);
2005         if(size){
2006                 emitpcode(POC_MOVWF,popGet(AOP(result),0));
2007                 size--;
2008                 offset = 1;
2009                 /* unsigned or positive */
2010                 while(size--)
2011                         emitpcode(POC_CLRF,popGet(AOP(result),offset++));
2012         }
2013         
2014 }
2015
2016 /*-----------------------------------------------------------------*/
2017 /* pic14_outBitC - output a bit C                                  */
2018 /*-----------------------------------------------------------------*/
2019 void pic14_outBitC(operand *result)
2020 {
2021         
2022         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2023         /* if the result is bit */
2024         if (AOP_TYPE(result) == AOP_CRY) 
2025                 aopPut(AOP(result),"c",0);
2026         else {
2027                 pic14_emitcode("clr","a  ; %d", __LINE__);
2028                 pic14_emitcode("rlc","a");
2029                 pic14_outAcc(result);
2030         }
2031 }
2032
2033 /*-----------------------------------------------------------------*/
2034 /* pic14_toBoolean - emit code for orl a,operator(sizeop)          */
2035 /*-----------------------------------------------------------------*/
2036 void pic14_toBoolean(operand *oper)
2037 {
2038         int size = AOP_SIZE(oper);
2039         int offset = 0;
2040         
2041         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2042
2043         assert (size > 0);
2044
2045         if (size == 1) {
2046                 /* MOVFW does not load the flags... */
2047                 if (AOP_TYPE(oper) == AOP_ACC) {
2048                         emitpcode(POC_IORLW, popGetLit(0));
2049                         offset = 1;
2050                 } else {
2051                         emitpcode(POC_MOVLW, popGetLit(0));
2052                         offset = 0;
2053                 }
2054         } else {
2055                 if ( AOP_TYPE(oper) != AOP_ACC) {
2056                         emitpcode(POC_MOVFW,popGet(AOP(oper),0));
2057                         offset = 1;
2058                 }
2059         }
2060         
2061         while (offset < size) {
2062                 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
2063         }
2064         /* Z is set iff (oper == 0) */
2065 }
2066
2067
2068 /*-----------------------------------------------------------------*/
2069 /* genNot - generate code for ! operation                          */
2070 /*-----------------------------------------------------------------*/
2071 static void genNot (iCode *ic)
2072 {
2073         //symbol *tlbl;
2074         int size;
2075
2076         FENTRY;
2077         
2078         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2079         /* assign asmOps to operand & result */
2080         aopOp (IC_LEFT(ic),ic,FALSE);
2081         aopOp (IC_RESULT(ic),ic,TRUE);
2082         
2083         DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2084         /* if in bit space then a special case */
2085         if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2086                 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2087                         emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2088                         emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2089                 } else {
2090                         emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2091                         emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2092                         emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2093                 }
2094                 goto release;
2095         }
2096         
2097         size = AOP_SIZE(IC_LEFT(ic));
2098         mov2w (AOP(IC_LEFT(ic)),0);
2099         while (--size > 0)
2100         {
2101           if (op_isLitLike (IC_LEFT(ic)))
2102             emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2103           else
2104             emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2105         }
2106         emitpcode(POC_MOVLW, popGetLit (0));
2107         emitSKPNZ;
2108         emitpcode(POC_MOVLW, popGetLit (1));
2109         movwf(AOP(IC_RESULT(ic)), 0);
2110
2111         for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2112         {
2113           emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2114         }
2115         goto release;
2116         
2117 release:        
2118         /* release the aops */
2119         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2120         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2121 }
2122
2123
2124 /*-----------------------------------------------------------------*/
2125 /* genCpl - generate code for complement                                                   */
2126 /*-----------------------------------------------------------------*/
2127 static void genCpl (iCode *ic)
2128 {
2129         operand *left, *result;
2130         int size, offset=0;  
2131         
2132         FENTRY;
2133         
2134         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2135         aopOp((left = IC_LEFT(ic)),ic,FALSE);
2136         aopOp((result=IC_RESULT(ic)),ic,TRUE);
2137         
2138         /* if both are in bit space then 
2139         a special case */
2140         if (AOP_TYPE(result) == AOP_CRY &&
2141                 AOP_TYPE(left) == AOP_CRY ) { 
2142                 
2143                 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir); 
2144                 pic14_emitcode("cpl","c"); 
2145                 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir); 
2146                 goto release; 
2147         } 
2148         
2149         size = AOP_SIZE(result);
2150         if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2151         while (size--) {
2152                 
2153                 if(AOP_TYPE(left) == AOP_ACC) 
2154                         emitpcode(POC_XORLW, popGetLit(0xff));
2155                 else
2156                         emitpcode(POC_COMFW,popGet(AOP(left),offset));
2157                 
2158                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2159                 offset++;
2160         }
2161         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2162         
2163         
2164 release:
2165         /* release the aops */
2166         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2167         freeAsmop(result,NULL,ic,TRUE);
2168 }
2169
2170 /*-----------------------------------------------------------------*/
2171 /* genUminusFloat - unary minus for floating points                        */
2172 /*-----------------------------------------------------------------*/
2173 static void genUminusFloat(operand *op,operand *result)
2174 {
2175         int size ,offset =0 ;
2176         char *l;
2177         
2178         FENTRY;
2179
2180         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2181         /* for this we just need to flip the 
2182         first it then copy the rest in place */
2183         size = AOP_SIZE(op) - 1;
2184         l = aopGet(AOP(op),3,FALSE,FALSE);
2185         
2186         MOVA(l);          
2187         
2188         pic14_emitcode("cpl","acc.7");
2189         aopPut(AOP(result),"a",3);      
2190         
2191         while(size--) {
2192                 aopPut(AOP(result),
2193                         aopGet(AOP(op),offset,FALSE,FALSE),
2194                         offset);
2195                 offset++;
2196         }                
2197 }
2198
2199 /*-----------------------------------------------------------------*/
2200 /* genUminus - unary minus code generation                                                 */
2201 /*-----------------------------------------------------------------*/
2202 static void genUminus (iCode *ic)
2203 {
2204         int size, i;
2205         sym_link *optype, *rtype;
2206         
2207         FENTRY;
2208         
2209         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2210         /* assign asmops */
2211         aopOp(IC_LEFT(ic),ic,FALSE);
2212         aopOp(IC_RESULT(ic),ic,TRUE);
2213         
2214         /* if both in bit space then special
2215         case */
2216         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2217                 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2218                 
2219                 emitpcode(POC_BCF,       popGet(AOP(IC_RESULT(ic)),0));
2220                 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2221                 emitpcode(POC_BSF,       popGet(AOP(IC_RESULT(ic)),0));
2222                 
2223                 goto release; 
2224         } 
2225         
2226         optype = operandType(IC_LEFT(ic));
2227         rtype = operandType(IC_RESULT(ic));
2228         
2229         /* if float then do float stuff */
2230         if (IS_FLOAT(optype)) {
2231                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2232                 goto release;
2233         }
2234         
2235         /* otherwise subtract from zero by taking the 2's complement */
2236         size = AOP_SIZE(IC_LEFT(ic));
2237         
2238         for(i=0; i<size; i++) {
2239                 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2240                         emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
2241                 else {
2242                         emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2243                         emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2244                 }
2245         }
2246         
2247         emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
2248         for(i=1; i<size; i++) {
2249                 emitSKPNZ;
2250                 emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
2251         }
2252         
2253 release:
2254         /* release the aops */
2255         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2256         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);  
2257 }
2258
2259 /*-----------------------------------------------------------------*/
2260 /* saveRegisters - will look for a call and save the registers     */
2261 /*-----------------------------------------------------------------*/
2262 static void saveRegisters(iCode *lic) 
2263 {
2264         int i;
2265         iCode *ic;
2266         bitVect *rsave;
2267         sym_link *dtype;
2268         
2269         FENTRY;
2270
2271         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2272         /* look for call */
2273         for (ic = lic ; ic ; ic = ic->next) 
2274                 if (ic->op == CALL || ic->op == PCALL)
2275                         break;
2276                 
2277                 if (!ic) {
2278                         fprintf(stderr,"found parameter push with no function call\n");
2279                         return ;
2280                 }
2281                 
2282                 /* if the registers have been saved already then
2283                 do nothing */
2284                 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2285                         return ;
2286                 
2287                         /* find the registers in use at this time 
2288                 and push them away to safety */
2289                 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2290                         ic->rUsed);
2291                 
2292                 ic->regsSaved = 1;
2293                 if (options.useXstack) {
2294                         if (bitVectBitValue(rsave,R0_IDX))
2295                                 pic14_emitcode("mov","b,r0");
2296                         pic14_emitcode("mov","r0,%s",spname);
2297                         for (i = 0 ; i < pic14_nRegs ; i++) {
2298                                 if (bitVectBitValue(rsave,i)) {
2299                                         if (i == R0_IDX)
2300                                                 pic14_emitcode("mov","a,b");
2301                                         else
2302                                                 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2303                                         pic14_emitcode("movx","@r0,a");
2304                                         pic14_emitcode("inc","r0");
2305                                 }
2306                         }
2307                         pic14_emitcode("mov","%s,r0",spname);
2308                         if (bitVectBitValue(rsave,R0_IDX))
2309                                 pic14_emitcode("mov","r0,b");     
2310                 }// else
2311                 //for (i = 0 ; i < pic14_nRegs ; i++) {
2312                 //        if (bitVectBitValue(rsave,i))
2313                 //      pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2314                 //}
2315                 
2316                 dtype = operandType(IC_LEFT(ic));
2317                 if (currFunc && dtype && 
2318                         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2319                         IFFUNC_ISISR(currFunc->type) &&
2320                         !ic->bankSaved) 
2321                         
2322                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2323                 
2324 }
2325 /*-----------------------------------------------------------------*/
2326 /* unsaveRegisters - pop the pushed registers                                      */
2327 /*-----------------------------------------------------------------*/
2328 static void unsaveRegisters (iCode *ic)
2329 {
2330         int i;
2331         bitVect *rsave;
2332         
2333         FENTRY;
2334
2335         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2336         /* find the registers in use at this time 
2337         and push them away to safety */
2338         rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2339                 ic->rUsed);
2340         
2341         if (options.useXstack) {
2342                 pic14_emitcode("mov","r0,%s",spname); 
2343                 for (i =  pic14_nRegs ; i >= 0 ; i--) {
2344                         if (bitVectBitValue(rsave,i)) {
2345                                 pic14_emitcode("dec","r0");
2346                                 pic14_emitcode("movx","a,@r0");
2347                                 if (i == R0_IDX)
2348                                         pic14_emitcode("mov","b,a");
2349                                 else
2350                                         pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2351                         }       
2352                         
2353                 }
2354                 pic14_emitcode("mov","%s,r0",spname);
2355                 if (bitVectBitValue(rsave,R0_IDX))
2356                         pic14_emitcode("mov","r0,b");
2357         } //else
2358         //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2359         //      if (bitVectBitValue(rsave,i))
2360         //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2361         //}
2362         
2363 }  
2364
2365
2366 /*-----------------------------------------------------------------*/
2367 /* pushSide -                            */
2368 /*-----------------------------------------------------------------*/
2369 static void pushSide(operand * oper, int size)
2370 {
2371 #if 0
2372         int offset = 0;
2373         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2374         while (size--) {
2375                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2376                 if (AOP_TYPE(oper) != AOP_REG &&
2377                         AOP_TYPE(oper) != AOP_DIR &&
2378                         strcmp(l,"a") ) {
2379                         pic14_emitcode("mov","a,%s",l);
2380                         pic14_emitcode("push","acc");
2381                 } else
2382                         pic14_emitcode("push","%s",l);
2383         }
2384 #endif
2385 }
2386
2387 /*-----------------------------------------------------------------*/
2388 /* assignResultValue -                           */
2389 /*-----------------------------------------------------------------*/
2390 static void assignResultValue(operand * oper)
2391 {
2392         int size = AOP_SIZE(oper);
2393         int offset = 0;
2394         
2395         FENTRY;
2396
2397         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2398         
2399         DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2400         
2401         /* assign MSB first (passed via WREG) */
2402         while (size--) {
2403                 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2404                 GpsuedoStkPtr++;
2405         }
2406 }
2407
2408
2409 /*-----------------------------------------------------------------*/
2410 /* genIpush - genrate code for pushing this gets a little complex  */
2411 /*-----------------------------------------------------------------*/
2412 static void genIpush (iCode *ic)
2413 {
2414         FENTRY;
2415         
2416         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2417 #if 0
2418         int size, offset = 0 ;
2419         char *l;
2420         
2421         
2422         /* if this is not a parm push : ie. it is spill push 
2423         and spill push is always done on the local stack */
2424         if (!ic->parmPush) {
2425                 
2426                 /* and the item is spilt then do nothing */
2427                 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2428                         return ;
2429                 
2430                 aopOp(IC_LEFT(ic),ic,FALSE);
2431                 size = AOP_SIZE(IC_LEFT(ic));
2432                 /* push it on the stack */
2433                 while(size--) {
2434                         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2435                         if (*l == '#') {
2436                                 MOVA(l);
2437                                 l = "acc";
2438                         }
2439                         pic14_emitcode("push","%s",l);
2440                 }
2441                 return ;                
2442         }
2443         
2444         /* this is a paramter push: in this case we call
2445         the routine to find the call and save those
2446         registers that need to be saved */   
2447         saveRegisters(ic);
2448         
2449         /* then do the push */
2450         aopOp(IC_LEFT(ic),ic,FALSE);
2451         
2452         
2453         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2454         size = AOP_SIZE(IC_LEFT(ic));
2455         
2456         while (size--) {
2457                 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2458                 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2459                         AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2460                         strcmp(l,"a") ) {
2461                         pic14_emitcode("mov","a,%s",l);
2462                         pic14_emitcode("push","acc");
2463                 } else
2464                         pic14_emitcode("push","%s",l);
2465         }         
2466         
2467         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2468 #endif
2469 }
2470
2471 /*-----------------------------------------------------------------*/
2472 /* genIpop - recover the registers: can happen only for spilling   */
2473 /*-----------------------------------------------------------------*/
2474 static void genIpop (iCode *ic)
2475 {
2476         FENTRY;
2477
2478         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2479         assert (!"genIpop -- unimplemented");
2480 #if 0
2481         int size,offset ;
2482         
2483         
2484         /* if the temp was not pushed then */
2485         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2486                 return ;
2487         
2488         aopOp(IC_LEFT(ic),ic,FALSE);
2489         size = AOP_SIZE(IC_LEFT(ic));
2490         offset = (size-1);
2491         while (size--) 
2492                 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2493                 FALSE,TRUE));
2494         
2495         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2496 #endif
2497 }
2498
2499 /*-----------------------------------------------------------------*/
2500 /* unsaverbank - restores the resgister bank from stack                    */
2501 /*-----------------------------------------------------------------*/
2502 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2503 {
2504         FENTRY;
2505
2506         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2507 #if 0
2508         int i;
2509         asmop *aop ;
2510         regs *r = NULL;
2511         
2512         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2513         if (popPsw) {
2514                 if (options.useXstack) {
2515                         aop = newAsmop(0);
2516                         r = getFreePtr(ic,&aop,FALSE);
2517                         
2518                         
2519                         pic14_emitcode("mov","%s,_spx",r->name);
2520                         pic14_emitcode("movx","a,@%s",r->name);
2521                         pic14_emitcode("mov","psw,a");
2522                         pic14_emitcode("dec","%s",r->name);
2523                         
2524                 }else
2525                         pic14_emitcode ("pop","psw");
2526         }
2527         
2528         for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2529                 if (options.useXstack) {           
2530                         pic14_emitcode("movx","a,@%s",r->name);
2531                         //pic14_emitcode("mov","(%s+%d),a",
2532                         //         regspic14[i].base,8*bank+regspic14[i].offset);
2533                         pic14_emitcode("dec","%s",r->name);
2534                         
2535                 } else 
2536                         pic14_emitcode("pop",""); //"(%s+%d)",
2537                 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2538         }
2539         
2540         if (options.useXstack) {
2541                 
2542                 pic14_emitcode("mov","_spx,%s",r->name);
2543                 freeAsmop(NULL,aop,ic,TRUE);
2544                 
2545         }
2546 #endif 
2547 }
2548
2549 /*-----------------------------------------------------------------*/
2550 /* saverbank - saves an entire register bank on the stack                  */
2551 /*-----------------------------------------------------------------*/
2552 static void saverbank (int bank, iCode *ic, bool pushPsw)
2553 {
2554         FENTRY;
2555
2556         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2557 #if 0
2558         int i;
2559         asmop *aop ;
2560         regs *r = NULL;
2561         
2562         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2563         if (options.useXstack) {
2564                 
2565                 aop = newAsmop(0);
2566                 r = getFreePtr(ic,&aop,FALSE);  
2567                 pic14_emitcode("mov","%s,_spx",r->name);
2568                 
2569         }
2570         
2571         for (i = 0 ; i < pic14_nRegs ;i++) {
2572                 if (options.useXstack) {
2573                         pic14_emitcode("inc","%s",r->name);
2574                         //pic14_emitcode("mov","a,(%s+%d)",
2575                         //               regspic14[i].base,8*bank+regspic14[i].offset);
2576                         pic14_emitcode("movx","@%s,a",r->name);                 
2577                 } else 
2578                         pic14_emitcode("push","");// "(%s+%d)",
2579                 //regspic14[i].base,8*bank+regspic14[i].offset);
2580         }
2581         
2582         if (pushPsw) {
2583                 if (options.useXstack) {
2584                         pic14_emitcode("mov","a,psw");
2585                         pic14_emitcode("movx","@%s,a",r->name); 
2586                         pic14_emitcode("inc","%s",r->name);
2587                         pic14_emitcode("mov","_spx,%s",r->name);                 
2588                         freeAsmop (NULL,aop,ic,TRUE);
2589                         
2590                 } else
2591                         pic14_emitcode("push","psw");
2592                 
2593                 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2594         }
2595         ic->bankSaved = 1;
2596 #endif
2597 }
2598
2599 /*-----------------------------------------------------------------*/
2600 /* genCall - generates a call statement                                                    */
2601 /*-----------------------------------------------------------------*/
2602 static void genCall (iCode *ic)
2603 {
2604         sym_link *dtype;         
2605         symbol *sym;
2606         char *name;
2607         int isExtern;
2608         
2609         FENTRY;
2610
2611         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2612         
2613         /* if caller saves & we have not saved then */
2614         if (!ic->regsSaved)
2615                 saveRegisters(ic);
2616         
2617                 /* if we are calling a function that is not using
2618                 the same register bank then we need to save the
2619         destination registers on the stack */
2620         dtype = operandType(IC_LEFT(ic));
2621         if (currFunc && dtype && 
2622                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2623                 IFFUNC_ISISR(currFunc->type) &&
2624                 !ic->bankSaved) 
2625                 
2626                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2627         
2628         /* if send set is not empty the assign */
2629         if (_G.sendSet) {
2630                 iCode *sic;
2631                 /* For the Pic port, there is no data stack.
2632                 * So parameters passed to functions are stored
2633                 * in registers. (The pCode optimizer will get
2634                 * rid of most of these :).
2635                 */
2636                 int psuedoStkPtr=-1;
2637                 int firstTimeThruLoop = 1;
2638                 
2639                 _G.sendSet = reverseSet(_G.sendSet);
2640                 
2641                 /* First figure how many parameters are getting passed */
2642                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2643                 sic = setNextItem(_G.sendSet)) {
2644                         
2645                         aopOp(IC_LEFT(sic),sic,FALSE);
2646                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2647                         freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2648                 }
2649                 
2650                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2651                 sic = setNextItem(_G.sendSet)) {
2652                         int size, offset = 0;
2653                         
2654                         aopOp(IC_LEFT(sic),sic,FALSE);
2655                         size = AOP_SIZE(IC_LEFT(sic));
2656                         
2657                         while (size--) {
2658                                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2659                                         AopType(AOP_TYPE(IC_LEFT(sic))));
2660                                 
2661                                 if(!firstTimeThruLoop) {
2662                                         /* If this is not the first time we've been through the loop
2663                                         * then we need to save the parameter in a temporary
2664                                         * register. The last byte of the last parameter is
2665                                         * passed in W. */
2666                                         emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2667                                         
2668                                 }
2669                                 firstTimeThruLoop=0;
2670                                 
2671                                 mov2w_op (IC_LEFT(sic),  offset);
2672                                 offset++;
2673                         }
2674                         freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2675                 }
2676                 _G.sendSet = NULL;
2677         }
2678         /* make the call */
2679         sym = OP_SYMBOL(IC_LEFT(ic));
2680         name = sym->rname[0] ? sym->rname : sym->name;
2681         isExtern = IS_EXTERN(sym->etype);
2682         if (isExtern) {
2683                 emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2684         }
2685         emitpcode(POC_CALL,popGetWithString(name,isExtern));
2686         if (isExtern) {
2687                 emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel to restore PCLATH before next goto or call instruction */
2688         }
2689         GpsuedoStkPtr=0;
2690         /* if we need assign a result value */
2691         if ((IS_ITEMP(IC_RESULT(ic)) && 
2692                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2693                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2694                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2695                 
2696                 _G.accInUse++;
2697                 aopOp(IC_RESULT(ic),ic,FALSE);
2698                 _G.accInUse--;
2699                 
2700                 assignResultValue(IC_RESULT(ic));
2701                 
2702                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2703                         AopType(AOP_TYPE(IC_RESULT(ic))));
2704                 
2705                 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2706         }
2707         
2708         /* if register bank was saved then pop them */
2709         if (ic->bankSaved)
2710                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2711         
2712         /* if we hade saved some registers then unsave them */
2713         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2714                 unsaveRegisters (ic);
2715         
2716         
2717 }
2718
2719 /*-----------------------------------------------------------------*/
2720 /* genPcall - generates a call by pointer statement                        */
2721 /*-----------------------------------------------------------------*/
2722 static void genPcall (iCode *ic)
2723 {
2724         sym_link *dtype;
2725         symbol *albl = newiTempLabel(NULL);
2726         symbol *blbl = newiTempLabel(NULL);
2727         PIC_OPCODE poc;
2728         pCodeOp *pcop;
2729         operand *left;
2730         
2731         FENTRY;
2732
2733         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2734         /* if caller saves & we have not saved then */
2735         if (!ic->regsSaved)
2736                 saveRegisters(ic);
2737         
2738                 /* if we are calling a function that is not using
2739                 the same register bank then we need to save the
2740         destination registers on the stack */
2741         dtype = operandType(IC_LEFT(ic));
2742         if (currFunc && dtype && 
2743                 IFFUNC_ISISR(currFunc->type) &&
2744                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2745                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2746         
2747         left = IC_LEFT(ic);
2748         aopOp(left,ic,FALSE);
2749         DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2750         
2751         poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2752         
2753         pushSide(IC_LEFT(ic), FPTRSIZE);
2754         
2755         /* if send set is not empty, assign parameters */
2756         if (_G.sendSet) {
2757                 
2758                 DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2759                 /* no way to pass args - W always gets used to make the call */
2760         }
2761         /* first idea - factor out a common helper function and call it.
2762         But don't know how to get it generated only once in its own block
2763         
2764         if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2765                 char *rname;
2766                 char *buffer;
2767                 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2768                 DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2769                 buffer = Safe_calloc(1,strlen(rname)+16);
2770                 sprintf(buffer, "%s_goto_helper", rname);
2771                 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2772                 free(buffer);
2773         }
2774         */
2775         emitpcode(POC_CALL,popGetLabel(albl->key));
2776         pcop = popGetLabel(blbl->key);
2777         emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2778         emitpcode(POC_GOTO,pcop);
2779         emitpLabel(albl->key);
2780         
2781         emitpcode(poc,popGetAddr(AOP(left),1,0));
2782         emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2783         emitpcode(poc,popGetAddr(AOP(left),0,0));
2784         emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2785         
2786         emitpLabel(blbl->key);
2787         
2788         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2789         
2790         /* if we need to assign a result value */
2791         if ((IS_ITEMP(IC_RESULT(ic)) &&
2792                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2793                 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2794                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2795                 
2796                 _G.accInUse++;
2797                 aopOp(IC_RESULT(ic),ic,FALSE);
2798                 _G.accInUse--;
2799
2800                 GpsuedoStkPtr = 0;
2801                 
2802                 assignResultValue(IC_RESULT(ic));
2803                 
2804                 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2805         }
2806         
2807         /* if register bank was saved then unsave them */
2808         if (currFunc && dtype && 
2809                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2810                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2811         
2812                 /* if we hade saved some registers then
2813         unsave them */
2814         if (ic->regsSaved)
2815                 unsaveRegisters (ic);
2816         
2817 }
2818
2819 /*-----------------------------------------------------------------*/
2820 /* resultRemat - result  is rematerializable                                       */
2821 /*-----------------------------------------------------------------*/
2822 static int resultRemat (iCode *ic)
2823 {
2824         //      DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2825         FENTRY;
2826
2827         if (SKIP_IC(ic) || ic->op == IFX)
2828                 return 0;
2829         
2830         if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2831                 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2832                 if (sym->remat && !POINTER_SET(ic)) 
2833                         return 1;
2834         }
2835         
2836         return 0;
2837 }
2838
2839 #if defined(__BORLANDC__) || defined(_MSC_VER)
2840 #define STRCASECMP stricmp
2841 #else
2842 #define STRCASECMP strcasecmp
2843 #endif
2844
2845 #if 0
2846 /*-----------------------------------------------------------------*/
2847 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2848 /*-----------------------------------------------------------------*/
2849 static bool inExcludeList(char *s)
2850 {
2851         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2852         int i =0;
2853         
2854         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2855         if (options.excludeRegs[i] &&
2856                 STRCASECMP(options.excludeRegs[i],"none") == 0)
2857                 return FALSE ;
2858         
2859         for ( i = 0 ; options.excludeRegs[i]; i++) {
2860                 if (options.excludeRegs[i] &&
2861                         STRCASECMP(s,options.excludeRegs[i]) == 0)
2862                         return TRUE;
2863         }
2864         return FALSE ;
2865 }
2866 #endif
2867
2868 /*-----------------------------------------------------------------*/
2869 /* genFunction - generated code for function entry                                 */
2870 /*-----------------------------------------------------------------*/
2871 static void genFunction (iCode *ic)
2872 {
2873         symbol *sym;
2874         sym_link *ftype;
2875         
2876         FENTRY;
2877
2878         DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2879         
2880         labelOffset += (max_key+4);
2881         max_key=0;
2882         GpsuedoStkPtr=0;
2883         _G.nRegsSaved = 0;
2884         /* create the function header */
2885         pic14_emitcode(";","-----------------------------------------");
2886         pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2887         pic14_emitcode(";","-----------------------------------------");
2888         
2889         /* prevent this symbol from being emitted as 'extern' */
2890         pic14_stringInSet(sym->rname, &pic14_localFunctions, 1);
2891
2892         pic14_emitcode("","%s:",sym->rname);
2893         addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2894         
2895         ftype = operandType(IC_LEFT(ic));
2896         
2897         /* if critical function then turn interrupts off */
2898         if (IFFUNC_ISCRITICAL(ftype))
2899                 pic14_emitcode("clr","ea");
2900         
2901                 /* here we need to generate the equates for the
2902         register bank if required */
2903 #if 0
2904         if (FUNC_REGBANK(ftype) != rbank) {
2905                 int i ;
2906                 
2907                 rbank = FUNC_REGBANK(ftype);
2908                 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2909                         if (strcmp(regspic14[i].base,"0") == 0)
2910                                 pic14_emitcode("","%s = 0x%02x",
2911                                 regspic14[i].dname,
2912                                 8*rbank+regspic14[i].offset);
2913                         else
2914                                 pic14_emitcode ("","%s = %s + 0x%02x",
2915                                 regspic14[i].dname,
2916                                 regspic14[i].base,
2917                                 8*rbank+regspic14[i].offset);
2918                 }
2919         }
2920 #endif
2921         
2922         /* if this is an interrupt service routine */
2923         if (IFFUNC_ISISR(sym->type)) {
2924         /*  already done in pic14createInterruptVect() - delete me
2925         addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2926         emitpcodeNULLop(POC_NOP);
2927         emitpcodeNULLop(POC_NOP);
2928         emitpcodeNULLop(POC_NOP);
2929                 */
2930                 emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2931                 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2932                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2933                 emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2934                 emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2935                 emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2936                 emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2937                 
2938                 pBlockConvert2ISR(pb);
2939                 pic14_hasInterrupt = 1;
2940 #if 0  
2941                 if (!inExcludeList("acc"))              
2942                         pic14_emitcode ("push","acc");  
2943                 if (!inExcludeList("b"))
2944                         pic14_emitcode ("push","b");
2945                 if (!inExcludeList("dpl"))
2946                         pic14_emitcode ("push","dpl");
2947                 if (!inExcludeList("dph"))
2948                         pic14_emitcode ("push","dph");
2949                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2950                 {
2951                         pic14_emitcode ("push", "dpx");
2952                         /* Make sure we're using standard DPTR */
2953                         pic14_emitcode ("push", "dps");
2954                         pic14_emitcode ("mov", "dps, #0x00");
2955                         if (options.stack10bit)
2956                         { 
2957                                 /* This ISR could conceivably use DPTR2. Better save it. */
2958                                 pic14_emitcode ("push", "dpl1");
2959                                 pic14_emitcode ("push", "dph1");
2960                                 pic14_emitcode ("push", "dpx1");
2961                         }
2962                 }
2963                 /* if this isr has no bank i.e. is going to
2964                 run with bank 0 , then we need to save more
2965                 registers :-) */
2966                 if (!FUNC_REGBANK(sym->type)) {
2967                         
2968                 /* if this function does not call any other
2969                 function then we can be economical and
2970                         save only those registers that are used */
2971                         if (! IFFUNC_HASFCALL(sym->type)) {
2972                                 int i;
2973                                 
2974                                 /* if any registers used */
2975                                 if (sym->regsUsed) {
2976                                         /* save the registers used */
2977                                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2978                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2979                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2980                                                         pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);               
2981                                         }
2982                                 }
2983                                 
2984                         } else {
2985                         /* this function has    a function call cannot
2986                         determines register usage so we will have the
2987                                 entire bank */
2988                                 saverbank(0,ic,FALSE);
2989                         }       
2990                 }
2991 #endif
2992         } else {
2993         /* if callee-save to be used for this function
2994                 then save the registers being used in this function */
2995                 if (IFFUNC_CALLEESAVES(sym->type)) {
2996                         int i;
2997                         
2998                         /* if any registers used */
2999                         if (sym->regsUsed) {
3000                                 /* save the registers used */
3001                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3002                                         if (bitVectBitValue(sym->regsUsed,i) ||
3003                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
3004                                                 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
3005                                                 _G.nRegsSaved++;
3006                                         }
3007                                 }
3008                         }
3009                 }
3010         }
3011         
3012         /* set the register bank to the desired value */
3013         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
3014                 pic14_emitcode("push","psw");
3015                 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);       
3016         }
3017         
3018         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3019                 
3020                 if (options.useXstack) {
3021                         pic14_emitcode("mov","r0,%s",spname);
3022                         pic14_emitcode("mov","a,_bp");
3023                         pic14_emitcode("movx","@r0,a");
3024                         pic14_emitcode("inc","%s",spname);
3025                 }
3026                 else
3027                 {
3028                         /* set up the stack */
3029                         pic14_emitcode ("push","_bp");   /* save the callers stack      */
3030                 }
3031                 pic14_emitcode ("mov","_bp,%s",spname);
3032         }
3033         
3034         /* adjust the stack for the function */
3035         if (sym->stack) {
3036                 
3037                 int i = sym->stack;
3038                 if (i > 256 ) 
3039                         werror(W_STACK_OVERFLOW,sym->name);
3040                 
3041                 if (i > 3 && sym->recvSize < 4) {                
3042                         
3043                         pic14_emitcode ("mov","a,sp");
3044                         pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3045                         pic14_emitcode ("mov","sp,a");
3046                         
3047                 }
3048                 else
3049                         while(i--)
3050                                 pic14_emitcode("inc","sp");
3051         }
3052         
3053         if (sym->xstack) {
3054                 
3055                 pic14_emitcode ("mov","a,_spx");
3056                 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3057                 pic14_emitcode ("mov","_spx,a");
3058         }
3059         
3060 }
3061
3062 /*-----------------------------------------------------------------*/
3063 /* genEndFunction - generates epilogue for functions                       */
3064 /*-----------------------------------------------------------------*/
3065 static void genEndFunction (iCode *ic)
3066 {
3067         symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3068         
3069         FENTRY;
3070
3071         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3072         
3073         if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3074         {
3075                 pic14_emitcode ("mov","%s,_bp",spname);
3076         }
3077         
3078         /* if use external stack but some variables were
3079         added to the local stack then decrement the
3080         local stack */
3081         if (options.useXstack && sym->stack) {    
3082                 pic14_emitcode("mov","a,sp");
3083                 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3084                 pic14_emitcode("mov","sp,a");
3085         }
3086         
3087         
3088         if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3089                 if (options.useXstack) {
3090                         pic14_emitcode("mov","r0,%s",spname);
3091                         pic14_emitcode("movx","a,@r0");
3092                         pic14_emitcode("mov","_bp,a");
3093                         pic14_emitcode("dec","%s",spname);
3094                 }
3095                 else
3096                 {
3097                         pic14_emitcode ("pop","_bp");
3098                 }
3099         }
3100         
3101         /* restore the register bank    */        
3102         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3103                 pic14_emitcode ("pop","psw");
3104         
3105         if (IFFUNC_ISISR(sym->type)) {
3106                 
3107                 /* now we need to restore the registers */
3108                 /* if this isr has no bank i.e. is going to
3109                 run with bank 0 , then we need to save more
3110 registers :-) */
3111                 if (!FUNC_REGBANK(sym->type)) {
3112                         
3113                 /* if this function does not call any other
3114                 function then we can be economical and
3115                         save only those registers that are used */
3116                         if (! IFFUNC_HASFCALL(sym->type)) {
3117                                 int i;
3118                                 
3119                                 /* if any registers used */
3120                                 if (sym->regsUsed) {
3121                                         /* save the registers used */
3122                                         for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3123                                                 if (bitVectBitValue(sym->regsUsed,i) ||
3124                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3125                                                         pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3126                                         }
3127                                 }
3128                                 
3129                         } else {
3130                         /* this function has    a function call cannot
3131                         determines register usage so we will have the
3132                                 entire bank */
3133                                 unsaverbank(0,ic,FALSE);
3134                         }       
3135                 }
3136 #if 0
3137                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3138                 {
3139                         if (options.stack10bit)
3140                         {
3141                                 pic14_emitcode ("pop", "dpx1");
3142                                 pic14_emitcode ("pop", "dph1");
3143                                 pic14_emitcode ("pop", "dpl1");
3144                         } 
3145                         pic14_emitcode ("pop", "dps");
3146                         pic14_emitcode ("pop", "dpx");
3147                 }
3148                 if (!inExcludeList("dph"))
3149                         pic14_emitcode ("pop","dph");
3150                 if (!inExcludeList("dpl"))
3151                         pic14_emitcode ("pop","dpl");
3152                 if (!inExcludeList("b"))
3153                         pic14_emitcode ("pop","b");
3154                 if (!inExcludeList("acc"))
3155                         pic14_emitcode ("pop","acc");
3156                 
3157                 if (IFFUNC_ISCRITICAL(sym->type))
3158                         pic14_emitcode("setb","ea");
3159 #endif
3160                 
3161                 /* if debug then send end of function */
3162                 /*      if (options.debug && currFunc) { */
3163                 if (currFunc) {
3164                         debugFile->writeEndFunction (currFunc, ic, 1);
3165                 }
3166                 
3167                 pic14_emitcode ("reti","");
3168                 emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
3169                 emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
3170                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
3171                 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3172                 emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
3173                 emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
3174                 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3175                 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3176                 emitpcodeNULLop(POC_RETFIE);
3177         }
3178         else {
3179                 if (IFFUNC_ISCRITICAL(sym->type))
3180                         pic14_emitcode("setb","ea");
3181                 
3182                 if (IFFUNC_CALLEESAVES(sym->type)) {
3183                         int i;
3184                         
3185                         /* if any registers used */
3186                         if (sym->regsUsed) {
3187                                 /* save the registers used */
3188                                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3189                                         if (bitVectBitValue(sym->regsUsed,i) ||
3190                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3191                                                 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3192                                 }
3193                         }
3194                         
3195                 }
3196                 
3197                 /* if debug then send end of function */
3198                 if (currFunc) {
3199                         debugFile->writeEndFunction (currFunc, ic, 1);
3200                 }
3201                 
3202                 pic14_emitcode ("return","");
3203                 emitpcodeNULLop(POC_RETURN);
3204                 
3205                 /* Mark the end of a function */
3206                 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3207         }
3208         
3209 }
3210
3211 /*-----------------------------------------------------------------*/
3212 /* genRet - generate code for return statement                                     */
3213 /*-----------------------------------------------------------------*/
3214 static void genRet (iCode *ic)
3215 {
3216         int size,offset = 0;
3217         
3218         FENTRY;
3219
3220         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3221         /* if we have no return value then
3222         just generate the "ret" */
3223         if (!IC_LEFT(ic)) 
3224                 goto jumpret;           
3225         
3226                 /* we have something to return then
3227         move the return value into place */
3228         aopOp(IC_LEFT(ic),ic,FALSE);
3229         size = AOP_SIZE(IC_LEFT(ic));
3230
3231         for (offset = 0; offset < size; offset++)
3232         {
3233                 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3234         }
3235         
3236         freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3237         
3238 jumpret:
3239         /* generate a jump to the return label
3240         if the next is not the return statement */
3241         if (!(ic->next && ic->next->op == LABEL &&
3242                 IC_LABEL(ic->next) == returnLabel)) {
3243                 
3244                 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3245         }
3246         
3247 }
3248
3249 /*-----------------------------------------------------------------*/
3250 /* genLabel - generates a label                                                                    */
3251 /*-----------------------------------------------------------------*/
3252 static void genLabel (iCode *ic)
3253 {
3254         FENTRY;
3255
3256         /* special case never generate */
3257         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3258         if (IC_LABEL(ic) == entryLabel)
3259                 return ;
3260         
3261         emitpLabel(IC_LABEL(ic)->key);
3262         pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3263 }
3264
3265 /*-----------------------------------------------------------------*/
3266 /* genGoto - generates a goto                                                                      */
3267 /*-----------------------------------------------------------------*/
3268 //tsd
3269 static void genGoto (iCode *ic)
3270 {
3271         FENTRY;
3272
3273         emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3274         pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3275 }
3276
3277
3278 /*-----------------------------------------------------------------*/
3279 /* genMultbits :- multiplication of bits                                                   */
3280 /*-----------------------------------------------------------------*/
3281 static void genMultbits (operand *left, 
3282                                                  operand *right, 
3283                                                  operand *result)
3284 {
3285         FENTRY;
3286         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3287         
3288         if(!pic14_sameRegs(AOP(result),AOP(right)))
3289                 emitpcode(POC_BSF,      popGet(AOP(result),0));
3290         
3291         emitpcode(POC_BTFSC,popGet(AOP(right),0));
3292         emitpcode(POC_BTFSS,popGet(AOP(left),0));
3293         emitpcode(POC_BCF,  popGet(AOP(result),0));
3294         
3295 }
3296
3297
3298 /*-----------------------------------------------------------------*/
3299 /* genMultOneByte : 8 bit multiplication & division                        */
3300 /*-----------------------------------------------------------------*/
3301 static void genMultOneByte (operand *left,
3302                                                         operand *right,
3303                                                         operand *result)
3304 {
3305         char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3306         
3307         // symbol *lbl ;
3308         int size,offset,i;
3309         
3310         
3311         FENTRY;
3312         
3313         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3314         DEBUGpic14_AopType(__LINE__,left,right,result);
3315         DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3316         
3317         /* (if two literals, the value is computed before) */
3318         /* if one literal, literal on the right */
3319         if (AOP_TYPE(left) == AOP_LIT){
3320                 operand *t = right;
3321                 right = left;
3322                 left = t;
3323         }
3324
3325         assert (AOP_SIZE(left) == AOP_SIZE(right));
3326         
3327         size = min(AOP_SIZE(result),AOP_SIZE(left));
3328         offset = Gstack_base_addr - (2*size - 1);
3329
3330         /* pass right operand as argument */
3331         for (i=0; i < size; i++)
3332         {
3333                 mov2w (AOP(right), i);
3334                 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3335         } // for
3336         
3337         /* pass left operand as argument */
3338         for (i=0; i < size; i++)
3339         {
3340                 mov2w (AOP(left), i);
3341                 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3342         } // for
3343         assert (offset == Gstack_base_addr);
3344         
3345         /* call library routine */
3346         assert (size > 0 && size <= 4);
3347         call_libraryfunc (func[size]);
3348         
3349         /* assign result */
3350         movwf (AOP(result), size-1);
3351         for (i=0; i < size - 1; i++)
3352         {
3353                 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3354                 movwf (AOP(result), size - 2 - i);
3355         } // for
3356
3357         /* now (zero-/sign) extend the result to its size */
3358         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3359 }
3360
3361 /*-----------------------------------------------------------------*/
3362 /* genMult - generates code for multiplication                                     */
3363 /*-----------------------------------------------------------------*/
3364 static void genMult (iCode *ic)
3365 {
3366         operand *left = IC_LEFT(ic);
3367         operand *right = IC_RIGHT(ic);
3368         operand *result= IC_RESULT(ic); 
3369         
3370         FENTRY;
3371
3372         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3373         /* assign the amsops */
3374         aopOp (left,ic,FALSE);
3375         aopOp (right,ic,FALSE);
3376         aopOp (result,ic,TRUE);
3377         
3378         DEBUGpic14_AopType(__LINE__,left,right,result);
3379         
3380         /* special cases first */
3381         /* both are bits */
3382         if (AOP_TYPE(left) == AOP_CRY &&
3383                 AOP_TYPE(right)== AOP_CRY) {
3384                 genMultbits(left,right,result);
3385                 goto release ;
3386         }
3387         
3388         /* if both are of size == 1 */
3389         if (AOP_SIZE(left) == 1 &&
3390                 AOP_SIZE(right) == 1 ) {
3391                 genMultOneByte(left,right,result);
3392                 goto release ;
3393         }
3394         
3395         /* should have been converted to function call */
3396         assert(0) ;
3397         
3398 release :
3399         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3400         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3401         freeAsmop(result,NULL,ic,TRUE); 
3402 }
3403
3404 /*-----------------------------------------------------------------*/
3405 /* genDivbits :- division of bits                                                                  */
3406 /*-----------------------------------------------------------------*/
3407 static void genDivbits (operand *left, 
3408                                                 operand *right, 
3409                                                 operand *result)
3410 {
3411         
3412         char *l;
3413         
3414         FENTRY;
3415
3416         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3417         /* the result must be bit */      
3418         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3419         l = aopGet(AOP(left),0,FALSE,FALSE);
3420         
3421         MOVA(l);          
3422         
3423         pic14_emitcode("div","ab");
3424         pic14_emitcode("rrc","a");
3425         aopPut(AOP(result),"c",0);
3426 }
3427
3428 /*-----------------------------------------------------------------*/
3429 /* genDivOneByte : 8 bit division                                                                  */
3430 /*-----------------------------------------------------------------*/
3431 static void genDivOneByte (operand *left,
3432                                                    operand *right,
3433                                                    operand *result)
3434 {
3435         int size;
3436         
3437         FENTRY;
3438         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3439         
3440         assert (AOP_SIZE(result) == 1);
3441         assert (AOP_SIZE(right) == 1);
3442         assert (AOP_SIZE(left) == 1);
3443
3444         size = min(AOP_SIZE(result),AOP_SIZE(left));
3445
3446         if (AOP_TYPE(right) == AOP_LIT)
3447         {
3448                 /* XXX: might add specialized code */
3449         }
3450
3451         if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3452         {
3453                 /* unsigned division */
3454         #if 1
3455                 mov2w(AOP(right),0);
3456                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3457                 mov2w(AOP(left),0);
3458                 call_libraryfunc("__divuchar");
3459                 movwf(AOP(result),0);
3460         #else
3461                 pCodeOp *temp;
3462                 symbol *lbl;
3463
3464                 temp = popGetTempReg();
3465                 lbl = newiTempLabel(NULL);
3466                 
3467                 /* XXX: improve this naive approach:
3468                    [result] = [a] / [b]
3469                         ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3470
3471                    In PIC assembler:
3472                    movf  left,W
3473                    movwf temp           // temp <-- left
3474                    movf  right,W        // W <-- right
3475                    clrf  result
3476                    label1:
3477                    incf  result
3478                    subwf temp,F         // temp <-- temp - W
3479                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if temp < W
3480                    goto  label1
3481                    decf result          // we just subtract once too often
3482                  */
3483
3484                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3485                 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3486                 
3487                 mov2w(AOP(left),0);
3488                 emitpcode(POC_MOVWF, temp);
3489                 mov2w(AOP(right),0);
3490                 emitpcode(POC_CLRF, popGet(AOP(result),0));
3491
3492                 emitpLabel(lbl->key);
3493                 emitpcode(POC_INCF, popGet(AOP(result),0));
3494                 emitpcode(POC_SUBWF, temp);
3495                 emitSKPNC;
3496                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3497                 emitpcode(POC_DECF, popGet(AOP(result),0));
3498         #endif
3499         }
3500         else
3501         {
3502                 /* signed division */
3503                 mov2w(AOP(right),0);
3504                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3505                 mov2w(AOP(left),0);
3506                 call_libraryfunc("__divschar");
3507                 movwf(AOP(result),0);
3508         }
3509
3510         /* now performed the signed/unsigned division -- extend result */
3511         addSign(result, 1, !SPEC_USIGN(operandType(result)));
3512 }
3513
3514 /*-----------------------------------------------------------------*/
3515 /* genDiv - generates code for division                            */
3516 /*-----------------------------------------------------------------*/
3517 static void genDiv (iCode *ic)
3518 {
3519         operand *left = IC_LEFT(ic);
3520         operand *right = IC_RIGHT(ic);
3521         operand *result= IC_RESULT(ic); 
3522         
3523         FENTRY;
3524         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3525         /* assign the amsops */
3526         aopOp (left,ic,FALSE);
3527         aopOp (right,ic,FALSE);
3528         aopOp (result,ic,TRUE);
3529         
3530         /* special cases first */
3531         /* both are bits */
3532         if (AOP_TYPE(left) == AOP_CRY &&
3533                 AOP_TYPE(right)== AOP_CRY) {
3534                 genDivbits(left,right,result);
3535                 goto release ;
3536         }
3537         
3538         /* if both are of size == 1 */
3539         if (AOP_SIZE(left) == 1 &&
3540                 AOP_SIZE(right) == 1 ) {
3541                 genDivOneByte(left,right,result);
3542                 goto release ;
3543         }
3544         
3545         /* should have been converted to function call */
3546         assert(0);
3547 release :
3548         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3549         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3550         freeAsmop(result,NULL,ic,TRUE); 
3551 }
3552
3553 /*-----------------------------------------------------------------*/
3554 /* genModbits :- modulus of bits                                                                   */
3555 /*-----------------------------------------------------------------*/
3556 static void genModbits (operand *left, 
3557                                                 operand *right, 
3558                                                 operand *result)
3559 {
3560         
3561         char *l;
3562         
3563         FENTRY;
3564         /* the result must be bit */      
3565         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3566         l = aopGet(AOP(left),0,FALSE,FALSE);
3567         
3568         MOVA(l);
3569         
3570         pic14_emitcode("div","ab");
3571         pic14_emitcode("mov","a,b");
3572         pic14_emitcode("rrc","a");
3573         aopPut(AOP(result),"c",0);
3574 }
3575
3576 /*-----------------------------------------------------------------*/
3577 /* genModOneByte : 8 bit modulus                                                                   */
3578 /*-----------------------------------------------------------------*/
3579 static void genModOneByte (operand *left,
3580                                                    operand *right,
3581                                                    operand *result)
3582 {
3583         int size;
3584         
3585         FENTRY;
3586         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3587         
3588         assert (AOP_SIZE(result) == 1);
3589         assert (AOP_SIZE(right) == 1);
3590         assert (AOP_SIZE(left) == 1);
3591
3592         size = min(AOP_SIZE(result),AOP_SIZE(left));
3593
3594         if (AOP_TYPE(right) == AOP_LIT)
3595         {
3596                 /* XXX: might add specialized code */
3597         }
3598
3599         if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3600         {
3601                 /* unsigned division */
3602         #if 1
3603                 mov2w(AOP(right),0);
3604                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3605                 mov2w(AOP(left),0);
3606                 call_libraryfunc("__moduchar");
3607                 movwf(AOP(result),0);
3608         #else
3609                 pCodeOp *temp;
3610                 symbol *lbl;
3611
3612                 lbl = newiTempLabel(NULL);
3613                 
3614                 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3615
3616                 /* XXX: improve this naive approach:
3617                    [result] = [a] % [b]
3618                         ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3619
3620                    In PIC assembler:
3621                    movf  left,W
3622                    movwf result         // result <-- left
3623                    movf  right,W        // W <-- right
3624                    label1:
3625                    subwf result,F       // result <-- result - W
3626                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if result < W
3627                    goto  label1
3628                    addwf result, F      // we just subtract once too often
3629                  */
3630
3631                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3632                 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3633                 
3634                 if (!pic14_sameRegs(AOP(left), AOP(result)))
3635                 {
3636                         mov2w(AOP(left),0);
3637                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
3638                 }
3639                 mov2w(AOP(right),0);
3640
3641                 emitpLabel(lbl->key);
3642                 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3643                 emitSKPNC;
3644                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3645                 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3646         #endif
3647         }
3648         else
3649         {
3650                 /* signed division */
3651                 mov2w(AOP(right),0);
3652                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3653                 mov2w(AOP(left),0);
3654                 call_libraryfunc("__modschar");
3655                 movwf(AOP(result),0);
3656         }
3657
3658         /* now we performed the signed/unsigned modulus -- extend result */
3659         addSign(result, 1, !SPEC_USIGN(operandType(result)));
3660 }
3661
3662 /*-----------------------------------------------------------------*/
3663 /* genMod - generates code for division                                                    */
3664 /*-----------------------------------------------------------------*/
3665 static void genMod (iCode *ic)
3666 {
3667         operand *left = IC_LEFT(ic);
3668         operand *right = IC_RIGHT(ic);
3669         operand *result= IC_RESULT(ic);  
3670         
3671         FENTRY;
3672         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3673         /* assign the amsops */
3674         aopOp (left,ic,FALSE);
3675         aopOp (right,ic,FALSE);
3676         aopOp (result,ic,TRUE);
3677         
3678         /* special cases first */
3679         /* both are bits */
3680         if (AOP_TYPE(left) == AOP_CRY &&
3681                 AOP_TYPE(right)== AOP_CRY) {
3682                 genModbits(left,right,result);
3683                 goto release ;
3684         }
3685         
3686         /* if both are of size == 1 */
3687         if (AOP_SIZE(left) == 1 &&
3688                 AOP_SIZE(right) == 1 ) {
3689                 genModOneByte(left,right,result);
3690                 goto release ;
3691         }
3692         
3693         /* should have been converted to function call */
3694         assert(0);
3695         
3696 release :
3697         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3698         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3699         freeAsmop(result,NULL,ic,TRUE); 
3700 }
3701
3702 /*-----------------------------------------------------------------*/
3703 /* genIfxJump :- will create a jump depending on the ifx                   */
3704 /*-----------------------------------------------------------------*/
3705 /*
3706 note: May need to add parameter to indicate when a variable is in bit space.
3707 */
3708 static void genIfxJump (iCode *ic, char *jval)
3709 {
3710         
3711         FENTRY;
3712         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3713         /* if true label then we jump if condition
3714         supplied is true */
3715         if ( IC_TRUE(ic) ) {
3716                 
3717                 if(strcmp(jval,"a") == 0)
3718                         emitSKPZ;
3719                 else if (strcmp(jval,"c") == 0)
3720                         emitSKPC;
3721                 else {
3722                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3723                         emitpcode(POC_BTFSC,    newpCodeOpBit(jval,-1,1));
3724                 }
3725                 
3726                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3727                 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3728                 
3729         }
3730         else {
3731                 /* false label is present */
3732                 if(strcmp(jval,"a") == 0)
3733                         emitSKPNZ;
3734                 else if (strcmp(jval,"c") == 0)
3735                         emitSKPNC;
3736                 else {
3737                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3738                         emitpcode(POC_BTFSS,    newpCodeOpBit(jval,-1,1));
3739                 }
3740                 
3741                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3742                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3743                 
3744         }
3745         
3746         
3747         /* mark the icode as generated */
3748         ic->generated = 1;
3749 }
3750
3751 #if 0
3752 /*-----------------------------------------------------------------*/
3753 /* genSkip                                                                                                                 */
3754 /*-----------------------------------------------------------------*/
3755 static void genSkip(iCode *ifx,int status_bit)
3756 {
3757         FENTRY;
3758         if(!ifx)
3759                 return;
3760         
3761         if ( IC_TRUE(ifx) ) {
3762                 switch(status_bit) {
3763                 case 'z':
3764                         emitSKPNZ;
3765                         break;
3766                         
3767                 case 'c':
3768                         emitSKPNC;
3769                         break;
3770                         
3771                 case 'd':
3772                         emitSKPDC;
3773                         break;
3774                         
3775                 }
3776                 
3777                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3778                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3779                 
3780         } else {
3781                 
3782                 switch(status_bit) {
3783                         
3784                 case 'z':
3785                         emitSKPZ;
3786                         break;
3787                         
3788                 case 'c':
3789                         emitSKPC;
3790                         break;
3791                         
3792                 case 'd':
3793                         emitSKPDC;
3794                         break;
3795                 }
3796                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3797                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3798                 
3799         }
3800         
3801 }
3802 #endif
3803
3804 /*-----------------------------------------------------------------*/
3805 /* genSkipc                                                                                                        */
3806 /*-----------------------------------------------------------------*/
3807 static void genSkipc(resolvedIfx *rifx)
3808 {
3809         FENTRY;
3810         if(!rifx)
3811                 return;
3812         
3813         if(rifx->condition)
3814                 emitSKPNC;
3815         else
3816                 emitSKPC;
3817         
3818         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3819         emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3820         rifx->generated = 1;
3821 }
3822
3823 #if 0
3824 /*-----------------------------------------------------------------*/
3825 /* genSkipz2                                                                                                       */
3826 /*-----------------------------------------------------------------*/
3827 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3828 {
3829         FENTRY;
3830         if(!rifx)
3831                 return;
3832         
3833         if( (rifx->condition ^ invert_condition) & 1)
3834                 emitSKPZ;
3835         else
3836                 emitSKPNZ;
3837         
3838         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3839         rifx->generated = 1;
3840 }
3841 #endif
3842
3843 #if 0
3844 /*-----------------------------------------------------------------*/
3845 /* genSkipz                                                        */
3846 /*-----------------------------------------------------------------*/
3847 static void genSkipz(iCode *ifx, int condition)
3848 {
3849         FENTRY;
3850         assert (ifx != NULL);
3851         
3852         if(condition)
3853                 emitSKPNZ;
3854         else
3855                 emitSKPZ;
3856         
3857         if ( IC_TRUE(ifx) )
3858                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3859         else
3860                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3861         
3862         if ( IC_TRUE(ifx) )
3863                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3864         else
3865                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3866         
3867 }
3868 #endif
3869
3870 #if 0
3871 /*-----------------------------------------------------------------*/
3872 /* genSkipCond                                                     */
3873 /*-----------------------------------------------------------------*/
3874 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3875 {
3876         FENTRY;
3877         if(!rifx)
3878                 return;
3879         
3880         if(rifx->condition)
3881                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3882         else
3883                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3884         
3885         
3886         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3887         rifx->generated = 1;
3888 }
3889 #endif
3890
3891 #if 0
3892 /*-----------------------------------------------------------------*/
3893 /* genChkZeroes :- greater or less than comparison                 */
3894 /*     For each byte in a literal that is zero, inclusive or the   */
3895 /*     the corresponding byte in the operand with W                */
3896 /*     returns true if any of the bytes are zero                   */
3897 /*-----------------------------------------------------------------*/
3898 static int genChkZeroes(operand *op, int lit,  int size)
3899 {
3900         
3901         int i;
3902         int flag =1;
3903         
3904         while(size--) {
3905                 i = (lit >> (size*8)) & 0xff;
3906                 
3907                 if(i==0) {
3908                         if(flag) 
3909                                 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3910                         else
3911                                 emitpcode(POC_IORFW, popGet(AOP(op),size));
3912                         flag = 0;
3913                 }
3914         }
3915         
3916         return (flag==0);
3917 }
3918 #endif
3919
3920
3921 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3922 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
3923 #define DEBUGpc           emitpComment
3924
3925 /*-----------------------------------------------------------------*/
3926 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
3927 /*                  aop (if it's NOT a literal) or from lit (if    */
3928 /*                  aop is a literal)                              */
3929 /*-----------------------------------------------------------------*/
3930 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3931   if (aop->type == AOP_LIT) {
3932     emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3933   } else {
3934     emitpcode (POC_MOVFW, popGet (aop, offset));
3935   }
3936 }
3937
3938 /* genCmp performs a left < right comparison, stores
3939  * the outcome in result (if != NULL) and generates
3940  * control flow code for the ifx (if != NULL).
3941  *
3942  * This version leaves in sequences like
3943  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3944  * which should be optmized by the peephole
3945  * optimizer - RN 2005-01-01 */
3946 static void genCmp (operand *left,operand *right,
3947                     operand *result, iCode *ifx, int sign)
3948 {
3949   resolvedIfx rIfx;
3950   int size;
3951   int offs;
3952   symbol *templbl;
3953   operand *dummy;
3954   unsigned long lit;
3955   unsigned long mask;
3956   int performedLt;
3957   int invert_result = 0;
3958
3959   FENTRY;
3960   
3961   assert (AOP_SIZE(left) == AOP_SIZE(right));
3962   assert (left && right);
3963
3964   size = AOP_SIZE(right) - 1;
3965   mask = (0x100UL << (size*8)) - 1;
3966   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3967   performedLt = 1;
3968   templbl = NULL;
3969   lit = 0;
3970   
3971   resolveIfx (&rIfx, ifx);
3972
3973   /**********************************************************************
3974    * handle bits - bit compares are promoted to int compares seemingly! *
3975    **********************************************************************/
3976 #if 0
3977   // THIS IS COMPLETELY UNTESTED!
3978   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3979     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3980     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3981     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3982
3983     emitSETC;
3984     // 1 < {0,1} is false --> clear C by skipping the next instruction
3985     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3986     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3987     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3988     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3989     emitCLRC; // only skipped for left=0 && right=1
3990
3991     goto correct_result_in_carry;
3992   } // if
3993 #endif
3994
3995   /*************************************************
3996    * make sure that left is register (or the like) *
3997    *************************************************/
3998   if (!isAOP_REGlike(left)) {
3999     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4000     assert (isAOP_LIT(left));
4001     assert (isAOP_REGlike(right));
4002     // swap left and right
4003     // left < right <==> right > left <==> (right >= left + 1)
4004     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4005
4006     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4007       // MAXVALUE < right? always false
4008       if (performedLt) emitCLRC; else emitSETC;
4009       goto correct_result_in_carry;
4010     } // if
4011
4012     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4013     // that's why we handled it above.
4014     lit++;
4015
4016     dummy = left;
4017     left = right;
4018     right = dummy;
4019
4020     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4021   } else if (isAOP_LIT(right)) {
4022     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4023   } // if
4024
4025   assert (isAOP_REGlike(left)); // left must be register or the like
4026   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4027
4028   /*************************************************
4029    * special cases go here                         *
4030    *************************************************/
4031
4032   if (isAOP_LIT(right)) {
4033     if (!sign) {
4034       // unsigned comparison to a literal
4035       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4036       if (lit == 0) {
4037         // unsigned left < 0? always false
4038         if (performedLt) emitCLRC; else emitSETC;
4039         goto correct_result_in_carry;
4040       }
4041     } else {
4042       // signed comparison to a literal
4043       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4044       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4045         // signed left < 0x80000000? always false
4046         if (performedLt) emitCLRC; else emitSETC;
4047         goto correct_result_in_carry;
4048       } else if (lit == 0) {
4049         // compare left < 0; set CARRY if SIGNBIT(left) is set
4050         if (performedLt) emitSETC; else emitCLRC;
4051         emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
4052         if (performedLt) emitCLRC; else emitSETC;
4053         goto correct_result_in_carry;
4054       }
4055     } // if (!sign)
4056   } // right is literal
4057
4058   /*************************************************
4059    * perform a general case comparison             *
4060    * make sure we get CARRY==1 <==> left >= right  *
4061    *************************************************/
4062   // compare most significant bytes
4063   //DEBUGpc ("comparing bytes at offset %d", size);
4064   if (!sign) {
4065     // unsigned comparison
4066     pic14_mov2w_regOrLit (AOP(right), lit, size);
4067     emitpcode (POC_SUBFW, popGet (AOP(left), size));
4068   } else {
4069     // signed comparison
4070     // (add 2^n to both operands then perform an unsigned comparison)
4071     if (isAOP_LIT(right)) {
4072       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4073       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4074
4075       if (litbyte == 0x80) {
4076         // left >= 0x80 -- always true, but more bytes to come
4077         mov2w (AOP(left), size);
4078         emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
4079         emitSETC;
4080       } else {
4081         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4082         mov2w (AOP(left), size);
4083         emitpcode (POC_ADDLW, popGetLit (0x80));
4084         emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4085       } // if
4086     } else {
4087       pCodeOp *pctemp = popGetTempReg();
4088       mov2w (AOP(left), size);
4089       emitpcode (POC_ADDLW, popGetLit (0x80));
4090       emitpcode (POC_MOVWF, pctemp);
4091       mov2w (AOP(right), size);
4092       emitpcode (POC_ADDLW, popGetLit (0x80));
4093       emitpcode (POC_SUBFW, pctemp);
4094       popReleaseTempReg(pctemp);
4095     }
4096   } // if (!sign)
4097
4098   // compare remaining bytes (treat as unsigned case from above)
4099   templbl = newiTempLabel ( NULL );
4100   offs = size;
4101   while (offs--) {
4102     //DEBUGpc ("comparing bytes at offset %d", offs);
4103     emitSKPZ;
4104     emitpcode (POC_GOTO, popGetLabel (templbl->key));
4105     pic14_mov2w_regOrLit (AOP(right), lit, offs);
4106     emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4107   } // while (offs)
4108   emitpLabel (templbl->key);
4109   goto result_in_carry;
4110
4111 result_in_carry:
4112   
4113   /****************************************************
4114    * now CARRY contains the result of the comparison: *
4115    * SUBWF sets CARRY iff                             *
4116    * F-W >= 0 <==> F >= W <==> !(F < W)               *
4117    * (F=left, W=right)                                *
4118    ****************************************************/
4119
4120   if (performedLt) {
4121     invert_result = 1;
4122     // value will be used in the following genSkipc()
4123     rIfx.condition ^= 1;
4124   } // if
4125
4126 correct_result_in_carry:
4127
4128   // assign result to variable (if neccessary)
4129   if (result && AOP_TYPE(result) != AOP_CRY) {
4130     //DEBUGpc ("assign result");
4131     size = AOP_SIZE(result);
4132     while (size--) {
4133       emitpcode (POC_CLRF, popGet (AOP(result), size));
4134     } // while
4135     if (invert_result) {
4136       emitSKPC;
4137       emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4138     } else {
4139       emitpcode (POC_RLF, popGet (AOP(result), 0));
4140     }
4141   } // if (result)
4142
4143   // perform conditional jump
4144   if (ifx) {
4145     //DEBUGpc ("generate control flow");
4146     genSkipc (&rIfx);
4147     ifx->generated = 1;
4148   } // if
4149 }
4150
4151
4152 #if 0
4153 /* OLD VERSION -- BUGGY, DO NOT USE */
4154
4155 /*-----------------------------------------------------------------*/
4156 /* genCmp :- greater or less than comparison                       */
4157 /*-----------------------------------------------------------------*/
4158 static void genCmp (operand *left,operand *right,
4159                                         operand *result, iCode *ifx, int sign)
4160 {
4161         int size; //, offset = 0 ;
4162         unsigned long lit = 0L,i = 0;
4163         resolvedIfx rFalseIfx;
4164         //  resolvedIfx rTrueIfx;
4165         symbol *truelbl;
4166
4167         FENTRY;
4168         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4169         /*
4170         if(ifx) {
4171         DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4172         DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4173         }
4174         */
4175         
4176         resolveIfx(&rFalseIfx,ifx);
4177         truelbl  = newiTempLabel(NULL);
4178         size = max(AOP_SIZE(left),AOP_SIZE(right));
4179         
4180         DEBUGpic14_AopType(__LINE__,left,right,result);
4181         
4182 #define _swapp
4183         
4184         /* if literal is on the right then swap with left */
4185         if ((AOP_TYPE(right) == AOP_LIT)) {
4186                 operand *tmp = right ;
4187                 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4188                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4189 #ifdef _swapp
4190                 
4191                 lit = (lit - 1) & mask;
4192                 right = left;
4193                 left = tmp;
4194                 rFalseIfx.condition ^= 1;
4195 #endif
4196                 
4197         } else if ((AOP_TYPE(left) == AOP_LIT)) {
4198                 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4199         }
4200         
4201         
4202         //if(IC_TRUE(ifx) == NULL)
4203         /* if left & right are bit variables */
4204         if (AOP_TYPE(left) == AOP_CRY &&
4205                 AOP_TYPE(right) == AOP_CRY ) {
4206                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4207                 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4208         } else {
4209         /* subtract right from left if at the
4210         end the carry flag is set then we know that
4211                 left is greater than right */
4212                 
4213                 symbol *lbl  = newiTempLabel(NULL);
4214                 
4215 #ifndef _swapp
4216                 if(AOP_TYPE(right) == AOP_LIT) {
4217                         
4218                         //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4219                         
4220                         DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4221                         
4222                         /* special cases */
4223                         
4224                         if(lit == 0) {
4225                                 
4226                                 if(sign != 0) 
4227                                         genSkipCond(&rFalseIfx,left,size-1,7);
4228                                 else 
4229                                         /* no need to compare to 0...*/
4230                                         /* NOTE: this is a de-generate compare that most certainly 
4231                                         *       creates some dead code. */
4232                                         emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4233                                 
4234                                 if(ifx) ifx->generated = 1;
4235                                 return;
4236                                 
4237                         }
4238                         size--;
4239                         
4240                         if(size == 0) {
4241                                 //i = (lit >> (size*8)) & 0xff;
4242                                 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4243                                 
4244                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4245                                 
4246                                 i = ((0-lit) & 0xff);
4247                                 if(sign) {
4248                                         if( i == 0x81) { 
4249                                         /* lit is 0x7f, all signed chars are less than
4250                                                 * this except for 0x7f itself */
4251                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4252                                                 genSkipz2(&rFalseIfx,0);
4253                                         } else {
4254                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4255                                                 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4256                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4257                                         }
4258                                         
4259                                 } else {
4260                                         if(lit == 1) {
4261                                                 genSkipz2(&rFalseIfx,1);
4262                                         } else {
4263                                                 emitpcode(POC_ADDLW, popGetLit(i));
4264                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4265                                         }
4266                                 }
4267                                 
4268                                 if(ifx) ifx->generated = 1;
4269                                 return;
4270                         }
4271                         
4272                         /* chars are out of the way. now do ints and longs */
4273                         
4274                         
4275                         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4276                         
4277                         /* special cases */
4278                         
4279                         if(sign) {
4280                                 
4281                                 if(lit == 0) {
4282                                         genSkipCond(&rFalseIfx,left,size,7);
4283                                         if(ifx) ifx->generated = 1;
4284                                         return;
4285                                 }
4286                                 
4287                                 if(lit <0x100) {
4288                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4289                                         
4290                                         //rFalseIfx.condition ^= 1;
4291                                         //genSkipCond(&rFalseIfx,left,size,7);
4292                                         //rFalseIfx.condition ^= 1;
4293                                         
4294                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4295                                         if(rFalseIfx.condition)
4296                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4297                                         else
4298                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4299                                         
4300                                         emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4301                                         emitpcode(POC_ADDFW, popGet(AOP(left),0));
4302                                         emitpcode(POC_MOVFW, popGet(AOP(left),1));
4303                                         
4304                                         while(size > 1)
4305                                                 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4306                                         
4307                                         if(rFalseIfx.condition) {
4308                                                 emitSKPZ;
4309                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4310                                                 
4311                                         } else {
4312                                                 emitSKPNZ;
4313                                         }
4314                                         
4315                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4316                                         emitpLabel(truelbl->key);
4317                                         if(ifx) ifx->generated = 1;
4318                                         return;
4319                                         
4320                                 }
4321                                 
4322                                 if(size == 1) {
4323                                         
4324                                         if( (lit & 0xff) == 0) {
4325                                                 /* lower byte is zero */
4326                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4327                                                 i = ((lit >> 8) & 0xff) ^0x80;
4328                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4329                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4330                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4331                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4332                                                 
4333                                                 
4334                                                 if(ifx) ifx->generated = 1;
4335                                                 return;
4336                                                 
4337                                         }
4338                                 } else {
4339                                         /* Special cases for signed longs */
4340                                         if( (lit & 0xffffff) == 0) {
4341                                                 /* lower byte is zero */
4342                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4343                                                 i = ((lit >> 8*3) & 0xff) ^0x80;
4344                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4345                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4346                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4347                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4348                                                 
4349                                                 
4350                                                 if(ifx) ifx->generated = 1;
4351                                                 return;
4352                                                 
4353                                         }
4354                                         
4355                                 }
4356                                 
4357                                 
4358                                 if(lit & (0x80 << (size*8))) {
4359                                         /* lit is negative */
4360                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4361                                         
4362                                         //genSkipCond(&rFalseIfx,left,size,7);
4363                                         
4364                                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4365                                         
4366                                         if(rFalseIfx.condition)
4367                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4368                                         else
4369                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4370                                         
4371                                         
4372                                 } else {
4373                                         /* lit is positive */
4374                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4375                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4376                                         if(rFalseIfx.condition)
4377                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4378                                         else
4379                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4380                                         
4381                                 }
4382                                 
4383                                 /* There are no more special cases, so perform a general compare */
4384                                 
4385                                 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4386                                 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4387                                 
4388                                 while(size--) {
4389                                         
4390                                         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4391                                         emitSKPNZ;
4392                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4393                                 }
4394                                 //rFalseIfx.condition ^= 1;
4395                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4396                                 
4397                                 emitpLabel(truelbl->key);
4398                                 
4399                                 if(ifx) ifx->generated = 1;
4400                                 return;
4401                                 
4402                                 
4403                         }
4404
4405
4406                         /* sign is out of the way. So now do an unsigned compare */
4407                         DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4408
4409
4410                         /* General case - compare to an unsigned literal on the right.*/
4411
4412                         i = (lit >> (size*8)) & 0xff;
4413                         emitpcode(POC_MOVLW, popGetLit(i));
4414                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4415                         while(size--) {
4416                                 i = (lit >> (size*8)) & 0xff;
4417                                 
4418                                 if(i) {
4419                                         emitpcode(POC_MOVLW, popGetLit(i));
4420                                         emitSKPNZ;
4421                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4422                                 } else {
4423                                 /* this byte of the lit is zero, 
4424                                         *if it's not the last then OR in the variable */
4425                                         if(size)
4426                                                 emitpcode(POC_IORFW, popGet(AOP(left),size));
4427                                 }
4428                         }
4429
4430
4431                 emitpLabel(lbl->key);
4432                 //if(emitFinalCheck)
4433                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4434                 if(sign)
4435                         emitpLabel(truelbl->key);
4436
4437                 if(ifx) ifx->generated = 1;
4438                 return;
4439
4440
4441                 }
4442 #endif  // _swapp
4443
4444                 if(AOP_TYPE(left) == AOP_LIT) {
4445                         //symbol *lbl = newiTempLabel(NULL);
4446                         
4447                         //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4448                         
4449                         
4450                         DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4451                         
4452                         /* Special cases */
4453                         if((lit == 0) && (sign == 0)){
4454                                 
4455                                 size--;
4456                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4457                                 while(size) 
4458                                         emitpcode(POC_IORFW, popGet(AOP(right),--size));
4459                                 
4460                                 genSkipz2(&rFalseIfx,0);
4461                                 if(ifx) ifx->generated = 1;
4462                                 return;
4463                         }
4464                         
4465                         if(size==1) {
4466                                 /* Special cases */
4467                                 lit &= 0xff;
4468                                 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4469                                         /* degenerate compare can never be true */
4470                                         if(rFalseIfx.condition == 0)
4471                                                 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4472                                         
4473                                         if(ifx) ifx->generated = 1;
4474                                         return;
4475                                 }
4476                                 
4477                                 if(sign) {
4478                                         /* signed comparisons to a literal byte */
4479                                         
4480                                         int lp1 = (lit+1) & 0xff;
4481                                         
4482                                         DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4483                                         switch (lp1) {
4484                                         case 0:
4485                                                 rFalseIfx.condition ^= 1;
4486                                                 genSkipCond(&rFalseIfx,right,0,7);
4487                                                 break;
4488                                         case 0x7f:
4489                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4490                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4491                                                 genSkipz2(&rFalseIfx,1);
4492                                                 break;
4493                                         default:
4494                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4495                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4496                                                 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4497                                                 rFalseIfx.condition ^= 1;
4498                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4499                                                 break;
4500                                         }
4501                                         if(ifx) ifx->generated = 1;
4502                                 } else {
4503                                         /* unsigned comparisons to a literal byte */
4504                                         
4505                                         switch(lit & 0xff ) {
4506                                         case 0:
4507                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4508                                                 genSkipz2(&rFalseIfx,0);
4509                                                 if(ifx) ifx->generated = 1;
4510                                                 break;
4511                                         case 0x7f:
4512                                                 genSkipCond(&rFalseIfx,right,0,7);
4513                                                 if(ifx) ifx->generated = 1;
4514                                                 break;
4515                                                 
4516                                         default:
4517                                                 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4518                                                 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4519                                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4520                                                 rFalseIfx.condition ^= 1;
4521                                                 if (AOP_TYPE(result) == AOP_CRY) {
4522                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4523                                                         if(ifx) ifx->generated = 1;
4524                                                 } else {
4525                                                         DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4526                                                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4527                                                         emitpcode(POC_RLF, popGet(AOP(result),0));
4528                                                         emitpcode(POC_MOVLW, popGetLit(0x01));
4529                                                         emitpcode(POC_XORWF, popGet(AOP(result),0));
4530                                                 }       
4531                                                 break;
4532                                         }
4533                                 }
4534                                 
4535                                 //goto check_carry;
4536                                 return;
4537                                 
4538                         } else {
4539                                 
4540                                 /* Size is greater than 1 */
4541                                 
4542                                 if(sign) {
4543                                         int lp1 = lit+1;
4544                                         
4545                                         size--;
4546                                         
4547                                         if(lp1 == 0) {
4548                                                 /* this means lit = 0xffffffff, or -1 */
4549                                                 
4550                                                 
4551                                                 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4552                                                 rFalseIfx.condition ^= 1;
4553                                                 genSkipCond(&rFalseIfx,right,size,7);
4554                                                 if(ifx) ifx->generated = 1;
4555                                                 return;
4556                                         }
4557                                         
4558                                         if(lit == 0) {
4559                                                 int s = size;
4560                                                 
4561                                                 if(rFalseIfx.condition) {
4562                                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4563                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4564                                                 }
4565                                                 
4566                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4567                                                 while(size--)
4568                                                         emitpcode(POC_IORFW, popGet(AOP(right),size));
4569                                                 
4570                                                 
4571                                                 emitSKPZ;
4572                                                 if(rFalseIfx.condition) {
4573                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4574                                                         emitpLabel(truelbl->key);
4575                                                 }else {
4576                                                         rFalseIfx.condition ^= 1;
4577                                                         genSkipCond(&rFalseIfx,right,s,7);
4578                                                 }
4579                                                 
4580                                                 if(ifx) ifx->generated = 1;
4581                                                 return;
4582                                         }
4583                                         
4584                                         if((size == 1) &&  (0 == (lp1&0xff))) {
4585                                                 /* lower byte of signed word is zero */
4586                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4587                                                 i = ((lp1 >> 8) & 0xff) ^0x80;
4588                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4589                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4590                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4591                                                 rFalseIfx.condition ^= 1;
4592                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4593                                                 
4594                                                 
4595                                                 if(ifx) ifx->generated = 1;
4596                                                 return;
4597                                         }
4598                                         
4599                                         if(lit & (0x80 << (size*8))) {
4600                                                 /* Lit is less than zero */
4601                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4602                                                 //rFalseIfx.condition ^= 1;
4603                                                 //genSkipCond(&rFalseIfx,left,size,7);
4604                                                 //rFalseIfx.condition ^= 1;
4605                                                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4606                                                 //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4607                                                 
4608                                                 if(rFalseIfx.condition)
4609                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4610                                                 else
4611                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4612                                                 
4613                                                 
4614                                         } else {
4615                                                 /* Lit is greater than or equal to zero */
4616                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4617                                                 //rFalseIfx.condition ^= 1;
4618                                                 //genSkipCond(&rFalseIfx,right,size,7);
4619                                                 //rFalseIfx.condition ^= 1;
4620                                                 
4621                                                 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4622                                                 //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4623                                                 
4624                                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4625                                                 if(rFalseIfx.condition)
4626                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4627                                                 else
4628                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4629                                                 
4630                                         }
4631                                         
4632                                         
4633                                         emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4634                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4635                                         
4636                                         while(size--) {
4637                                                 
4638                                                 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4639                                                 emitSKPNZ;
4640                                                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4641                                         }
4642                                         rFalseIfx.condition ^= 1;
4643                                         //rFalseIfx.condition = 1;
4644                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4645                                         
4646                                         emitpLabel(truelbl->key);
4647                                         
4648                                         if(ifx) ifx->generated = 1;
4649                                         return;
4650                                         // end of if (sign)
4651                                 } else {
4652                                         
4653                                         /* compare word or long to an unsigned literal on the right.*/
4654                                         
4655                                         
4656                                         size--;
4657                                         if(lit < 0xff) {
4658                                                 DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4659                                                 switch (lit) {
4660                                                 case 0:
4661                                                         break; /* handled above */
4662                                                 /*
4663                                                 case 0xff:
4664                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4665                                                         while(size--)
4666                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4667                                                         genSkipz2(&rFalseIfx,0);
4668                                                         break;
4669                                                 */
4670                                                 default:
4671                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4672                                                         while(--size)
4673                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4674                                                         
4675                                                         emitSKPZ;
4676                                                         if(rFalseIfx.condition)
4677                                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4678                                                         else
4679                                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4680                                                         
4681                                                         
4682                                                         emitpcode(POC_MOVLW, popGetLit(lit+1));
4683                                                         emitpcode(POC_SUBFW, popGet(AOP(right),0));
4684                                                         
4685                                                         rFalseIfx.condition ^= 1;
4686                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4687                                                 }
4688                                                 
4689                                                 emitpLabel(truelbl->key);
4690                                                 
4691                                                 if(ifx) ifx->generated = 1;
4692                                                 return;
4693                                         }
4694                                         
4695                                         
4696                                         lit++;
4697                                         DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4698                                         i = (lit >> (size*8)) & 0xff;
4699                                         
4700                                         emitpcode(POC_MOVLW, popGetLit(i));
4701                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4702                                         
4703                                         while(size--) {
4704                                                 i = (lit >> (size*8)) & 0xff;
4705                                                 
4706                                                 if(i) {
4707                                                         emitpcode(POC_MOVLW, popGetLit(i));
4708                                                         emitSKPNZ;
4709                                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4710                                                 } else {
4711                                                 /* this byte of the lit is zero, 
4712                                                         *if it's not the last then OR in the variable */
4713                                                         if(size)
4714                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4715                                                 }
4716                                         }
4717                                         
4718                                         
4719                                         emitpLabel(lbl->key);
4720                                         
4721                                         rFalseIfx.condition ^= 1;
4722                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4723                                 }
4724                                 
4725                                 if(sign)
4726                                         emitpLabel(truelbl->key);
4727                                 if(ifx) ifx->generated = 1;
4728                                 return;
4729                         }
4730                 }
4731                 /* Compare two variables */
4732                 
4733                 DEBUGpic14_emitcode(";sign","%d",sign);
4734                 
4735                 size--;
4736                 if(sign) {
4737                         /* Sigh. thus sucks... */
4738                         if(size) {
4739                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4740                                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4741                                 emitpcode(POC_MOVLW, popGetLit(0x80));
4742                                 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4743                                 emitpcode(POC_XORFW, popGet(AOP(right),size));
4744                                 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4745                         } else {
4746                                 /* Signed char comparison */
4747                                 /* Special thanks to Nikolai Golovchenko for this snippet */
4748                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4749                                 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4750                                 emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4751                                 emitpcode(POC_XORFW, popGet(AOP(left),0));
4752                                 emitpcode(POC_XORFW, popGet(AOP(right),0));
4753                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4754                                 
4755                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4756                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4757                                 
4758                                 if(ifx) ifx->generated = 1;
4759                                 return;
4760                         }
4761                         
4762                 } else {
4763                         
4764                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4765                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4766                 }
4767                 
4768                 
4769                 /* The rest of the bytes of a multi-byte compare */
4770                 while (size) {
4771                         
4772                         emitSKPZ;
4773                         emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4774                         size--;
4775                         
4776                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4777                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4778                         
4779                         
4780                 }
4781                 
4782                 emitpLabel(lbl->key);
4783                 
4784                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4785                 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4786                         (AOP_TYPE(result) == AOP_REG)) {
4787                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4788                         emitpcode(POC_RLF, popGet(AOP(result),0));
4789                 } else {
4790                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4791                 }       
4792                 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4793                 if(ifx) ifx->generated = 1;
4794                 
4795                 return;
4796                 
4797         }
4798         
4799         // check_carry:
4800         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4801                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4802                 pic14_outBitC(result);
4803         } else {
4804                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4805                 /* if the result is used in the next
4806                 ifx conditional branch then generate
4807                 code a little differently */
4808                 if (ifx )
4809                         genIfxJump (ifx,"c");
4810                 else
4811                         pic14_outBitC(result);
4812                 /* leave the result in acc */
4813         }
4814         
4815 }
4816 #endif
4817
4818 /*-----------------------------------------------------------------*/
4819 /* genCmpGt :- greater than comparison                             */
4820 /*-----------------------------------------------------------------*/
4821 static void genCmpGt (iCode *ic, iCode *ifx)
4822 {
4823         operand *left, *right, *result;
4824         sym_link *letype , *retype;
4825         int sign ;
4826         
4827         FENTRY;
4828         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4829         left = IC_LEFT(ic);
4830         right= IC_RIGHT(ic);
4831         result = IC_RESULT(ic);
4832         
4833         letype = getSpec(operandType(left));
4834         retype =getSpec(operandType(right));
4835         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4836         /* assign the amsops */
4837         aopOp (left,ic,FALSE);
4838         aopOp (right,ic,FALSE);
4839         aopOp (result,ic,TRUE);
4840         
4841         genCmp(right, left, result, ifx, sign);
4842         
4843         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4844         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4845         freeAsmop(result,NULL,ic,TRUE); 
4846 }
4847
4848 /*-----------------------------------------------------------------*/
4849 /* genCmpLt - less than comparisons                                */
4850 /*-----------------------------------------------------------------*/
4851 static void genCmpLt (iCode *ic, iCode *ifx)
4852 {
4853         operand *left, *right, *result;
4854         sym_link *letype , *retype;
4855         int sign ;
4856         
4857         FENTRY;
4858         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4859         left = IC_LEFT(ic);
4860         right= IC_RIGHT(ic);
4861         result = IC_RESULT(ic);
4862         
4863         letype = getSpec(operandType(left));
4864         retype =getSpec(operandType(right));
4865         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4866         
4867         /* assign the amsops */
4868         aopOp (left,ic,FALSE);
4869         aopOp (right,ic,FALSE);
4870         aopOp (result,ic,TRUE);
4871         
4872         genCmp(left, right, result, ifx, sign);
4873         
4874         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4875         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4876         freeAsmop(result,NULL,ic,TRUE); 
4877 }
4878
4879 #if 0
4880 /*-----------------------------------------------------------------*/
4881 /* genc16bit2lit - compare a 16 bit value to a literal             */
4882 /*-----------------------------------------------------------------*/
4883 static void genc16bit2lit(operand *op, int lit, int offset)
4884 {
4885         int i;
4886         
4887         FENTRY;
4888         DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4889         if( (lit&0xff) == 0) 
4890                 i=1;
4891         else
4892                 i=0;
4893         
4894         switch( BYTEofLONG(lit,i)) { 
4895         case 0:
4896                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4897                 break;
4898         case 1:
4899                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4900                 break;
4901         case 0xff:
4902                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4903                 break;
4904         default:
4905                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4906                 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4907         }
4908         
4909         i ^= 1;
4910         
4911         switch( BYTEofLONG(lit,i)) { 
4912         case 0:
4913                 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4914                 break;
4915         case 1:
4916                 emitSKPNZ;
4917                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4918                 break;
4919         case 0xff:
4920                 emitSKPNZ;
4921                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4922                 break;
4923         default:
4924                 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4925                 emitSKPNZ;
4926                 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4927                 
4928         }
4929         
4930 }
4931 #endif
4932
4933 #if 0
4934 /*-----------------------------------------------------------------*/
4935 /* gencjneshort - compare and jump if not equal                    */
4936 /*-----------------------------------------------------------------*/
4937 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4938 {
4939         int size = min(AOP_SIZE(left),AOP_SIZE(right));
4940         int offset = 0;
4941         //resolvedIfx rIfx;
4942         symbol *lbl;
4943         
4944         //unsigned long lit = 0L;
4945         FENTRY;
4946         if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4947           emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4948           return;
4949         }
4950         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4951         DEBUGpic14_AopType(__LINE__,left,right,result);
4952         
4953         assert (!pic14_sameRegs (AOP(left), AOP(result)));
4954         assert (!pic14_sameRegs (AOP(right), AOP(result)));
4955         if (AOP_SIZE(result)) {
4956           for (offset = 0; offset < AOP_SIZE(result); offset++)
4957             emitpcode (POC_CLRF, popGet (AOP(result), offset));
4958         }
4959         
4960         assert (AOP_SIZE(left) == AOP_SIZE(right));
4961         //resolveIfx(&rIfx,ifx);
4962         lbl = newiTempLabel (NULL);
4963         while (size--)
4964         {
4965           mov2w (AOP(right),size);
4966           emitpcode (POC_XORFW, popGet (AOP(left), size));
4967           if (size)
4968           {
4969             emitSKPZ;
4970             emitpcode (POC_GOTO, popGetLabel (lbl->key));
4971           }
4972         } // while
4973         emitpLabel (lbl->key);
4974         if (AOP_SIZE(result)) {
4975           emitSKPNZ;
4976           emitpcode (POC_INCF, popGet (AOP(result), 0));
4977         } else {
4978           assert (ifx);
4979           genSkipz (ifx, NULL != IC_TRUE(ifx));
4980           ifx->generated = 1;
4981         }
4982         return;
4983 #if 0   
4984         if(result)
4985         {
4986                 DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4987                 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4988                 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4989                 for (offset=0; offset < AOP_SIZE(result); offset++)
4990                 {
4991                         emitpcode (POC_CLRF, popGet (AOP(result), offset));
4992                 } // for offset
4993         }
4994         
4995         
4996         /* if the left side is a literal or 
4997         if the right is in a pointer register and left 
4998         is not */
4999         if ((AOP_TYPE(left) == AOP_LIT) || 
5000                 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5001                 operand *t = right;
5002                 right = left;
5003                 left = t;
5004         }
5005         if(AOP_TYPE(right) == AOP_LIT)
5006                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5007         
5008         /* if the right side is a literal then anything goes */
5009         if (AOP_TYPE(right) == AOP_LIT &&
5010                 AOP_TYPE(left) != AOP_DIR ) {
5011                 switch(size) {
5012                 case 2:
5013                         genc16bit2lit(left, lit, 0);
5014                         emitSKPNZ;
5015                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
5016                         break;
5017                 default:
5018                         offset = 0;
5019                         while (size--) {
5020                                 if(lit & 0xff) {
5021                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5022                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5023                                 } else {
5024                                         emitpcode(POC_MOVF,popGet(AOP(left),offset));
5025                                 }
5026                                 
5027                                 emitSKPNZ;
5028                                 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5029                                 offset++;
5030                                 lit >>= 8;
5031                         }
5032                         break;
5033                 }
5034         }
5035         
5036         /* if the right side is in a register or in direct space or
5037         if the left is a pointer register & right is not */    
5038         else if (AOP_TYPE(right) == AOP_REG ||
5039                 AOP_TYPE(right) == AOP_DIR || 
5040                 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5041                 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5042                 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5043                 int lbl_key = lbl->key;
5044                 
5045                 if(!result) {
5046                         DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5047                         fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5048                                 __FUNCTION__,__LINE__);
5049                         return;
5050                 }
5051                 
5052                 /*     switch(size) { */
5053                 /*     case 2: */
5054                 /*       genc16bit2lit(left, lit, 0); */
5055                 /*       emitSKPNZ; */
5056                 /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
5057                 /*       break; */
5058                 /*     default: */
5059                 offset = 0;
5060                 while (size--) {
5061                         int emit_skip=1;
5062                         if((AOP_TYPE(left) == AOP_DIR) && 
5063                                 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5064                                 
5065                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5066                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5067                                 
5068                         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5069                                 
5070                                 switch (lit & 0xff) {
5071                                 case 0:
5072                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5073                                         break;
5074                                 case 1:
5075                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5076                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5077                                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
5078                                         emit_skip=0;
5079                                         break;
5080                                 case 0xff:
5081                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5082                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5083                                         //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5084                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5085                                         emit_skip=0;
5086                                         break;
5087                                 default:
5088                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5089                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5090                                 }
5091                                 lit >>= 8;
5092                                 
5093                         } else {
5094                                 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5095                         }
5096                         if(emit_skip) {
5097                                 if(AOP_TYPE(result) == AOP_CRY) {
5098                                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5099                                         if(rIfx.condition)
5100                                                 emitSKPNZ;
5101                                         else
5102                                                 emitSKPZ;
5103                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5104                                 } else {
5105                                         /* fix me. probably need to check result size too */
5106                                         //emitpcode(POC_CLRF,popGet(AOP(result),0));
5107                                         if(rIfx.condition)
5108                                                 emitSKPZ;
5109                                         else
5110                                                 emitSKPNZ;
5111                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5112                                 }
5113                                 if(ifx)
5114                                         ifx->generated=1;
5115                         }
5116                         emit_skip++;
5117                         offset++;
5118                 }
5119                 /*       break; */
5120                 /*     } */
5121         } else if(AOP_TYPE(right) == AOP_REG &&
5122                 AOP_TYPE(left) != AOP_DIR){
5123
5124                 offset = 0;
5125                 while(size--) {
5126                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5127                         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5128                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5129                         if(rIfx.condition)
5130                                 emitSKPNZ;
5131                         else
5132                                 emitSKPZ;
5133                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5134                         offset++;
5135                 }
5136                 
5137         }else{
5138                 /* right is a pointer reg need both a & b */
5139                 offset = 0;
5140                 while(size--) {
5141                         char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5142                         if(strcmp(l,"b"))
5143                                 pic14_emitcode("mov","b,%s",l);
5144                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5145                         pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5146                         offset++;
5147                 }
5148         }
5149         
5150         emitpcode(POC_INCF,popGet(AOP(result),0));
5151         if(!rIfx.condition)
5152                 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5153         
5154         emitpLabel(lbl->key);
5155         
5156         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5157         
5158         if(ifx)
5159                 ifx->generated = 1;
5160 #endif
5161 }
5162 #endif
5163
5164 #if 0
5165 /*-----------------------------------------------------------------*/
5166 /* gencjne - compare and jump if not equal                         */
5167 /*-----------------------------------------------------------------*/
5168 static void gencjne(operand *left, operand *right, iCode *ifx)
5169 {
5170         symbol *tlbl  = newiTempLabel(NULL);
5171         
5172         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5173         gencjneshort(left, right, lbl);
5174         
5175         pic14_emitcode("mov","a,%s",one);
5176         pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5177         pic14_emitcode("","%05d_DS_:",lbl->key+100);
5178         pic14_emitcode("clr","a");
5179         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5180         
5181         emitpLabel(lbl->key);
5182         emitpLabel(tlbl->key);
5183         
5184 }
5185 #endif
5186
5187 /*-----------------------------------------------------------------*/
5188 /* genCmpEq - generates code for equal to                          */
5189 /*-----------------------------------------------------------------*/
5190 static void genCmpEq (iCode *ic, iCode *ifx)
5191 {
5192   operand *left, *right, *result;
5193   int size;
5194   symbol *false_label;
5195
5196   FENTRY;
5197   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5198
5199   if(ifx)
5200     DEBUGpic14_emitcode ("; ifx is non-null","");
5201   else
5202     DEBUGpic14_emitcode ("; ifx is null","");
5203
5204   aopOp((left=IC_LEFT(ic)),ic,FALSE);
5205   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5206   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5207
5208   DEBUGpic14_AopType(__LINE__,left,right,result);
5209
5210   /* if literal, move literal to right */ 
5211   if (op_isLitLike (IC_LEFT(ic))) {
5212     operand *tmp = right ;
5213     right = left;
5214     left = tmp;
5215   }
5216
5217   false_label = NULL;
5218   if (ifx && !IC_TRUE(ifx))
5219   {
5220     assert (IC_FALSE(ifx));
5221     false_label = IC_FALSE(ifx);
5222   }
5223
5224   size = min(AOP_SIZE(left),AOP_SIZE(right));
5225   assert(!pic14_sameRegs(AOP(result),AOP(left)));
5226   assert(!pic14_sameRegs(AOP(result),AOP(right)));
5227
5228   /* assume left != right */
5229   {
5230     int i;
5231     for (i=0; i < AOP_SIZE(result); i++)
5232     {
5233       emitpcode(POC_CLRF, popGet(AOP(result),i));
5234     }
5235   }
5236
5237   if (AOP_TYPE(right) == AOP_LIT)
5238   {
5239     unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5240     int i;
5241     size = AOP_SIZE(left);
5242     assert(!op_isLitLike(left));
5243
5244     switch (lit)
5245     {
5246       case 0:
5247         mov2w(AOP(left), 0);
5248         for (i=1; i < size; i++)
5249           emitpcode(POC_IORFW,popGet(AOP(left),i));
5250         /* now Z is set iff `left == right' */
5251         emitSKPZ;
5252         if (!false_label) false_label = newiTempLabel(NULL);
5253         emitpcode(POC_GOTO, popGetLabel(false_label->key));
5254         break;
5255
5256       default:
5257         for (i=0; i < size; i++)
5258         {
5259           mov2w(AOP(left),i);
5260           emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5261           /* now Z is cleared if `left != right' */
5262           emitSKPZ;
5263           if (!false_label) false_label = newiTempLabel(NULL);
5264           emitpcode(POC_GOTO, popGetLabel(false_label->key));
5265         } // for i
5266         break;
5267     } // switch (lit)
5268   }
5269   else
5270   {
5271     /* right is no literal */
5272     int i;
5273
5274     for (i=0; i < size; i++)
5275     {
5276       mov2w(AOP(right),i);
5277       emitpcode(POC_XORFW,popGet(AOP(left),i));
5278       /* now Z is cleared if `left != right' */
5279       emitSKPZ;
5280       if (!false_label) false_label = newiTempLabel(NULL);
5281       emitpcode(POC_GOTO, popGetLabel(false_label->key));
5282     } // for i
5283   }
5284
5285   /* if we reach here, left == right */
5286
5287   if (AOP_SIZE(result) > 0)
5288   {
5289     emitpcode(POC_INCF, popGet(AOP(result),0));
5290   }
5291
5292   if (ifx && IC_TRUE(ifx))
5293   {
5294     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5295   }
5296
5297   if (false_label && (!ifx || IC_TRUE(ifx)))
5298     emitpLabel(false_label->key);
5299
5300   if (ifx) ifx->generated = 1;
5301
5302   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5303   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5304   freeAsmop(result,NULL,ic,TRUE);
5305 }
5306
5307 /*-----------------------------------------------------------------*/
5308 /* ifxForOp - returns the icode containing the ifx for operand     */
5309 /*-----------------------------------------------------------------*/
5310 static iCode *ifxForOp ( operand *op, iCode *ic )
5311 {
5312         FENTRY;
5313         /* if true symbol then needs to be assigned */
5314         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5315         if (IS_TRUE_SYMOP(op))
5316                 return NULL ;
5317         
5318         /* if this has register type condition and
5319         the next instruction is ifx with the same operand
5320         and live to of the operand is upto the ifx only then */
5321         if (ic->next &&
5322                 ic->next->op == IFX &&
5323                 IC_COND(ic->next)->key == op->key &&
5324                 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5325                 return ic->next;
5326         
5327         if (ic->next &&
5328                 ic->next->op == IFX &&
5329                 IC_COND(ic->next)->key == op->key) {
5330                 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5331                 return ic->next;
5332         }
5333         
5334         DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5335         if (ic->next &&
5336                 ic->next->op == IFX)
5337                 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5338         
5339         if (ic->next &&
5340                 ic->next->op == IFX &&
5341                 IC_COND(ic->next)->key == op->key) {
5342                 DEBUGpic14_emitcode ("; "," key is okay");
5343                 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5344                         OP_SYMBOL(op)->liveTo,
5345                         ic->next->seq);
5346         }
5347         
5348         
5349         return NULL;
5350 }
5351 /*-----------------------------------------------------------------*/
5352 /* genAndOp - for && operation                                     */
5353 /*-----------------------------------------------------------------*/
5354 static void genAndOp (iCode *ic)
5355 {
5356         operand *left,*right, *result;
5357         /*     symbol *tlbl; */
5358         
5359         FENTRY;
5360         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5361         /* note here that && operations that are in an
5362         if statement are taken away by backPatchLabels
5363         only those used in arthmetic operations remain */
5364         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5365         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5366         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5367         
5368         DEBUGpic14_AopType(__LINE__,left,right,result);
5369         
5370         emitpcode(POC_MOVFW,popGet(AOP(left),0));
5371         emitpcode(POC_ANDFW,popGet(AOP(right),0));
5372         emitpcode(POC_MOVWF,popGet(AOP(result),0));
5373         
5374         /* if both are bit variables */
5375         /*     if (AOP_TYPE(left) == AOP_CRY && */
5376         /*         AOP_TYPE(right) == AOP_CRY ) { */
5377         /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5378         /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5379         /*         pic14_outBitC(result); */
5380         /*     } else { */
5381         /*         tlbl = newiTempLabel(NULL); */
5382         /*         pic14_toBoolean(left);     */
5383         /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5384         /*         pic14_toBoolean(right); */
5385         /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5386         /*         pic14_outBitAcc(result); */
5387         /*     } */
5388         
5389         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5390         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5391         freeAsmop(result,NULL,ic,TRUE);
5392 }
5393
5394
5395 /*-----------------------------------------------------------------*/
5396 /* genOrOp - for || operation                                      */
5397 /*-----------------------------------------------------------------*/
5398 /*
5399 tsd pic port -
5400 modified this code, but it doesn't appear to ever get called
5401 */
5402
5403 static void genOrOp (iCode *ic)
5404 {
5405         operand *left,*right, *result;
5406         symbol *tlbl;
5407         int i;
5408         
5409         /* note here that || operations that are in an
5410         if statement are taken away by backPatchLabels
5411         only those used in arthmetic operations remain */
5412         FENTRY;
5413         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5414         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5415         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5416         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5417         
5418         DEBUGpic14_AopType(__LINE__,left,right,result);
5419
5420         for (i=0; i < AOP_SIZE(result); i++)
5421         {
5422                 emitpcode(POC_CLRF, popGet(AOP(result), i));
5423         } // for i
5424
5425         tlbl = newiTempLabel(NULL);
5426         pic14_toBoolean(left);
5427         emitSKPZ;
5428         emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5429         pic14_toBoolean(right);
5430         emitpLabel(tlbl->key);
5431         /* here Z is clear IFF `left || right' */
5432         emitSKPZ;
5433         emitpcode(POC_INCF, popGet(AOP(result), 0));
5434         
5435         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5436         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5437         freeAsmop(result,NULL,ic,TRUE);            
5438 }
5439
5440 /*-----------------------------------------------------------------*/
5441 /* isLiteralBit - test if lit == 2^n                               */
5442 /*-----------------------------------------------------------------*/
5443 static int isLiteralBit(unsigned long lit)
5444 {
5445         unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5446                 0x100L,0x200L,0x400L,0x800L,
5447                 0x1000L,0x2000L,0x4000L,0x8000L,
5448                 0x10000L,0x20000L,0x40000L,0x80000L,
5449                 0x100000L,0x200000L,0x400000L,0x800000L,
5450                 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5451                 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5452         int idx;
5453         
5454         FENTRY;
5455         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5456         for(idx = 0; idx < 32; idx++)
5457                 if(lit == pw[idx])
5458                         return idx+1;
5459                 return 0;
5460 }
5461
5462 /*-----------------------------------------------------------------*/
5463 /* continueIfTrue -                                                */
5464 /*-----------------------------------------------------------------*/
5465 static void continueIfTrue (iCode *ic)
5466 {
5467         FENTRY;
5468         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5469         if(IC_TRUE(ic))
5470                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5471         ic->generated = 1;
5472 }
5473
5474 /*-----------------------------------------------------------------*/
5475 /* jmpIfTrue -                                                     */
5476 /*-----------------------------------------------------------------*/
5477 static void jumpIfTrue (iCode *ic)
5478 {
5479         FENTRY;
5480         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5481         if(!IC_TRUE(ic))
5482                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5483         ic->generated = 1;
5484 }
5485
5486 /*-----------------------------------------------------------------*/
5487 /* jmpTrueOrFalse -                                                */
5488 /*-----------------------------------------------------------------*/
5489 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5490 {
5491         FENTRY;
5492         // ugly but optimized by peephole
5493         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5494         if(IC_TRUE(ic)){
5495                 symbol *nlbl = newiTempLabel(NULL);
5496                 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5497                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5498                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5499                 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5500         }
5501         else{
5502                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5503                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5504         }
5505         ic->generated = 1;
5506 }
5507
5508 /*-----------------------------------------------------------------*/
5509 /* genAnd  - code for and                                          */
5510 /*-----------------------------------------------------------------*/
5511 static void genAnd (iCode *ic, iCode *ifx)
5512 {
5513         operand *left, *right, *result;
5514         int size, offset=0;  
5515         unsigned long lit = 0L;
5516         int bytelit = 0;
5517         resolvedIfx rIfx;
5518         
5519         FENTRY;
5520         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5521         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5522         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5523         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5524         
5525         resolveIfx(&rIfx,ifx);
5526         
5527         /* if left is a literal & right is not then exchange them */
5528         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5529                 AOP_NEEDSACC(left)) {
5530                 operand *tmp = right ;
5531                 right = left;
5532                 left = tmp;
5533         }
5534         
5535         /* if result = right then exchange them */
5536         if(pic14_sameRegs(AOP(result),AOP(right))){
5537                 operand *tmp = right ;
5538                 right = left;
5539                 left = tmp;
5540         }
5541         
5542         /* if right is bit then exchange them */
5543         if (AOP_TYPE(right) == AOP_CRY &&
5544                 AOP_TYPE(left) != AOP_CRY){
5545                 operand *tmp = right ;
5546                 right = left;
5547                 left = tmp;
5548         }
5549         if(AOP_TYPE(right) == AOP_LIT)
5550                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5551         
5552         size = AOP_SIZE(result);
5553         
5554         DEBUGpic14_AopType(__LINE__,left,right,result);
5555         
5556         // if(bit & yy)
5557         // result = bit & yy;
5558         if (AOP_TYPE(left) == AOP_CRY){
5559                 // c = bit & literal;
5560                 if(AOP_TYPE(right) == AOP_LIT){
5561                         if(lit & 1) {
5562                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5563                                         // no change
5564                                         goto release;
5565                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5566                         } else {
5567                                 // bit(result) = 0;
5568                                 if(size && (AOP_TYPE(result) == AOP_CRY)){
5569                                         pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5570                                         goto release;
5571                                 }
5572                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5573                                         jumpIfTrue(ifx);
5574                                         goto release;
5575                                 }
5576                                 pic14_emitcode("clr","c");
5577                         }
5578                 } else {
5579                         if (AOP_TYPE(right) == AOP_CRY){
5580                                 // c = bit & bit;
5581                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5582                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5583                         } else {
5584                                 // c = bit & val;
5585                                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5586                                 // c = lsb
5587                                 pic14_emitcode("rrc","a");
5588                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5589                         }
5590                 }
5591                 // bit = c
5592                 // val = c
5593                 if(size)
5594                         pic14_outBitC(result);
5595                 // if(bit & ...)
5596                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5597                         genIfxJump(ifx, "c");           
5598                 goto release ;
5599         }
5600         
5601         // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5602         // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5603         if((AOP_TYPE(right) == AOP_LIT) &&
5604                 (AOP_TYPE(result) == AOP_CRY) &&
5605                 (AOP_TYPE(left) != AOP_CRY)){
5606                 int posbit = isLiteralBit(lit);
5607                 /* left &  2^n */
5608                 if(posbit){
5609                         posbit--;
5610                         //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5611                         // bit = left & 2^n
5612                         if(size)
5613                                 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5614                         // if(left &  2^n)
5615                         else{
5616                                 if(ifx){
5617                                         int offset = 0;
5618                                         while (posbit > 7) {
5619                                                 posbit -= 8;
5620                                                 offset++;
5621                                         }
5622                                         emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5623                                                 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5624                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5625                                         
5626                                         ifx->generated = 1;
5627                                 }
5628                                 goto release;
5629                         }
5630                 } else {
5631                         symbol *tlbl = newiTempLabel(NULL);
5632                         int sizel = AOP_SIZE(left);
5633                         if(size)
5634                                 pic14_emitcode("setb","c");
5635                         while(sizel--){
5636                                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5637                                         MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5638                                         // byte ==  2^n ?
5639                                         if((posbit = isLiteralBit(bytelit)) != 0)
5640                                                 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5641                                         else{
5642                                                 if(bytelit != 0x0FFL)
5643                                                         pic14_emitcode("anl","a,%s",
5644                                                         aopGet(AOP(right),offset,FALSE,TRUE));
5645                                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5646                                         }
5647                                 }
5648                                 offset++;
5649                         }
5650                         // bit = left & literal
5651                         if(size){
5652                                 pic14_emitcode("clr","c");
5653                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5654                         }
5655                         // if(left & literal)
5656                         else{
5657                                 if(ifx)
5658                                         jmpTrueOrFalse(ifx, tlbl);
5659                                 goto release ;
5660                         }
5661                 }
5662                 pic14_outBitC(result);
5663                 goto release ;
5664         }
5665         
5666         /* if left is same as result */
5667         if(pic14_sameRegs(AOP(result),AOP(left))){
5668                 int know_W = -1;
5669                 for(;size--; offset++,lit>>=8) {
5670                         if(AOP_TYPE(right) == AOP_LIT){
5671                                 switch(lit & 0xff) {
5672                                 case 0x00:
5673                                         /*  and'ing with 0 has clears the result */
5674                                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
5675                                         break;
5676                                 case 0xff:
5677                                         /* and'ing with 0xff is a nop when the result and left are the same */
5678                                         break;
5679                                         
5680                                 default:
5681                                         {
5682                                                 int p = my_powof2( (~lit) & 0xff );
5683                                                 if(p>=0) {
5684                                                         /* only one bit is set in the literal, so use a bcf instruction */
5685                                                         emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5686                                                         
5687                                                 } else {
5688                                                         if(know_W != (int)(lit&0xff))
5689                                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5690                                                         know_W = lit &0xff;
5691                                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5692                                                 }
5693                                         }    
5694                                 }
5695                         } else {
5696                                 if (AOP_TYPE(left) == AOP_ACC) {
5697                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5698                                 } else {        
5699                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5700                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5701                                         
5702                                 }
5703                         }
5704                 }
5705                 
5706         } else {
5707                 // left & result in different registers
5708                 if(AOP_TYPE(result) == AOP_CRY){
5709                         // result = bit
5710                         // if(size), result in bit
5711                         // if(!size && ifx), conditional oper: if(left & right)
5712                         symbol *tlbl = newiTempLabel(NULL);
5713                         int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5714                         if(size)
5715                                 pic14_emitcode("setb","c");
5716                         while(sizer--){
5717                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5718                                 pic14_emitcode("anl","a,%s",
5719                                         aopGet(AOP(left),offset,FALSE,FALSE));
5720                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5721                                 offset++;
5722                         }
5723                         if(size){
5724                                 CLRC;
5725                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5726                                 pic14_outBitC(result);
5727                         } else if(ifx)
5728                                 jmpTrueOrFalse(ifx, tlbl);
5729                 } else {
5730                         for(;(size--);offset++) {
5731                                 // normal case
5732                                 // result = left & right
5733                                 if(AOP_TYPE(right) == AOP_LIT){
5734                                         int t = (lit >> (offset*8)) & 0x0FFL;
5735                                         switch(t) { 
5736                                         case 0x00:
5737                                                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5738                                                 break;
5739                                         case 0xff:
5740                                                 if(AOP_TYPE(left) != AOP_ACC) {
5741                                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5742                                                 }
5743                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5744                                                 break;
5745                                         default:
5746                                                 if(AOP_TYPE(left) == AOP_ACC) {
5747                                                         emitpcode(POC_ANDLW, popGetLit(t));
5748                                                 } else {
5749                                                         emitpcode(POC_MOVLW, popGetLit(t));
5750                                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5751                                                 }
5752                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5753                                         }
5754                                         continue;
5755                                 }
5756                                 
5757                                 if (AOP_TYPE(left) == AOP_ACC) {
5758                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5759                                 } else {
5760                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5761                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5762                                 }
5763                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5764                         }
5765                 }
5766         }
5767         
5768 release :
5769         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5770         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5771         freeAsmop(result,NULL,ic,TRUE);     
5772 }
5773
5774 /*-----------------------------------------------------------------*/
5775 /* genOr  - code for or                                            */
5776 /*-----------------------------------------------------------------*/
5777 static void genOr (iCode *ic, iCode *ifx)
5778 {
5779         operand *left, *right, *result;
5780         int size, offset=0;
5781         unsigned long lit = 0L;
5782         
5783         FENTRY;
5784         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5785         
5786         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5787         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5788         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5789         
5790         DEBUGpic14_AopType(__LINE__,left,right,result);
5791         
5792         /* if left is a literal & right is not then exchange them */
5793         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5794                 AOP_NEEDSACC(left)) {
5795                 operand *tmp = right ;
5796                 right = left;
5797                 left = tmp;
5798         }
5799         
5800         /* if result = right then exchange them */
5801         if(pic14_sameRegs(AOP(result),AOP(right))){
5802                 operand *tmp = right ;
5803                 right = left;
5804                 left = tmp;
5805         }
5806         
5807         /* if right is bit then exchange them */
5808         if (AOP_TYPE(right) == AOP_CRY &&
5809                 AOP_TYPE(left) != AOP_CRY){
5810                 operand *tmp = right ;
5811                 right = left;
5812                 left = tmp;
5813         }
5814         
5815         DEBUGpic14_AopType(__LINE__,left,right,result);
5816         
5817         if(AOP_TYPE(right) == AOP_LIT)
5818                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5819         
5820         size = AOP_SIZE(result);
5821         
5822         // if(bit | yy)
5823         // xx = bit | yy;
5824         if (AOP_TYPE(left) == AOP_CRY){
5825                 if(AOP_TYPE(right) == AOP_LIT){
5826                         // c = bit & literal;
5827                         if(lit){
5828                                 // lit != 0 => result = 1
5829                                 if(AOP_TYPE(result) == AOP_CRY){
5830                                         if(size)
5831                                                 emitpcode(POC_BSF, popGet(AOP(result),0));
5832                                         //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5833                                         //   AOP(result)->aopu.aop_dir,
5834                                         //   AOP(result)->aopu.aop_dir);
5835                                         else if(ifx)
5836                                                 continueIfTrue(ifx);
5837                                         goto release;
5838                                 }
5839                         } else {
5840                                 // lit == 0 => result = left
5841                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5842                                         goto release;
5843                                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5844                         }
5845                 } else {
5846                         if (AOP_TYPE(right) == AOP_CRY){
5847                                 if(pic14_sameRegs(AOP(result),AOP(left))){
5848                                         // c = bit | bit;
5849                                         emitpcode(POC_BCF,   popGet(AOP(result),0));
5850                                         emitpcode(POC_BTFSC, popGet(AOP(right),0));
5851                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5852                                         
5853                                         pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5854                                                 AOP(result)->aopu.aop_dir,
5855                                                 AOP(result)->aopu.aop_dir);
5856                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5857                                                 AOP(right)->aopu.aop_dir,
5858                                                 AOP(right)->aopu.aop_dir);
5859                                         pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5860                                                 AOP(result)->aopu.aop_dir,
5861                                                 AOP(result)->aopu.aop_dir);
5862                                 } else {
5863                                         if( AOP_TYPE(result) == AOP_ACC) {
5864                                                 emitpcode(POC_MOVLW, popGetLit(0));
5865                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5866                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5867                                                 emitpcode(POC_MOVLW, popGetLit(1));
5868                                                 
5869                                         } else {
5870                                                 
5871                                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5872                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5873                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5874                                                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5875                                                 
5876                                                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5877                                                         AOP(result)->aopu.aop_dir,
5878                                                         AOP(result)->aopu.aop_dir);
5879                                                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5880                                                         AOP(right)->aopu.aop_dir,
5881                                                         AOP(right)->aopu.aop_dir);
5882                                                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5883                                                         AOP(left)->aopu.aop_dir,
5884                                                         AOP(left)->aopu.aop_dir);
5885                                                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5886                                                         AOP(result)->aopu.aop_dir,
5887                                                         AOP(result)->aopu.aop_dir);
5888                                         }
5889                                 }
5890                         } else {
5891                                 // c = bit | val;
5892                                 symbol *tlbl = newiTempLabel(NULL);
5893                                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5894                                 
5895                                 
5896                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5897                                 if( AOP_TYPE(right) == AOP_ACC) {
5898                                         emitpcode(POC_IORLW, popGetLit(0));
5899                                         emitSKPNZ;
5900                                         emitpcode(POC_BTFSC, popGet(AOP(left),0));
5901                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5902                                 }
5903                                 
5904                                 
5905                                 
5906                                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5907                                         pic14_emitcode(";XXX setb","c");
5908                                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5909                                         AOP(left)->aopu.aop_dir,tlbl->key+100);
5910                                 pic14_toBoolean(right);
5911                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5912                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5913                                         jmpTrueOrFalse(ifx, tlbl);
5914                                         goto release;
5915                                 } else {
5916                                         CLRC;
5917                                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5918                                 }
5919                         }
5920                 }
5921                 // bit = c
5922                 // val = c
5923                 if(size)
5924                         pic14_outBitC(result);
5925                 // if(bit | ...)
5926                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5927                         genIfxJump(ifx, "c");           
5928                 goto release ;
5929         }
5930
5931         // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5932         // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5933         if((AOP_TYPE(right) == AOP_LIT) &&
5934           (AOP_TYPE(result) == AOP_CRY) &&
5935           (AOP_TYPE(left) != AOP_CRY)){
5936                 if(lit){
5937                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5938                         // result = 1
5939                         if(size)
5940                                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5941                         else 
5942                                 continueIfTrue(ifx);
5943                         goto release;
5944                 } else {
5945                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5946                         // lit = 0, result = boolean(left)
5947                         if(size)
5948                                 pic14_emitcode(";XXX setb","c");
5949                         pic14_toBoolean(right);
5950                         if(size){
5951                                 symbol *tlbl = newiTempLabel(NULL);
5952                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5953                                 CLRC;
5954                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5955                         } else {
5956                                 genIfxJump (ifx,"a");
5957                                 goto release;
5958                         }
5959                 }
5960                 pic14_outBitC(result);
5961                 goto release ;
5962         }
5963
5964         /* if left is same as result */
5965         if(pic14_sameRegs(AOP(result),AOP(left))){
5966                 int know_W = -1;
5967                 for(;size--; offset++,lit>>=8) {
5968                         if(AOP_TYPE(right) == AOP_LIT){
5969                                 if((lit & 0xff) == 0)
5970                                         /*  or'ing with 0 has no effect */
5971                                         continue;
5972                                 else {
5973                                         int p = my_powof2(lit & 0xff);
5974                                         if(p>=0) {
5975                                                 /* only one bit is set in the literal, so use a bsf instruction */
5976                                                 emitpcode(POC_BSF,
5977                                                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5978                                         } else {
5979                                                 if(know_W != (int)(lit & 0xff))
5980                                                         emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5981                                                 know_W = lit & 0xff;
5982                                                 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5983                                         }
5984                                         
5985                                 }
5986                         } else {
5987                                 if (AOP_TYPE(left) == AOP_ACC) {
5988                                         emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5989                                         pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5990                                 } else {        
5991                                         emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5992                                         emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5993                                         
5994                                         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5995                                         pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5996                                         
5997                                 }
5998                         }
5999                 }
6000         } else {
6001                 // left & result in different registers
6002                 if(AOP_TYPE(result) == AOP_CRY){
6003                         // result = bit
6004                         // if(size), result in bit
6005                         // if(!size && ifx), conditional oper: if(left | right)
6006                         symbol *tlbl = newiTempLabel(NULL);
6007                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6008                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6009                         
6010                         
6011                         if(size)
6012                                 pic14_emitcode(";XXX setb","c");
6013                         while(sizer--){
6014                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6015                                 pic14_emitcode(";XXX orl","a,%s",
6016                                         aopGet(AOP(left),offset,FALSE,FALSE));
6017                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6018                                 offset++;
6019                         }
6020                         if(size){
6021                                 CLRC;
6022                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6023                                 pic14_outBitC(result);
6024                         } else if(ifx)
6025                                 jmpTrueOrFalse(ifx, tlbl);
6026                 } else for(;(size--);offset++){
6027                         // normal case
6028                         // result = left | right
6029                         if(AOP_TYPE(right) == AOP_LIT){
6030                                 int t = (lit >> (offset*8)) & 0x0FFL;
6031                                 switch(t) { 
6032                                 case 0x00:
6033                                         if (AOP_TYPE(left) != AOP_ACC) {
6034                                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
6035                                         }
6036                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6037                                         
6038                                         break;
6039                                 default:
6040                                         if (AOP_TYPE(left) == AOP_ACC) {
6041                                                 emitpcode(POC_IORLW,  popGetLit(t));
6042                                         } else {
6043                                                 emitpcode(POC_MOVLW,  popGetLit(t));
6044                                                 emitpcode(POC_IORFW,  popGet(AOP(left),offset));
6045                                         }
6046                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));        
6047                                 }
6048                                 continue;
6049                         }
6050                         
6051                         // faster than result <- left, anl result,right
6052                         // and better if result is SFR
6053                         if (AOP_TYPE(left) == AOP_ACC) {
6054                                 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6055                         } else {
6056                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6057                                 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6058                         }
6059                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6060                 }
6061         }
6062
6063 release :
6064         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6065         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6066         freeAsmop(result,NULL,ic,TRUE);     
6067 }
6068
6069 /*-----------------------------------------------------------------*/
6070 /* genXor - code for xclusive or                                   */
6071 /*-----------------------------------------------------------------*/
6072 static void genXor (iCode *ic, iCode *ifx)
6073 {
6074         operand *left, *right, *result;
6075         int size, offset=0;
6076         unsigned long lit = 0L;
6077         
6078         FENTRY;
6079         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6080         
6081         aopOp((left = IC_LEFT(ic)),ic,FALSE);
6082         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6083         aopOp((result=IC_RESULT(ic)),ic,TRUE);
6084         
6085         /* if left is a literal & right is not ||
6086         if left needs acc & right does not */
6087         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6088                 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6089                 operand *tmp = right ;
6090                 right = left;
6091                 left = tmp;
6092         }
6093         
6094         /* if result = right then exchange them */
6095         if(pic14_sameRegs(AOP(result),AOP(right))){
6096                 operand *tmp = right ;
6097                 right = left;
6098                 left = tmp;
6099         }
6100         
6101         /* if right is bit then exchange them */
6102         if (AOP_TYPE(right) == AOP_CRY &&
6103                 AOP_TYPE(left) != AOP_CRY){
6104                 operand *tmp = right ;
6105                 right = left;
6106                 left = tmp;
6107         }
6108         if(AOP_TYPE(right) == AOP_LIT)
6109                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6110         
6111         size = AOP_SIZE(result);
6112         
6113         // if(bit ^ yy)
6114         // xx = bit ^ yy;
6115         if (AOP_TYPE(left) == AOP_CRY){
6116                 if(AOP_TYPE(right) == AOP_LIT){
6117                         // c = bit & literal;
6118                         if(lit>>1){
6119                                 // lit>>1  != 0 => result = 1
6120                                 if(AOP_TYPE(result) == AOP_CRY){
6121                                         if(size)
6122                                         {emitpcode(POC_BSF,  popGet(AOP(result),offset));
6123                                         pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6124                                         else if(ifx)
6125                                                 continueIfTrue(ifx);
6126                                         goto release;
6127                                 }
6128                                 pic14_emitcode("setb","c");
6129                         } else{
6130                                 // lit == (0 or 1)
6131                                 if(lit == 0){
6132                                         // lit == 0, result = left
6133                                         if(size && pic14_sameRegs(AOP(result),AOP(left)))
6134                                                 goto release;
6135                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6136                                 } else{
6137                                         // lit == 1, result = not(left)
6138                                         if(size && pic14_sameRegs(AOP(result),AOP(left))){
6139                                                 emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
6140                                                 emitpcode(POC_XORWF,  popGet(AOP(result),offset));
6141                                                 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6142                                                 goto release;
6143                                         } else {
6144                                                 assert ( !"incomplete genXor" );
6145                                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6146                                                 pic14_emitcode("cpl","c");
6147                                         }
6148                                 }
6149                         }
6150                         
6151                 } else {
6152                         // right != literal
6153                         symbol *tlbl = newiTempLabel(NULL);
6154                         if (AOP_TYPE(right) == AOP_CRY){
6155                                 // c = bit ^ bit;
6156                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6157                         }
6158                         else{
6159                                 int sizer = AOP_SIZE(right);
6160                                 // c = bit ^ val
6161                                 // if val>>1 != 0, result = 1
6162                                 pic14_emitcode("setb","c");
6163                                 while(sizer){
6164                                         MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6165                                         if(sizer == 1)
6166                                                 // test the msb of the lsb
6167                                                 pic14_emitcode("anl","a,#0xfe");
6168                                         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6169                                         sizer--;
6170                                 }
6171                                 // val = (0,1)
6172                                 pic14_emitcode("rrc","a");
6173                         }
6174                         pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6175                         pic14_emitcode("cpl","c");
6176                         pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6177                 }
6178                 // bit = c
6179                 // val = c
6180                 if(size)
6181                         pic14_outBitC(result);
6182                 // if(bit | ...)
6183                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6184                         genIfxJump(ifx, "c");           
6185                 goto release ;
6186         }
6187         
6188         if(pic14_sameRegs(AOP(result),AOP(left))){
6189                 /* if left is same as result */
6190                 for(;size--; offset++) {
6191                         if(AOP_TYPE(right) == AOP_LIT){
6192                                 int t  = (lit >> (offset*8)) & 0x0FFL;
6193                                 if(t == 0x00L)
6194                                         continue;
6195                                 else
6196                                         if (IS_AOP_PREG(left)) {
6197                                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6198                                                 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6199                                                 aopPut(AOP(result),"a",offset);
6200                                         } else {
6201                                                 emitpcode(POC_MOVLW, popGetLit(t));
6202                                                 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6203                                                 pic14_emitcode("xrl","%s,%s",
6204                                                         aopGet(AOP(left),offset,FALSE,TRUE),
6205                                                         aopGet(AOP(right),offset,FALSE,FALSE));
6206                                         }
6207                         } else {
6208                                 if (AOP_TYPE(left) == AOP_ACC)
6209                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6210                                 else {
6211                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6212                                         emitpcode(POC_XORWF,popGet(AOP(left),offset));
6213                                         /*
6214                                         if (IS_AOP_PREG(left)) {
6215                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6216                                         aopPut(AOP(result),"a",offset);
6217                                         } else
6218                                         pic14_emitcode("xrl","%s,a",
6219                                         aopGet(AOP(left),offset,FALSE,TRUE));
6220                                         */
6221                                 }
6222                         }
6223                 }
6224         } else {
6225                 // left & result in different registers
6226                 if(AOP_TYPE(result) == AOP_CRY){
6227                         // result = bit
6228                         // if(size), result in bit
6229                         // if(!size && ifx), conditional oper: if(left ^ right)
6230                         symbol *tlbl = newiTempLabel(NULL);
6231                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6232                         if(size)
6233                                 pic14_emitcode("setb","c");
6234                         while(sizer--){
6235                                 if((AOP_TYPE(right) == AOP_LIT) &&
6236                                         (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6237                                         MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6238                                 } else {
6239                                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6240                                         pic14_emitcode("xrl","a,%s",
6241                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6242                                 }
6243                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6244                                 offset++;
6245                         }
6246                         if(size){
6247                                 CLRC;
6248                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6249                                 pic14_outBitC(result);
6250                         } else if(ifx)
6251                                 jmpTrueOrFalse(ifx, tlbl);
6252                 } else for(;(size--);offset++){
6253                         // normal case
6254                         // result = left & right
6255                         if(AOP_TYPE(right) == AOP_LIT){
6256                                 int t = (lit >> (offset*8)) & 0x0FFL;
6257                                 switch(t) { 
6258                                 case 0x00:
6259                                         if (AOP_TYPE(left) != AOP_ACC) {
6260                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6261                                         }
6262                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6263                                         pic14_emitcode("movf","%s,w",
6264                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6265                                         pic14_emitcode("movwf","%s",
6266                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6267                                         break;
6268                                 case 0xff:
6269                                         if (AOP_TYPE(left) == AOP_ACC) {
6270                                                 emitpcode(POC_XORLW, popGetLit(t));
6271                                         } else {
6272                                                 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6273                                         }
6274                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6275                                         break;
6276                                 default:
6277                                         if (AOP_TYPE(left) == AOP_ACC) {
6278                                                 emitpcode(POC_XORLW, popGetLit(t));
6279                                         } else {
6280                                                 emitpcode(POC_MOVLW, popGetLit(t));
6281                                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6282                                         }
6283                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6284                                         pic14_emitcode("movlw","0x%x",t);
6285                                         pic14_emitcode("xorwf","%s,w",
6286                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6287                                         pic14_emitcode("movwf","%s",
6288                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6289                                         
6290                                 }
6291                                 continue;
6292                         }
6293                         
6294                         // faster than result <- left, anl result,right
6295                         // and better if result is SFR
6296                         if (AOP_TYPE(left) == AOP_ACC) {
6297                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6298                         } else {
6299                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6300                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6301                         }
6302                         if ( AOP_TYPE(result) != AOP_ACC){
6303                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6304                         }
6305                 }
6306         }
6307         
6308 release :
6309         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6310         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6311         freeAsmop(result,NULL,ic,TRUE);     
6312 }
6313
6314 /*-----------------------------------------------------------------*/
6315 /* genInline - write the inline code out                           */
6316 /*-----------------------------------------------------------------*/
6317 static void genInline (iCode *ic)
6318 {
6319   char *buffer, *bp, *bp1;
6320
6321   FENTRY;
6322   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6323
6324   _G.inLine += (!options.asmpeep);
6325
6326   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6327   strcpy(buffer,IC_INLINE(ic));
6328
6329   /* emit each line as a code */
6330   while (*bp) {
6331     if (*bp == '\n') {
6332       *bp++ = '\0';
6333       
6334       if(*bp1)
6335         addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6336       bp1 = bp;
6337     } else {
6338       if (*bp == ':') {
6339         bp++;
6340         *bp = '\0';
6341         bp++;
6342
6343         /* print label, use this special format with NULL directive
6344          * to denote that the argument should not be indented with tab */
6345         addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6346
6347         bp1 = bp;
6348       } else
6349         bp++;
6350     }
6351   }
6352   if ((bp1 != bp) && *bp1)
6353     addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6354
6355   Safe_free(buffer);
6356
6357   _G.inLine -= (!options.asmpeep);
6358 }
6359
6360 /*-----------------------------------------------------------------*/
6361 /* genRRC - rotate right with carry                                */
6362 /*-----------------------------------------------------------------*/
6363 static void genRRC (iCode *ic)
6364 {
6365         operand *left , *result ;
6366         int size, offset = 0, same;
6367         
6368         FENTRY;
6369         /* rotate right with carry */
6370         left = IC_LEFT(ic);
6371         result=IC_RESULT(ic);
6372         aopOp (left,ic,FALSE);
6373         aopOp (result,ic,FALSE);
6374         
6375         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6376         
6377         same = pic14_sameRegs(AOP(result),AOP(left));
6378         
6379         size = AOP_SIZE(result);    
6380         
6381         /* get the lsb and put it into the carry */
6382         emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6383         
6384         offset = 0 ;
6385         
6386         while(size--) {
6387                 
6388                 if(same) {
6389                         emitpcode(POC_RRF, popGet(AOP(left),offset));
6390                 } else {
6391                         emitpcode(POC_RRFW, popGet(AOP(left),offset));
6392                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6393                 }
6394                 
6395                 offset++;
6396         }
6397         
6398         freeAsmop(left,NULL,ic,TRUE);
6399         freeAsmop(result,NULL,ic,TRUE);
6400 }
6401
6402 /*-----------------------------------------------------------------*/
6403 /* genRLC - generate code for rotate left with carry               */
6404 /*-----------------------------------------------------------------*/
6405 static void genRLC (iCode *ic)
6406 {    
6407         operand *left , *result ;
6408         int size, offset = 0;
6409         int same;
6410         
6411         FENTRY;
6412         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6413         /* rotate right with carry */
6414         left = IC_LEFT(ic);
6415         result=IC_RESULT(ic);
6416         aopOp (left,ic,FALSE);
6417         aopOp (result,ic,FALSE);
6418         
6419         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6420         
6421         same = pic14_sameRegs(AOP(result),AOP(left));
6422         
6423         /* move it to the result */
6424         size = AOP_SIZE(result);    
6425         
6426         /* get the msb and put it into the carry */
6427         emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6428         
6429         offset = 0 ;
6430         
6431         while(size--) {
6432                 
6433                 if(same) {
6434                         emitpcode(POC_RLF, popGet(AOP(left),offset));
6435                 } else {
6436                         emitpcode(POC_RLFW, popGet(AOP(left),offset));
6437                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6438                 }
6439                 
6440                 offset++;
6441         }
6442         
6443         
6444         freeAsmop(left,NULL,ic,TRUE);
6445         freeAsmop(result,NULL,ic,TRUE);
6446 }
6447
6448 /*-----------------------------------------------------------------*/
6449 /* genGetHbit - generates code get highest order bit               */
6450 /*-----------------------------------------------------------------*/
6451 static void genGetHbit (iCode *ic)
6452 {
6453         operand *left, *result;
6454         left = IC_LEFT(ic);
6455         result=IC_RESULT(ic);
6456         aopOp (left,ic,FALSE);
6457         aopOp (result,ic,FALSE);
6458         
6459         FENTRY;
6460         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6461         /* get the highest order byte into a */
6462         MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6463         if(AOP_TYPE(result) == AOP_CRY){
6464                 pic14_emitcode("rlc","a");
6465                 pic14_outBitC(result);
6466         }
6467         else{
6468                 pic14_emitcode("rl","a");
6469                 pic14_emitcode("anl","a,#0x01");
6470                 pic14_outAcc(result);
6471         }
6472         
6473         
6474         freeAsmop(left,NULL,ic,TRUE);
6475         freeAsmop(result,NULL,ic,TRUE);
6476 }
6477
6478 /*-----------------------------------------------------------------*/
6479 /* AccLsh - shift left accumulator by known count                  */
6480 /* MARK: pic14 always rotates through CARRY!                       */
6481 /*-----------------------------------------------------------------*/
6482 static void AccLsh (pCodeOp *pcop,int shCount)
6483 {
6484         FENTRY;
6485         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6486         shCount &= 0x0007;              // shCount : 0..7
6487         switch(shCount){
6488         case 0 :
6489                 return;
6490                 break;
6491         case 1 :
6492                 emitCLRC;
6493                 emitpcode(POC_RLF,pcop);
6494                 return;
6495                 break;
6496         case 2 :
6497                 emitpcode(POC_RLF,pcop);
6498                 emitpcode(POC_RLF,pcop);
6499                 break;
6500         case 3 :
6501                 emitpcode(POC_RLF,pcop);
6502                 emitpcode(POC_RLF,pcop);
6503                 emitpcode(POC_RLF,pcop);
6504                 break;
6505         case 4 :
6506                 emitpcode(POC_SWAPF,pcop);
6507                 break;
6508         case 5 :
6509                 emitpcode(POC_SWAPF,pcop);
6510                 emitpcode(POC_RLF,pcop);
6511                 break;
6512         case 6 :
6513                 emitpcode(POC_SWAPF,pcop);
6514                 emitpcode(POC_RLF,pcop);
6515                 emitpcode(POC_RLF,pcop);
6516                 break;
6517         case 7 :
6518                 emitpcode(POC_RRFW,pcop);
6519                 emitpcode(POC_RRF,pcop);
6520                 break;
6521         }
6522         /* clear invalid bits */
6523         emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6524         emitpcode(POC_ANDWF, pcop);
6525 }
6526
6527 /*-----------------------------------------------------------------*/
6528 /* AccRsh - shift right accumulator by known count                 */
6529 /* MARK: pic14 always rotates through CARRY!                       */
6530 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6531 /*            1: mask out invalid bits (zero-extend)               */
6532 /*            2: sign-extend result (pretty slow)                  */
6533 /*-----------------------------------------------------------------*/
6534 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6535 {
6536         FENTRY;
6537         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6538         shCount &= 0x0007;              // shCount : 0..7
6539         switch(shCount){
6540         case 0 :
6541                 return;
6542                 break;
6543         case 1 :
6544                 /* load sign if needed */
6545                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6546                 else if (mask_mode == 1) emitCLRC;
6547                 emitpcode(POC_RRF,pcop);
6548                 return;
6549                 break;
6550         case 2 :
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 3 :
6560                 /* load sign if needed */
6561                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6562                 emitpcode(POC_RRF,pcop);
6563                 /* load sign if needed */
6564                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6565                 emitpcode(POC_RRF,pcop);
6566                 /* load sign if needed */
6567                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6568                 emitpcode(POC_RRF,pcop);
6569                 if (mask_mode == 2) return;
6570                 break;
6571         case 4 :
6572                 emitpcode(POC_SWAPF,pcop);
6573                 break;
6574         case 5 :
6575                 emitpcode(POC_SWAPF,pcop);
6576                 emitpcode(POC_RRF,pcop);
6577                 break;
6578         case 6 :
6579                 emitpcode(POC_SWAPF,pcop);
6580                 emitpcode(POC_RRF,pcop);
6581                 emitpcode(POC_RRF,pcop);
6582                 break;
6583         case 7 :
6584                 if (mask_mode == 2)
6585                 {
6586                         /* load sign */
6587                         emitpcode(POC_RLFW,pcop);
6588                         emitpcode(POC_CLRF,pcop);
6589                         emitSKPNC;
6590                         emitpcode(POC_COMF,pcop);
6591                         return;
6592                 } else {
6593                         emitpcode(POC_RLFW,pcop);
6594                         emitpcode(POC_RLF,pcop);
6595                 }
6596                 break;
6597         }
6598
6599         if (mask_mode == 0)
6600         {
6601                 /* leave invalid bits undefined */
6602                 return;
6603         }
6604         
6605         /* clear invalid bits -- zero-extend */
6606         emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6607         emitpcode(POC_ANDWF, pcop);
6608
6609         if (mask_mode == 2) {
6610           /* sign-extend */
6611           emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6612           emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6613           emitpcode(POC_IORWF, pcop);
6614         }
6615 }
6616
6617 #if 0
6618 /*-----------------------------------------------------------------*/
6619 /* AccSRsh - signed right shift accumulator by known count                 */
6620 /*-----------------------------------------------------------------*/
6621 static void AccSRsh (int shCount)
6622 {
6623         symbol *tlbl ;
6624         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6625         if(shCount != 0){
6626                 if(shCount == 1){
6627                         pic14_emitcode("mov","c,acc.7");
6628                         pic14_emitcode("rrc","a");
6629                 } else if(shCount == 2){
6630                         pic14_emitcode("mov","c,acc.7");
6631                         pic14_emitcode("rrc","a");
6632                         pic14_emitcode("mov","c,acc.7");
6633                         pic14_emitcode("rrc","a");
6634                 } else {
6635                         tlbl = newiTempLabel(NULL);
6636                         /* rotate right accumulator */
6637                         AccRol(8 - shCount);
6638                         /* and kill the higher order bits */
6639                         pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6640                         pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6641                         pic14_emitcode("orl","a,#0x%02x",
6642                                 (unsigned char)~SRMask[shCount]);
6643                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6644                 }
6645         }
6646 }
6647
6648 /*-----------------------------------------------------------------*/
6649 /* shiftR1Left2Result - shift right one byte from left to result   */
6650 /*-----------------------------------------------------------------*/
6651 static void shiftR1Left2ResultSigned (operand *left, int offl,
6652                                                                           operand *result, int offr,
6653                                                                           int shCount)
6654 {
6655         int same;
6656         
6657         FENTRY;
6658         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6659         
6660         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6661         
6662         switch(shCount) {
6663         case 1:
6664                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6665                 if(same) 
6666                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6667                 else {
6668                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6669                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6670                 }
6671                 
6672                 break;
6673         case 2:
6674                 
6675                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6676                 if(same) 
6677                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6678                 else {
6679                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6680                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6681                 }
6682                 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6683                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6684                 
6685                 break;
6686                 
6687         case 3:
6688                 if(same)
6689                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6690                 else {
6691                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6692                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6693                 }
6694                 
6695                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6696                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6697                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6698                 
6699                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6700                 emitpcode(POC_IORLW, popGetLit(0xe0));
6701                 
6702                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6703                 break;
6704                 
6705         case 4:
6706                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6707                 emitpcode(POC_ANDLW,  popGetLit(0x0f));
6708                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6709                 emitpcode(POC_IORLW,  popGetLit(0xf0));
6710                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6711                 break;
6712         case 5:
6713                 if(same) {
6714                         emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6715                 } else {
6716                         emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6717                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6718                 }
6719                 emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6720                 emitpcode(POC_ANDLW,  popGetLit(0x07));
6721                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6722                 emitpcode(POC_IORLW,  popGetLit(0xf8));
6723                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6724                 break;
6725                 
6726         case 6:
6727                 if(same) {
6728                         emitpcode(POC_MOVLW, popGetLit(0x00));
6729                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6730                         emitpcode(POC_MOVLW, popGetLit(0xfe));
6731                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6732                         emitpcode(POC_IORLW, popGetLit(0x01));
6733                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6734                 } else {
6735                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6736                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6737                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6738                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6739                         emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6740                 }
6741                 break;
6742                 
6743         case 7:
6744                 if(same) {
6745                         emitpcode(POC_MOVLW, popGetLit(0x00));
6746                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6747                         emitpcode(POC_MOVLW, popGetLit(0xff));
6748                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6749                 } else {
6750                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6751                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6752                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6753                 }
6754                 
6755         default:
6756                 break;
6757         }
6758 }
6759
6760 /*-----------------------------------------------------------------*/
6761 /* shiftR1Left2Result - shift right one byte from left to result   */
6762 /*-----------------------------------------------------------------*/
6763 static void shiftR1Left2Result (operand *left, int offl,
6764                                                                 operand *result, int offr,
6765                                                                 int shCount, int sign)
6766 {
6767         int same;
6768         
6769         FENTRY;
6770         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6771         
6772         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6773         
6774         /* Copy the msb into the carry if signed. */
6775         if(sign) {
6776                 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6777                 return;
6778         }
6779         
6780         
6781         
6782         switch(shCount) {
6783         case 1:
6784                 emitCLRC;
6785                 if(same) 
6786                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6787                 else {
6788                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6789                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6790                 }
6791                 break;
6792         case 2:
6793                 emitCLRC;
6794                 if(same) {
6795                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6796                 } else {
6797                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6798                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6799                 }
6800                 emitCLRC;
6801                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6802                 
6803                 break;
6804         case 3:
6805                 if(same)
6806                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6807                 else {
6808                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6809                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6810                 }
6811                 
6812                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6813                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6814                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6815                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6816                 break;
6817                 
6818         case 4:
6819                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6820                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6821                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6822                 break;
6823                 
6824         case 5:
6825                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6826                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6827                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6828                 emitCLRC;
6829                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6830                 
6831                 break;
6832         case 6:
6833                 
6834                 emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6835                 emitpcode(POC_ANDLW, popGetLit(0x80));
6836                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6837                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6838                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6839                 break;
6840                 
6841         case 7:
6842                 
6843                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6844                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6845                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6846                 
6847                 break;
6848                 
6849         default:
6850                 break;
6851         }
6852 }
6853
6854 /*-----------------------------------------------------------------*/
6855 /* shiftL1Left2Result - shift left one byte from left to result    */
6856 /*-----------------------------------------------------------------*/
6857 static void shiftL1Left2Result (operand *left, int offl,
6858                                                                 operand *result, int offr, int shCount)
6859 {
6860         int same;
6861         
6862         //    char *l;
6863         FENTRY;
6864         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6865         
6866         same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6867         DEBUGpic14_emitcode ("; ***","same =  %d",same);
6868         //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6869         //    MOVA(l);
6870         /* shift left accumulator */
6871         //AccLsh(shCount); // don't comment out just yet...
6872         //    aopPut(AOP(result),"a",offr);
6873         
6874         switch(shCount) {
6875         case 1:
6876                 /* Shift left 1 bit position */
6877                 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6878                 if(same) {
6879                         emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6880                 } else {
6881                         emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6882                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6883                 }
6884                 break;
6885         case 2:
6886                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6887                 emitpcode(POC_ANDLW,popGetLit(0x7e));
6888                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6889                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6890                 break;
6891         case 3:
6892                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6893                 emitpcode(POC_ANDLW,popGetLit(0x3e));
6894                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6895                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6896                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6897                 break;
6898         case 4:
6899                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6900                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6901                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6902                 break;
6903         case 5:
6904                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6905                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6906                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6907                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6908                 break;
6909         case 6:
6910                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6911                 emitpcode(POC_ANDLW, popGetLit(0x30));
6912                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6913                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6914                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6915                 break;
6916         case 7:
6917                 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6918                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6919                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6920                 break;
6921                 
6922         default:
6923                 DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6924         }
6925         
6926 }
6927 #endif
6928
6929 /*-----------------------------------------------------------------*/
6930 /* movLeft2Result - move byte from left to result                  */
6931 /*-----------------------------------------------------------------*/
6932 static void movLeft2Result (operand *left, int offl,
6933                                                         operand *result, int offr)
6934 {
6935         char *l;
6936         FENTRY;
6937         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6938         if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6939                 l = aopGet(AOP(left),offl,FALSE,FALSE);
6940                 
6941                 if (*l == '@' && (IS_AOP_PREG(result))) {
6942                         pic14_emitcode("mov","a,%s",l);
6943                         aopPut(AOP(result),"a",offr);
6944                 } else {
6945                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6946                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6947                 }
6948         }
6949 }
6950
6951 /*-----------------------------------------------------------------*/
6952 /* shiftLeft_Left2ResultLit - shift left by known count            */
6953 /*-----------------------------------------------------------------*/
6954
6955 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6956 {
6957         int size, same, offr, i;
6958
6959         size = AOP_SIZE(left);
6960         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6961         
6962         same = pic14_sameRegs (AOP(left), AOP(result));
6963         
6964         offr = shCount / 8;
6965         shCount = shCount & 0x07;
6966
6967         size -= offr;
6968
6969         switch (shCount)
6970         {
6971         case 0: /* takes 0 or 2N cycles (for offr==0) */
6972                 if (!same || offr) {
6973                         for (i=size-1; i >= 0; i--)
6974                                 movLeft2Result (left, i, result, offr + i);
6975                 } // if
6976                 break;
6977                 
6978         case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6979                 if (same && offr) {
6980                         shiftLeft_Left2ResultLit (left, result, 8 * offr);
6981                         shiftLeft_Left2ResultLit (result, result, shCount);
6982                         return; /* prevent clearing result again */
6983                 } else {
6984                         emitCLRC;
6985                         for (i=0; i < size; i++) {
6986                                 if (same && !offr) {
6987                                         emitpcode (POC_RLF, popGet (AOP(left), i));
6988                                 } else {
6989                                         emitpcode (POC_RLFW, popGet (AOP(left), i));
6990                                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6991                                 } // if
6992                         } // for
6993                 } // if (offr)
6994                 break;
6995                 
6996         case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6997                 /* works in-place/with offr as well */
6998                 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6999                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7000                 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
7001
7002                 for (i = size - 2; i >= 0; i--)
7003                 {
7004                         emitpcode (POC_SWAPFW, popGet (AOP(left), i));
7005                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7006                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7007                         emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
7008                         emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
7009                 } // for i
7010                 break;
7011                 
7012         case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7013                 /* works in-place/with offr as well */
7014                 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7015                 for (i = size-2; i >= 0; i--) {
7016                         emitpcode (POC_RRFW, popGet (AOP(left), i));
7017                         emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7018                 } // for i
7019                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7020                 emitpcode (POC_RRF, popGet (AOP(result), offr));
7021                 break;
7022         
7023         default:
7024                 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7025                 shiftLeft_Left2ResultLit (result, result, 1);
7026                 return; /* prevent clearing result again */
7027                 break;
7028         } // switch
7029
7030         while (0 < offr--)
7031         {
7032                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7033         } // while
7034 }
7035
7036 /*-----------------------------------------------------------------*/
7037 /* shiftRight_Left2ResultLit - shift right by known count          */
7038 /*-----------------------------------------------------------------*/
7039
7040 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7041 {
7042         int size, same, offr, i;
7043
7044         size = AOP_SIZE(left);
7045         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7046         
7047         same = pic14_sameRegs (AOP(left), AOP(result));
7048         
7049         offr = shCount / 8;
7050         shCount = shCount & 0x07;
7051
7052         size -= offr;
7053
7054         if (size)
7055         {
7056                 switch (shCount)
7057                 {
7058                 case 0: /* takes 0 or 2N cycles (for offr==0) */
7059                         if (!same || offr) {
7060                                 for (i=0; i < size; i++)
7061                                         movLeft2Result (left, i + offr, result, i);
7062                         } // if
7063                         break;
7064                         
7065                 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7066                         emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7067                         if (same && offr) {
7068                                 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7069                                 shiftRight_Left2ResultLit (result, result, shCount, sign);
7070                                 return; /* prevent sign-extending result again */
7071                         } else {
7072                                 emitCLRC;
7073                                 if (sign) {
7074                                         emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7075                                         emitSETC;
7076                                 }
7077                                 for (i = size-1; i >= 0; i--) {
7078                                         if (same && !offr) {
7079                                                 emitpcode (POC_RRF, popGet (AOP(left), i));
7080                                         } else {
7081                                                 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7082                                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7083                                         }
7084                                 } // for i
7085                         } // if (offr)
7086                         break;
7087                         
7088                 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7089                         /* works in-place/with offr as well */
7090                         emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7091                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7092                         emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7093
7094                         for (i = 1; i < size; i++)
7095                         {
7096                                 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7097                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7098                                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7099                                 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7100                                 emitpcode (POC_XORWF, popGet (AOP(result), i));
7101                         } // for i
7102
7103                         if (sign)
7104                         {
7105                                 emitpcode (POC_MOVLW, popGetLit (0xF0));
7106                                 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7107                                 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7108                         } // if
7109                         break;
7110                         
7111                 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7112                         /* works in-place/with offr as well */
7113                         emitpcode (POC_RLFW, popGet (AOP(left), offr));
7114                         for (i = 0; i < size-1; i++) {
7115                                 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7116                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7117                         } // for i
7118                         emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7119                         if (!sign) {
7120                                 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7121                         } else {
7122                                 emitSKPNC;
7123                                 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7124                         }
7125                         break;
7126                 
7127                 default:
7128                         shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7129                         shiftRight_Left2ResultLit (result, result, 1, sign);
7130                         return; /* prevent sign extending result again */
7131                         break;
7132                 } // switch
7133         } // if
7134
7135         addSign (result, size, sign);
7136 }
7137
7138 #if 0
7139 /*-----------------------------------------------------------------*/
7140 /* shiftL2Left2Result - shift left two bytes from left to result   */
7141 /*-----------------------------------------------------------------*/
7142 static void shiftL2Left2Result (operand *left, int offl,
7143                                                                 operand *result, int offr, int shCount)
7144 {
7145         FENTRY;
7146         
7147         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7148         
7149         if(pic14_sameRegs(AOP(result), AOP(left))) {
7150                 switch(shCount) {
7151                 case 0:
7152                         break;
7153                 case 1:
7154                 case 2:
7155                 case 3:
7156                         
7157                         emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7158                         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7159                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7160                         
7161                         while(--shCount) {
7162                                 emitCLRC;
7163                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7164                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7165                         }
7166                         
7167                         break;
7168                 case 4:
7169                 case 5:
7170                         emitpcode(POC_MOVLW, popGetLit(0x0f));
7171                         emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7172                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7173                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7174                         emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7175                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7176                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7177                         if(shCount >=5) {
7178                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7179                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7180                         }
7181                         break;
7182                 case 6:
7183                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7184                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7185                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7186                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7187                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7188                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7189                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7190                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7191                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7192                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7193                         break;
7194                 case 7:
7195                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7196                         emitpcode(POC_RRFW, popGet(AOP(result),offr));
7197                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7198                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7199                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7200                 }
7201                 
7202         } else {
7203                 switch(shCount) {
7204                 case 0:
7205                         break;
7206                 case 1:
7207                 case 2:
7208                 case 3:
7209                 /* note, use a mov/add for the shift since the mov has a
7210                         chance of getting optimized out */
7211                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7212                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7213                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7214                         emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
7215                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7216                         
7217                         while(--shCount) {
7218                                 emitCLRC;
7219                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7220                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7221                         }
7222                         break;
7223                         
7224                 case 4:
7225                 case 5:
7226                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7227                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7228                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7229                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7230                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7231                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7232                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7233                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7234                         
7235                         
7236                         if(shCount == 5) {
7237                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7238                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7239                         }
7240                         break;
7241                 case 6:
7242                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7243                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7244                         emitpcode(POC_RRFW, popGet(AOP(result),offl));
7245                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
7246                         
7247                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7248                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7249                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7250                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7251                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7252                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7253                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7254                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7255                         break;
7256                 case 7:
7257                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7258                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7259                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7260                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7261                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7262                 }
7263         }
7264         
7265 }
7266
7267 /*-----------------------------------------------------------------*/
7268 /* shiftR2Left2Result - shift right two bytes from left to result  */
7269 /*-----------------------------------------------------------------*/
7270 static void shiftR2Left2Result (operand *left, int offl,
7271                                                                 operand *result, int offr,
7272                                                                 int shCount, int sign)
7273 {
7274         int same=0;
7275         
7276         FENTRY;
7277         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7278         same = pic14_sameRegs(AOP(result), AOP(left));
7279         
7280         if(same && ((offl + MSB16) == offr)){
7281                 same=1;
7282                 /* don't crash result[offr] */
7283                 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7284                 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7285         }
7286         /* else {
7287         movLeft2Result(left,offl, result, offr);
7288         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7289         }
7290         */
7291         /* a:x >> shCount (x = lsb(result))*/
7292         /*
7293         if(sign)
7294         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7295         else {
7296         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7297         */
7298         switch(shCount) {
7299         case 0:
7300                 break;
7301         case 1:
7302         case 2:
7303         case 3:
7304                 if(sign)
7305                         emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7306                 else
7307                         emitCLRC;
7308                 
7309                 if(same) {
7310                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7311                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7312                 } else {
7313                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7314                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7315                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7316                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7317                 }
7318                 
7319                 while(--shCount) {
7320                         if(sign)
7321                                 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7322                         else
7323                                 emitCLRC;
7324                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7325                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7326                 }
7327                 break;
7328         case 4:
7329         case 5:
7330                 if(same) {
7331                         
7332                         emitpcode(POC_MOVLW, popGetLit(0xf0));
7333                         emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7334                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7335                         
7336                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7337                         emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7338                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7339                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7340                 } else {
7341                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7342                         emitpcode(POC_ANDLW, popGetLit(0x0f));
7343                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7344                         
7345                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7346                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7347                         emitpcode(POC_ANDLW, popGetLit(0xf0));
7348                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7349                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7350                 }
7351                 
7352                 if(shCount >=5) {
7353                         emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7354                         emitpcode(POC_RRF, popGet(AOP(result),offr));
7355                 }
7356                 
7357                 if(sign) {
7358                         emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7359                         emitpcode(POC_BTFSC, 
7360                                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7361                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7362                 }
7363                 
7364                 break;
7365                 
7366         case 6:
7367                 if(same) {
7368                         
7369                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7370                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7371                         
7372                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7373                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7374                         emitpcode(POC_RLFW, popGet(AOP(result),offr));
7375                         emitpcode(POC_ANDLW,popGetLit(0x03));
7376                         if(sign) {
7377                                 emitpcode(POC_BTFSC, 
7378                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7379                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7380                         }
7381                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7382                         emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7383                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7384                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7385                 } else {
7386                         emitpcode(POC_RLFW, popGet(AOP(left),offl));
7387                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7388                         emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7389                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7390                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7391                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7392                         emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7393                         emitpcode(POC_ANDLW,popGetLit(0x03));
7394                         if(sign) {
7395                                 emitpcode(POC_BTFSC, 
7396                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7397                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7398                         }
7399                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7400                         //emitpcode(POC_RLF,  popGet(AOP(result),offr));
7401                         
7402                         
7403                 }
7404                 
7405                 break;
7406         case 7:
7407                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7408                 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7409                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7410                 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7411                 if(sign) {
7412                         emitSKPNC;
7413                         emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7414                 } else 
7415                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7416   }
7417 }
7418
7419 /*-----------------------------------------------------------------*/
7420 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7421 /*-----------------------------------------------------------------*/
7422 static void shiftLLeftOrResult (operand *left, int offl,
7423                                                                 operand *result, int offr, int shCount)
7424 {
7425         FENTRY;
7426         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7427         
7428         /* shift left accumulator */
7429         AccLsh(left,offl,shCount);
7430         /* or with result */
7431         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7432         assert ( !"broken (modifies left, fails for left==result))" );
7433 }
7434
7435 /*-----------------------------------------------------------------*/
7436 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7437 /*-----------------------------------------------------------------*/
7438 static void shiftRLeftOrResult (operand *left, int offl,
7439                                                                 operand *result, int offr, int shCount)
7440 {
7441         FENTRY;
7442         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7443         
7444         /* shift right accumulator */
7445         AccRsh(left,offl,shCount);
7446         /* or with result */
7447         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7448         assert ( !"broken (modifies left, fails for left==result))" );
7449 }
7450
7451 /*-----------------------------------------------------------------*/
7452 /* genlshOne - left shift a one byte quantity by known count       */
7453 /*-----------------------------------------------------------------*/
7454 static void genlshOne (operand *result, operand *left, int shCount)
7455 {       
7456         FENTRY;
7457         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7458         shiftL1Left2Result(left, LSB, result, LSB, shCount);
7459 }
7460
7461 /*-----------------------------------------------------------------*/
7462 /* genlshTwo - left shift two bytes by known amount != 0           */
7463 /*-----------------------------------------------------------------*/
7464 static void genlshTwo (operand *result,operand *left, int shCount)
7465 {
7466         int size;
7467         
7468         FENTRY;
7469         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7470         size = pic14_getDataSize(result);
7471         
7472         /* if shCount >= 8 */
7473         if (shCount >= 8) {
7474                 shCount -= 8 ;
7475                 
7476                 if (size > 1){
7477                         if (shCount)
7478                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7479                         else 
7480                                 movLeft2Result(left, LSB, result, MSB16);
7481                 }
7482                 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7483         }
7484         
7485         /*  1 <= shCount <= 7 */
7486         else {  
7487                 if(size == 1)
7488                         shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7489                 else 
7490                         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7491         }
7492 }
7493
7494 /*-----------------------------------------------------------------*/
7495 /* shiftLLong - shift left one long from left to result            */
7496 /* offl = LSB or MSB16                                             */
7497 /*-----------------------------------------------------------------*/
7498 static void shiftLLong (operand *left, operand *result, int offr )
7499 {
7500         char *l;
7501         int size = AOP_SIZE(result);
7502         
7503         FENTRY;
7504         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7505         if(size >= LSB+offr){
7506                 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7507                 MOVA(l);
7508                 pic14_emitcode("add","a,acc");
7509                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7510                         size >= MSB16+offr && offr != LSB )
7511                         pic14_emitcode("xch","a,%s",
7512                         aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7513                 else      
7514                         aopPut(AOP(result),"a",LSB+offr);
7515         }
7516         
7517         if(size >= MSB16+offr){
7518                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7519                         l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7520                         MOVA(l);
7521                 }
7522                 pic14_emitcode("rlc","a");
7523                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7524                         size >= MSB24+offr && offr != LSB)
7525                         pic14_emitcode("xch","a,%s",
7526                         aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7527                 else      
7528                         aopPut(AOP(result),"a",MSB16+offr);
7529         }
7530         
7531         if(size >= MSB24+offr){
7532                 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7533                         l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7534                         MOVA(l);
7535                 }
7536                 pic14_emitcode("rlc","a");
7537                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7538                         size >= MSB32+offr && offr != LSB )
7539                         pic14_emitcode("xch","a,%s",
7540                         aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7541                 else      
7542                         aopPut(AOP(result),"a",MSB24+offr);
7543         }
7544         
7545         if(size > MSB32+offr){
7546                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7547                         l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7548                         MOVA(l);  
7549                 }
7550                 pic14_emitcode("rlc","a");
7551                 aopPut(AOP(result),"a",MSB32+offr);
7552         }
7553         if(offr != LSB)
7554                 aopPut(AOP(result),zero,LSB);       
7555 }
7556
7557 /*-----------------------------------------------------------------*/
7558 /* genlshFour - shift four byte by a known amount != 0             */
7559 /*-----------------------------------------------------------------*/
7560 static void genlshFour (operand *result, operand *left, int shCount)
7561 {
7562         int size;
7563         
7564         FENTRY;
7565         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7566         size = AOP_SIZE(result);
7567         
7568         /* if shifting more that 3 bytes */
7569         if (shCount >= 24 ) {
7570                 shCount -= 24;
7571                 if (shCount)
7572                 /* lowest order of left goes to the highest
7573                 order of the destination */
7574                 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7575                 else
7576                         movLeft2Result(left, LSB, result, MSB32);
7577                 aopPut(AOP(result),zero,LSB);
7578                 aopPut(AOP(result),zero,MSB16);
7579                 aopPut(AOP(result),zero,MSB32);
7580                 return;
7581         }
7582         
7583         /* more than two bytes */
7584         else if ( shCount >= 16 ) {
7585                 /* lower order two bytes goes to higher order two bytes */
7586                 shCount -= 16;
7587                 /* if some more remaining */
7588                 if (shCount)
7589                         shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7590                 else {
7591                         movLeft2Result(left, MSB16, result, MSB32);
7592                         movLeft2Result(left, LSB, result, MSB24);
7593                 }
7594                 aopPut(AOP(result),zero,MSB16);
7595                 aopPut(AOP(result),zero,LSB);
7596                 return;
7597         }    
7598         
7599         /* if more than 1 byte */
7600         else if ( shCount >= 8 ) {
7601                 /* lower order three bytes goes to higher order  three bytes */
7602                 shCount -= 8;
7603                 if(size == 2){
7604                         if(shCount)
7605                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7606                         else
7607                                 movLeft2Result(left, LSB, result, MSB16);
7608                 }
7609                 else{   /* size = 4 */
7610                         if(shCount == 0){
7611                                 movLeft2Result(left, MSB24, result, MSB32);
7612                                 movLeft2Result(left, MSB16, result, MSB24);
7613                                 movLeft2Result(left, LSB, result, MSB16);
7614                                 aopPut(AOP(result),zero,LSB);
7615                         }
7616                         else if(shCount == 1)
7617                                 shiftLLong(left, result, MSB16);
7618                         else{
7619                                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7620                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7621                                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7622                                 aopPut(AOP(result),zero,LSB);
7623                         }
7624                 }
7625         }
7626         
7627         /* 1 <= shCount <= 7 */
7628         else if(shCount <= 2){
7629                 shiftLLong(left, result, LSB);
7630                 if(shCount == 2)
7631                         shiftLLong(result, result, LSB);
7632         }
7633         /* 3 <= shCount <= 7, optimize */
7634         else{
7635                 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7636                 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7637                 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7638         }
7639 }
7640 #endif
7641
7642 #if 0
7643 /*-----------------------------------------------------------------*/
7644 /* genLeftShiftLiteral - left shifting by known count              */
7645 /*-----------------------------------------------------------------*/
7646 static void genLeftShiftLiteral (operand *left,
7647                                                                  operand *right,
7648                                                                  operand *result,
7649                                                                  iCode *ic)
7650 {    
7651         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7652         //int size;
7653         
7654         FENTRY;
7655         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7656         freeAsmop(right,NULL,ic,TRUE);
7657         
7658         aopOp(left,ic,FALSE);
7659         aopOp(result,ic,FALSE);
7660
7661         size = getSize(operandType(result));
7662         
7663 #if VIEW_SIZE
7664         pic14_emitcode("; shift left ","result %d, left %d",size,
7665                 AOP_SIZE(left));
7666 #endif
7667         
7668         /* I suppose that the left size >= result size */
7669         if(shCount == 0){
7670                 while(size--){
7671                         movLeft2Result(left, size, result, size);
7672                 }
7673         }
7674         
7675         else if(shCount >= (size * 8))
7676                 while(size--)
7677                         aopPut(AOP(result),zero,size);
7678                 else{
7679                         switch (size) {
7680                         case 1:
7681                                 genlshOne (result,left,shCount);
7682                                 break;
7683                                 
7684                         case 2:
7685                         case 3:
7686                                 genlshTwo (result,left,shCount);
7687                                 break;
7688                                 
7689                         case 4:
7690                                 genlshFour (result,left,shCount);
7691                                 break;
7692                         }
7693                 }
7694                 freeAsmop(left,NULL,ic,TRUE);
7695                 freeAsmop(result,NULL,ic,TRUE);
7696 }
7697 #endif
7698
7699 /*-----------------------------------------------------------------*
7700 * genMultiAsm - repeat assembly instruction for size of register.
7701 * if endian == 1, then the high byte (i.e base address + size of 
7702 * register) is used first else the low byte is used first;
7703 *-----------------------------------------------------------------*/
7704 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7705 {
7706         
7707         int offset = 0;
7708         
7709         FENTRY;
7710         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7711         
7712         if(!reg)
7713                 return;
7714         
7715         if(!endian) {
7716                 endian = 1;
7717         } else {
7718                 endian = -1;
7719                 offset = size-1;
7720         }
7721         
7722         while(size--) {
7723                 emitpcode(poc,    popGet(AOP(reg),offset));
7724                 offset += endian;
7725         }
7726         
7727 }
7728
7729 #if 0
7730 /*-----------------------------------------------------------------*/
7731 /* genLeftShift - generates code for left shifting                 */
7732 /*-----------------------------------------------------------------*/
7733 static void genLeftShift (iCode *ic)
7734 {
7735         operand *left,*right, *result;
7736         int size, offset;
7737         unsigned long lit = 0L;
7738         char *l;
7739         symbol *tlbl , *tlbl1;
7740         pCodeOp *pctemp;
7741         
7742         FENTRY;
7743         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7744         
7745         right = IC_RIGHT(ic);
7746         left  = IC_LEFT(ic);
7747         result = IC_RESULT(ic);
7748         
7749         aopOp(right,ic,FALSE);
7750         aopOp(left,ic,FALSE);
7751         aopOp(result,ic,FALSE);
7752         
7753         
7754         /* if the shift count is known then do it 
7755         as efficiently as possible */
7756         if (AOP_TYPE(right) == AOP_LIT) {
7757                 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7758                 return ;
7759         }
7760         
7761         /* shift count is unknown then we have to form 
7762         a loop get the loop count in B : Note: we take
7763         only the lower order byte since shifting
7764         more that 32 bits make no sense anyway, ( the
7765         largest size of an object can be only 32 bits ) */  
7766         
7767         /* this code fails for RIGHT == RESULT */
7768         assert (!pic14_sameRegs (AOP(right), AOP(result)));
7769         
7770         /* now move the left to the result if they are not the
7771         same */
7772         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7773                 AOP_SIZE(result) > 1) {
7774                 
7775                 size = AOP_SIZE(result);
7776                 offset=0;
7777                 while (size--) {
7778                         l = aopGet(AOP(left),offset,FALSE,TRUE);
7779                         if (*l == '@' && (IS_AOP_PREG(result))) {
7780                                 
7781                                 pic14_emitcode("mov","a,%s",l);
7782                                 aopPut(AOP(result),"a",offset);
7783                         } else {
7784                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7785                                 emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7786                                 //aopPut(AOP(result),l,offset);
7787                         }
7788                         offset++;
7789                 }
7790         }
7791         
7792         if(AOP_TYPE(left) == AOP_LIT)
7793                 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7794
7795         size = AOP_SIZE(result);
7796         
7797         /* if it is only one byte then */
7798         if (size == 1) {
7799                 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7800                         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7801                         emitpcode(POC_ANDLW,  popGetLit(0xf0));
7802                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7803                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7804                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7805                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7806                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7807                         emitpcode(POC_RLFW,   popGet(AOP(result),0));
7808                         emitpcode(POC_ANDLW,  popGetLit(0xfe));
7809                         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7810                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7811                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7812                 } else {
7813                         
7814                         tlbl = newiTempLabel(NULL);
7815                         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7816                                 mov2w (AOP(left), 0);
7817                                 emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7818                         }
7819                         
7820                         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7821                         emitpcode(POC_RRF,    popGet(AOP(result),0));
7822                         emitpLabel(tlbl->key);
7823                         emitpcode(POC_RLF,    popGet(AOP(result),0));
7824                         emitpcode(POC_ADDLW,  popGetLit(1));
7825                         emitSKPC;
7826                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7827                 }
7828                 goto release ;
7829         }
7830         
7831         if (pic14_sameRegs(AOP(left),AOP(result))) {
7832                 
7833                 tlbl = newiTempLabel(NULL);
7834                 emitpcode(POC_COMFW,  popGet(AOP(right),0));
7835                 genMultiAsm(POC_RRF, result, size,1);
7836                 emitpLabel(tlbl->key);
7837                 genMultiAsm(POC_RLF, result, size,0);
7838                 emitpcode(POC_ADDLW,  popGetLit(1));
7839                 emitSKPC;
7840                 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7841                 goto release;
7842         }
7843         
7844         //tlbl = newiTempLabel(NULL);
7845         //offset = 0 ;   
7846         //tlbl1 = newiTempLabel(NULL);
7847         
7848         //reAdjustPreg(AOP(result));    
7849         
7850         //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7851         //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7852         //l = aopGet(AOP(result),offset,FALSE,FALSE);
7853         //MOVA(l);
7854         //pic14_emitcode("add","a,acc");         
7855         //aopPut(AOP(result),"a",offset++);
7856         //while (--size) {
7857         //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7858         //  MOVA(l);
7859         //  pic14_emitcode("rlc","a");         
7860         //  aopPut(AOP(result),"a",offset++);
7861         //}
7862         //reAdjustPreg(AOP(result));
7863         
7864         //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7865         //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7866         
7867         
7868         tlbl = newiTempLabel(NULL);
7869         tlbl1= newiTempLabel(NULL);
7870         
7871         size = AOP_SIZE(result);
7872         offset = 1;
7873         
7874         pctemp = popGetTempReg();  /* grab a temporary working register. */
7875         
7876         emitpcode(POC_MOVFW, popGet(AOP(right),0));
7877         
7878         /* offset should be 0, 1 or 3 */
7879         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7880         emitSKPNZ;
7881         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7882         
7883         emitpcode(POC_MOVWF, pctemp);
7884         
7885         
7886         emitpLabel(tlbl->key);
7887         
7888         emitCLRC;
7889         emitpcode(POC_RLF,  popGet(AOP(result),0));
7890         while(--size)
7891                 emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7892         
7893         emitpcode(POC_DECFSZ,  pctemp);
7894         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7895         emitpLabel(tlbl1->key);
7896         
7897         popReleaseTempReg(pctemp);
7898         
7899         
7900 release:
7901         freeAsmop (right,NULL,ic,TRUE);
7902         freeAsmop(left,NULL,ic,TRUE);
7903         freeAsmop(result,NULL,ic,TRUE);
7904 }
7905 #endif
7906
7907 #if 0
7908 /*-----------------------------------------------------------------*/
7909 /* genrshOne - right shift a one byte quantity by known count      */
7910 /*-----------------------------------------------------------------*/
7911 static void genrshOne (operand *result, operand *left,
7912                                            int shCount, int sign)
7913 {
7914         FENTRY;
7915         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7916         shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7917 }
7918
7919 /*-----------------------------------------------------------------*/
7920 /* genrshTwo - right shift two bytes by known amount != 0          */
7921 /*-----------------------------------------------------------------*/
7922 static void genrshTwo (operand *result,operand *left,
7923                                            int shCount, int sign)
7924 {
7925         FENTRY;
7926         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7927         /* if shCount >= 8 */
7928         if (shCount >= 8) {
7929                 shCount -= 8 ;
7930                 if (shCount)
7931                         shiftR1Left2Result(left, MSB16, result, LSB,
7932                         shCount, sign);
7933                 else
7934                         movLeft2Result(left, MSB16, result, LSB);
7935                 
7936                 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7937                 
7938                 if(sign) {
7939                         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7940                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7941                 }
7942         }
7943         
7944         /*  1 <= shCount <= 7 */
7945         else
7946                 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7947 }
7948
7949 /*-----------------------------------------------------------------*/
7950 /* shiftRLong - shift right one long from left to result           */
7951 /* offl = LSB or MSB16                                             */
7952 /*-----------------------------------------------------------------*/
7953 static void shiftRLong (operand *left, int offl,
7954                                                 operand *result, int sign)
7955 {
7956         int size, same;
7957         
7958         FENTRY;
7959         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7960         
7961         size = AOP_SIZE(left);
7962         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7963         
7964         if (sign)
7965                 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7966         else
7967                 emitCLRC;
7968
7969         assert (offl >= 0 && offl < size);
7970
7971         same = pic14_sameRegs (AOP(left), AOP(result));
7972
7973         /* perform the shift */
7974         while (size--)
7975         {
7976                 if (same && !offl) {
7977                         emitpcode (POC_RRF, popGet (AOP(result), size));
7978                 } else {
7979                         emitpcode (POC_RRFW, popGet (AOP(left), size));
7980                         emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7981                 }
7982         } // while
7983
7984         addSign (result, AOP_SIZE(left) - offl, sign);
7985 }
7986
7987 /*-----------------------------------------------------------------*/
7988 /* genrshFour - shift four byte by a known amount != 0             */
7989 /*-----------------------------------------------------------------*/
7990 static void genrshFour (operand *result, operand *left,
7991                                                 int shCount, int sign)
7992 {
7993         FENTRY;
7994         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7995         /* if shifting more that 3 bytes */
7996         if(shCount >= 24 ) {
7997                 shCount -= 24;
7998                 if(shCount)
7999                         shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8000                 else
8001                         movLeft2Result(left, MSB32, result, LSB);
8002                 
8003                 addSign(result, MSB16, sign);
8004         }
8005         else if(shCount >= 16){
8006                 shCount -= 16;
8007                 if(shCount)
8008                         shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8009                 else{
8010                         movLeft2Result(left, MSB24, result, LSB);
8011                         movLeft2Result(left, MSB32, result, MSB16);
8012                 }
8013                 addSign(result, MSB24, sign);
8014         }
8015         else if(shCount >= 8){
8016                 shCount -= 8;
8017                 if(shCount == 1)
8018                         shiftRLong(left, MSB16, result, sign);
8019                 else if(shCount == 0){
8020                         movLeft2Result(left, MSB16, result, LSB);
8021                         movLeft2Result(left, MSB24, result, MSB16);
8022                         movLeft2Result(left, MSB32, result, MSB24);
8023                         addSign(result, MSB32, sign);
8024                 }
8025                 else{
8026                         shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8027                         shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8028                         /* the last shift is signed */
8029                         shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8030                         addSign(result, MSB32, sign);
8031                 }
8032         }
8033         else{   /* 1 <= shCount <= 7 */
8034                 if(shCount <= 2){
8035                         shiftRLong(left, LSB, result, sign);
8036                         if(shCount == 2)
8037                                 shiftRLong(result, LSB, result, sign);
8038                 }
8039                 else{
8040                         shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8041                         shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8042                         shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8043                 }
8044         }
8045 }
8046
8047 /*-----------------------------------------------------------------*/
8048 /* genRightShiftLiteral - right shifting by known count            */
8049 /*-----------------------------------------------------------------*/
8050 static void genRightShiftLiteral (operand *left,
8051                                                                   operand *right,
8052                                                                   operand *result,
8053                                                                   iCode *ic,
8054                                                                   int sign)
8055 {    
8056         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8057         int lsize,res_size;
8058         
8059         FENTRY;
8060         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8061         freeAsmop(right,NULL,ic,TRUE);
8062         
8063         aopOp(left,ic,FALSE);
8064         aopOp(result,ic,FALSE);
8065         
8066 #if VIEW_SIZE
8067         pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8068                 AOP_SIZE(left));
8069 #endif
8070         
8071         lsize = pic14_getDataSize(left);
8072         res_size = pic14_getDataSize(result);
8073         /* test the LEFT size !!! */
8074         
8075         /* I suppose that the left size >= result size */
8076         if(shCount == 0){
8077                 while(res_size--)
8078                         movLeft2Result(left, res_size, result, res_size);
8079         }
8080         
8081         else if(shCount >= (lsize * 8)){
8082                 
8083                 if(res_size == 1) {
8084                         emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8085                         if(sign) {
8086                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8087                                 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8088                         }
8089                 } else {
8090                         
8091                         if(sign) {
8092                                 emitpcode(POC_MOVLW, popGetLit(0));
8093                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8094                                 emitpcode(POC_MOVLW, popGetLit(0xff));
8095                                 while(res_size--)
8096                                         emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8097                                 
8098                         } else {
8099                                 
8100                                 while(res_size--)
8101                                         emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8102                         }
8103                 }
8104         } else {
8105                 
8106                 switch (res_size) {
8107                 case 1:
8108                         genrshOne (result,left,shCount,sign);
8109                         break;
8110                         
8111                 case 2:
8112                         genrshTwo (result,left,shCount,sign);
8113                         break;
8114                         
8115                 case 4:
8116                         genrshFour (result,left,shCount,sign);
8117                         break;
8118                 default :
8119                         break;
8120                 }
8121                 
8122         }
8123
8124         freeAsmop(left,NULL,ic,TRUE);
8125         freeAsmop(result,NULL,ic,TRUE);
8126 }
8127 #endif
8128
8129 #if 0
8130 /*-----------------------------------------------------------------*/
8131 /* genSignedRightShift - right shift of signed number              */
8132 /*-----------------------------------------------------------------*/
8133 static void genSignedRightShift (iCode *ic)
8134 {
8135         operand *right, *left, *result;
8136         int size, offset;
8137         //  char *l;
8138         symbol *tlbl, *tlbl1 ;
8139         pCodeOp *pctemp;
8140         
8141         //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8142         
8143         /* we do it the hard way put the shift count in b
8144         and loop thru preserving the sign */
8145         FENTRY;
8146         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8147         
8148         right = IC_RIGHT(ic);
8149         left  = IC_LEFT(ic);
8150         result = IC_RESULT(ic);
8151         
8152         aopOp(right,ic,FALSE);  
8153         aopOp(left,ic,FALSE);
8154         aopOp(result,ic,FALSE);
8155         
8156         
8157         if ( AOP_TYPE(right) == AOP_LIT) {
8158                 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8159                 //genRightShiftLiteral (left,right,result,ic,1);
8160                 return ;
8161         }
8162         /* shift count is unknown then we have to form 
8163         a loop get the loop count in B : Note: we take
8164         only the lower order byte since shifting
8165         more that 32 bits make no sense anyway, ( the
8166         largest size of an object can be only 32 bits ) */  
8167         
8168         //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8169         //pic14_emitcode("inc","b");
8170         //freeAsmop (right,NULL,ic,TRUE);
8171         //aopOp(left,ic,FALSE);
8172         //aopOp(result,ic,FALSE);
8173         
8174         /* now move the left to the result if they are not the
8175         same */
8176         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
8177                 AOP_SIZE(result) > 1) {
8178                 
8179                 size = AOP_SIZE(result);
8180                 offset=0;
8181                 while (size--) { 
8182                         /*
8183                         l = aopGet(AOP(left),offset,FALSE,TRUE);
8184                         if (*l == '@' && IS_AOP_PREG(result)) {
8185                                 pic14_emitcode("mov","a,%s",l);
8186                                 aopPut(AOP(result),"a",offset);
8187                         } else
8188                         aopPut(AOP(result),l,offset);
8189                         */
8190                         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
8191                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
8192                         
8193                         offset++;
8194                 }
8195         }
8196         
8197         /* mov the highest order bit to OVR */    
8198         tlbl = newiTempLabel(NULL);
8199         tlbl1= newiTempLabel(NULL);
8200         
8201         size = AOP_SIZE(result);
8202         offset = size - 1;
8203         
8204         pctemp = popGetTempReg();  /* grab a temporary working register. */
8205         
8206         emitpcode(POC_MOVFW, popGet(AOP(right),0));
8207         
8208         /* offset should be 0, 1 or 3 */
8209         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8210         emitSKPNZ;
8211         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
8212         
8213         emitpcode(POC_MOVWF, pctemp);
8214         
8215         
8216         emitpLabel(tlbl->key);
8217         
8218         emitpcode(POC_RLFW,  popGet(AOP(result),offset));
8219         emitpcode(POC_RRF,   popGet(AOP(result),offset));
8220         
8221         while(--size) {
8222                 emitpcode(POC_RRF,   popGet(AOP(result),--offset));
8223         }
8224         
8225         emitpcode(POC_DECFSZ,  pctemp);
8226         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8227         emitpLabel(tlbl1->key);
8228         
8229         popReleaseTempReg(pctemp);
8230 #if 0
8231         size = AOP_SIZE(result);
8232         offset = size - 1;
8233         pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8234         pic14_emitcode("rlc","a");
8235         pic14_emitcode("mov","ov,c");
8236         /* if it is only one byte then */
8237         if (size == 1) {
8238                 l = aopGet(AOP(left),0,FALSE,FALSE);
8239                 MOVA(l);
8240                 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8241                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8242                 pic14_emitcode("mov","c,ov");
8243                 pic14_emitcode("rrc","a");
8244                 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8245                 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8246                 aopPut(AOP(result),"a",0);
8247                 goto release ;
8248         }
8249         
8250         reAdjustPreg(AOP(result));
8251         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8252         pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
8253         pic14_emitcode("mov","c,ov");
8254         while (size--) {
8255                 l = aopGet(AOP(result),offset,FALSE,FALSE);
8256                 MOVA(l);
8257                 pic14_emitcode("rrc","a");         
8258                 aopPut(AOP(result),"a",offset--);
8259         }
8260         reAdjustPreg(AOP(result));
8261         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8262         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8263         
8264 release:
8265 #endif
8266         
8267         freeAsmop(left,NULL,ic,TRUE);
8268         freeAsmop(result,NULL,ic,TRUE);
8269         freeAsmop(right,NULL,ic,TRUE);
8270 }
8271 #endif
8272
8273 /*-----------------------------------------------------------------*/
8274 /* loadSignToC - load the operand's sign bit into CARRY            */
8275 /*-----------------------------------------------------------------*/
8276
8277 static void loadSignToC (operand *op)
8278 {
8279         FENTRY;
8280         assert (op && AOP(op) && AOP_SIZE(op));
8281
8282         emitCLRC;
8283         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8284         emitSETC;
8285 }
8286
8287 /*-----------------------------------------------------------------*/
8288 /* genRightShift - generate code for right shifting                */
8289 /*-----------------------------------------------------------------*/
8290 static void genGenericShift (iCode *ic, int shiftRight)
8291 {
8292         operand *right, *left, *result;
8293         sym_link *retype ;
8294         int size;
8295         symbol *tlbl, *tlbl1, *inverselbl;
8296         
8297         FENTRY;
8298         /* if signed then we do it the hard way preserve the
8299         sign bit moving it inwards */
8300         retype = getSpec(operandType(IC_RESULT(ic)));
8301         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8302         
8303         /* signed & unsigned types are treated the same : i.e. the
8304         signed is NOT propagated inwards : quoting from the
8305         ANSI - standard : "for E1 >> E2, is equivalent to division
8306         by 2**E2 if unsigned or if it has a non-negative value,
8307         otherwise the result is implementation defined ", MY definition
8308         is that the sign does not get propagated */
8309         
8310         right = IC_RIGHT(ic);
8311         left  = IC_LEFT(ic);
8312         result = IC_RESULT(ic);
8313         
8314         aopOp(right,ic,FALSE);
8315         aopOp(left,ic,FALSE);
8316         aopOp(result,ic,FALSE);
8317         
8318         /* if the shift count is known then do it 
8319         as efficiently as possible */
8320         if (AOP_TYPE(right) == AOP_LIT) {
8321                 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8322                 if (lit < 0)
8323                 {
8324                         lit = -lit;
8325                         shiftRight = !shiftRight;
8326                 }
8327                 
8328                 if (shiftRight)
8329                         shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8330                 else
8331                         shiftLeft_Left2ResultLit (left, result, lit);
8332                 //genRightShiftLiteral (left,right,result,ic, 0);
8333                 return ;
8334         }
8335         
8336         /* shift count is unknown then we have to form 
8337         a loop get the loop count in B : Note: we take
8338         only the lower order byte since shifting
8339         more that 32 bits make no sense anyway, ( the
8340         largest size of an object can be only 32 bits ) */  
8341
8342         /* we must not overwrite the shift counter */
8343         assert (!pic14_sameRegs(AOP(right),AOP(result)));
8344         
8345         /* now move the left to the result if they are not the
8346         same */
8347         if (!pic14_sameRegs(AOP(left),AOP(result)))
8348         {
8349                 size = min(AOP_SIZE(result), AOP_SIZE(left));
8350                 while (size--) {
8351                         mov2w(AOP(left), size);
8352                         movwf(AOP(result), size);
8353                 }
8354                 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8355         }
8356         
8357         tlbl = newiTempLabel(NULL);
8358         tlbl1= newiTempLabel(NULL);
8359         inverselbl = NULL;
8360         size = AOP_SIZE(result);
8361
8362         mov2w(AOP(right),0);
8363         if (!SPEC_USIGN(operandType(right)))
8364         {
8365                 inverselbl = newiTempLabel(NULL);
8366                 /* signed shift count -- invert shift direction for c<0 */
8367                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8368                 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8369         } // if
8370         emitpcode(POC_SUBLW, popGetLit(0));     /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8371         /* check for `a = b >> c' with `-c == 0' */
8372         emitSKPNZ;
8373         emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8374         emitpLabel(tlbl->key);
8375         /* propagate the sign bit inwards for SIGNED result */
8376         if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8377         genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8378         emitpcode(POC_ADDLW,  popGetLit(1));    /* clears CARRY (unless W==0 afterwards) */
8379         emitSKPC;
8380         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8381
8382         if (!SPEC_USIGN(operandType(right)))
8383         {
8384                 symbol *inv_loop = newiTempLabel(NULL);
8385
8386                 shiftRight = !shiftRight;       /* invert shift direction */
8387                 
8388                 /* we came here from the code above -- we are done */
8389                 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8390                 
8391                 /* emit code for shifting N<0 steps, count is already in W */
8392                 emitpLabel(inverselbl->key);
8393                 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8394                 emitpLabel(inv_loop->key);
8395                 /* propagate the sign bit inwards for SIGNED result */
8396                 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8397                 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8398                 emitpcode(POC_ADDLW, popGetLit(1));
8399                 emitSKPC;
8400                 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8401         } // if
8402         
8403         emitpLabel(tlbl1->key);
8404         
8405         freeAsmop(left,NULL,ic,TRUE);
8406         freeAsmop (right,NULL,ic,TRUE);
8407         freeAsmop(result,NULL,ic,TRUE);
8408 }
8409
8410 static void genRightShift (iCode *ic)
8411 {
8412         genGenericShift(ic, 1);
8413 }
8414
8415 static void genLeftShift (iCode *ic)
8416 {
8417         genGenericShift(ic, 0);
8418 }
8419
8420 /*-----------------------------------------------------------------*/
8421 /* SetIrp - Set IRP bit                                            */
8422 /*-----------------------------------------------------------------*/
8423 void SetIrp(operand *result) {
8424         FENTRY;
8425         if (AOP_TYPE(result) == AOP_LIT) {
8426                 unsigned lit = (unsigned)operandLitValue(result);
8427                 if (lit&0x100)
8428                         emitSETIRP;
8429                 else
8430                         emitCLRIRP;
8431         } else {
8432                 if (PCOP(AOP(result))->type == PO_LITERAL) {
8433                         int addrs = PCOL(AOP(result))->lit;
8434                         if (addrs & 0x100)
8435                                 emitSETIRP;
8436                         else
8437                                 emitCLRIRP;
8438                 } else {
8439                         emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8440                         if(AOP_SIZE(result) > 1) {
8441                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8442                                 emitSETIRP;
8443                         }
8444                 }
8445         }
8446 }
8447
8448 static void
8449 setup_fsr (operand *ptr)
8450 {
8451   mov2w_op(ptr, 0);
8452   emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8453
8454   /* also setup-up IRP */
8455   SetIrp (ptr);
8456 }
8457
8458 /*-----------------------------------------------------------------*/
8459 /* emitPtrByteGet - emits code to get a byte into WREG from an     */
8460 /*                  arbitrary pointer (__code, __data, generic)    */
8461 /*-----------------------------------------------------------------*/
8462 static void
8463 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8464 {
8465     FENTRY;
8466     switch (p_type)
8467     {
8468     case POINTER:
8469     case FPOINTER:
8470       if (!alreadyAddressed) setup_fsr (src);
8471       emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8472       break;
8473     
8474     case CPOINTER:
8475       assert( AOP_SIZE(src) == 2 );
8476       mov2w_op(src, 0);
8477       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8478       mov2w_op(src, 1);
8479       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8480       emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE));   /* GPOINTER tag for __code space */
8481       call_libraryfunc ("__gptrget1");
8482       break;
8483     
8484     case GPOINTER:
8485       assert( AOP_SIZE(src) == 3 );
8486       mov2w_op(src, 0);
8487       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8488       mov2w_op(src, 1);
8489       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8490       mov2w_op(src, 2);
8491       call_libraryfunc ("__gptrget1");
8492       break;
8493     
8494     default:
8495       assert( !"unhandled pointer type" );
8496       break;
8497     }
8498 }
8499
8500 /*-----------------------------------------------------------------*/
8501 /* emitPtrByteSet - emits code to set a byte from src through a    */
8502 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR).       */
8503 /*-----------------------------------------------------------------*/
8504 static void
8505 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8506 {
8507     FENTRY;
8508     switch (p_type)
8509     {
8510     case POINTER:
8511     case FPOINTER:
8512       if (!alreadyAddressed) setup_fsr (dst);
8513       emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8514       break;
8515     
8516     case CPOINTER:
8517       assert( !"trying to assign to __code pointer" );
8518       break;
8519     
8520     case GPOINTER:
8521       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8522       mov2w_op(dst, 0);
8523       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8524       mov2w_op(dst, 1);
8525       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8526       mov2w_op(dst, 2);
8527       call_libraryfunc ("__gptrput1");
8528       break;
8529
8530     default:
8531       assert( !"unhandled pointer type" );
8532       break;
8533     }
8534 }
8535
8536 /*-----------------------------------------------------------------*/
8537 /* genUnpackBits - generates code for unpacking bits               */
8538 /*-----------------------------------------------------------------*/
8539 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8540 {    
8541   int rsize;            /* result size */
8542   sym_link *etype;      /* bitfield type information */
8543   int blen;             /* bitfield length */
8544   int bstr;             /* bitfield starting bit within byte */
8545
8546   FENTRY;
8547   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8548   etype = getSpec(operandType(result));
8549   rsize = getSize (operandType (result));
8550   blen = SPEC_BLEN (etype);
8551   bstr = SPEC_BSTR (etype);
8552
8553   /* single bit field case */
8554   if (blen == 1) {
8555     if (ifx) { /* that is for an if statement */
8556       pCodeOp *pcop;
8557       resolvedIfx rIfx;
8558       resolveIfx(&rIfx,ifx);
8559       if (ptype == -1) /* direct */
8560         pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8561       else
8562         pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8563       emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8564       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8565       ifx->generated=1;
8566     } else {
8567       int i;
8568       assert (!pic14_sameRegs (AOP(result), AOP(left)));
8569       for (i=0; i < AOP_SIZE(result); i++)
8570         emitpcode (POC_CLRF, popGet (AOP(result), i));
8571
8572       switch (ptype)
8573       {
8574       case -1:
8575         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8576         /* adjust result below */
8577         break;
8578         
8579       case POINTER:
8580       case FPOINTER:
8581       case GPOINTER:
8582       case CPOINTER:
8583         emitPtrByteGet (left, ptype, FALSE);
8584         emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8585         emitSKPZ;
8586         /* adjust result below */
8587         break;
8588         
8589       default:
8590         assert( !"unhandled pointer type" );
8591       } // switch
8592
8593       /* move sign-/zero extended bit to result */
8594       if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8595         emitpcode (POC_INCF, popGet (AOP(result), 0));
8596       } else {
8597         emitpcode (POC_DECF, popGet (AOP(result), 0));
8598       }
8599       addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8600     }
8601     return;
8602   }
8603   else if (blen <= 8 && ((blen + bstr) <= 8))
8604   {
8605     /* blen > 1 */
8606     int i;
8607
8608     for (i=0; i < AOP_SIZE(result); i++)
8609       emitpcode (POC_CLRF, popGet (AOP(result), i));
8610
8611     switch (ptype)
8612     {
8613     case -1:
8614       mov2w(AOP(left), 0);
8615       break;
8616       
8617     case POINTER:
8618     case FPOINTER:
8619     case GPOINTER:
8620     case CPOINTER:
8621       emitPtrByteGet (left, ptype, FALSE);
8622       break;
8623       
8624     default:
8625       assert( !"unhandled pointer type" );
8626     } // switch
8627
8628     if (blen < 8)
8629       emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8630     movwf(AOP(result), 0);
8631     AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8632
8633     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8634     {
8635       /* signed bitfield */
8636       assert (bstr + blen > 0);
8637       emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8638       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8639       emitpcode(POC_IORWF, popGet(AOP(result),0));
8640     }
8641     addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8642     return;
8643   }
8644
8645   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8646 }
8647
8648 #if 1
8649 /*-----------------------------------------------------------------*/
8650 /* genDataPointerGet - generates code when ptr offset is known     */
8651 /*-----------------------------------------------------------------*/
8652 static void genDataPointerGet (operand *left, 
8653         operand *result, 
8654         iCode *ic)
8655 {
8656         int size , offset = 0;
8657                 
8658         FENTRY;
8659         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8660         
8661         
8662         /* optimization - most of the time, left and result are the same
8663         * address, but different types. for the pic code, we could omit
8664         * the following
8665         */
8666         aopOp(result,ic,TRUE);
8667         
8668         if (pic14_sameRegs (AOP(left), AOP(result)))
8669                 return;
8670         
8671         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8672         
8673         //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8674         
8675         size = AOP_SIZE(result);
8676         if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8677         
8678         offset = 0;
8679         while (size--) {
8680                 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8681                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8682                 offset++;
8683         }
8684         
8685         freeAsmop(left,NULL,ic,TRUE);
8686         freeAsmop(result,NULL,ic,TRUE);
8687 }
8688 #endif
8689
8690 /*-----------------------------------------------------------------*/
8691 /* genNearPointerGet - pic14_emitcode for near pointer fetch       */
8692 /*-----------------------------------------------------------------*/
8693 static void genNearPointerGet (operand *left, 
8694                                                            operand *result, 
8695                                                            iCode *ic)
8696 {
8697         asmop *aop = NULL;
8698         sym_link *ltype = operandType(left);
8699         sym_link *rtype = operandType(result);
8700         sym_link *retype= getSpec(rtype);      /* bitfield type information */
8701         int direct = 0;
8702
8703         FENTRY;
8704         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8705         
8706         
8707         aopOp(left,ic,FALSE);
8708         
8709         /* if left is rematerialisable and
8710         result is not bit variable type and
8711         the left is pointer to data space i.e
8712         lower 128 bytes of space */
8713         if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8714                 !IS_BITVAR(retype)         &&
8715                 PIC_IS_DATA_PTR(ltype)) {
8716                 genDataPointerGet (left,result,ic);
8717                 return ;
8718         }
8719         
8720         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8721         aopOp (result,ic,FALSE);
8722         
8723         /* Check if can access directly instead of via a pointer */
8724         if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8725                 && AOP_SIZE(result) == 1)
8726         {
8727                 direct = 1;
8728         }
8729
8730         if (IS_BITFIELD(getSpec(operandType(result)))) 
8731         {
8732                 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8733                 goto release;
8734         }
8735         
8736         /* If the pointer value is not in a the FSR then need to put it in */
8737         /* Must set/reset IRP bit for use with FSR. */
8738         if (!direct)
8739           setup_fsr (left);
8740         
8741 //      sym_link *etype;
8742         /* if bitfield then unpack the bits */
8743         {
8744                 /* we have can just get the values */
8745                 int size = AOP_SIZE(result);
8746                 int offset = 0 ;  
8747                 
8748                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8749                 
8750                 while(size--) {
8751                         if (direct)
8752                                 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8753                         else
8754                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8755                         if (AOP_TYPE(result) == AOP_LIT) {
8756                                 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8757                         } else {
8758                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8759                         }
8760                         if (size && !direct)
8761                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8762                         offset++;
8763                 }
8764         }
8765         
8766         /* now some housekeeping stuff */
8767         if (aop) {
8768                 /* we had to allocate for this iCode */
8769                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8770                 freeAsmop(NULL,aop,ic,TRUE);
8771         } else { 
8772                 /* we did not allocate which means left
8773                 already in a pointer register, then
8774                 if size > 0 && this could be used again
8775                 we have to point it back to where it 
8776                 belongs */
8777                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8778                 if (AOP_SIZE(result) > 1 &&
8779                         !OP_SYMBOL(left)->remat &&
8780                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8781                         ic->depth )) {
8782                         int size = AOP_SIZE(result) - 1;
8783                         while (size--)
8784                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8785                 }
8786         }
8787         
8788 release:
8789         /* done */
8790         freeAsmop(left,NULL,ic,TRUE);
8791         freeAsmop(result,NULL,ic,TRUE);
8792
8793 }
8794
8795 #if 0
8796 /*-----------------------------------------------------------------*/
8797 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8798 /*-----------------------------------------------------------------*/
8799 static void genPagedPointerGet (operand *left, 
8800                                                                 operand *result, 
8801                                                                 iCode *ic)
8802 {
8803         asmop *aop = NULL;
8804         regs *preg = NULL ;
8805         char *rname ;
8806         sym_link *rtype, *retype;    
8807         
8808         FENTRY;
8809         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8810         
8811         rtype = operandType(result);
8812         retype= getSpec(rtype);
8813         
8814         aopOp(left,ic,FALSE);
8815         
8816         /* if the value is already in a pointer register
8817         then don't need anything more */
8818         if (!AOP_INPREG(AOP(left))) {
8819                 /* otherwise get a free pointer register */
8820                 aop = newAsmop(0);
8821                 preg = getFreePtr(ic,&aop,FALSE);
8822                 pic14_emitcode("mov","%s,%s",
8823                         preg->name,
8824                         aopGet(AOP(left),0,FALSE,TRUE));
8825                 rname = preg->name ;
8826         } else
8827                 rname = aopGet(AOP(left),0,FALSE,FALSE);
8828         
8829         freeAsmop(left,NULL,ic,TRUE);
8830         aopOp (result,ic,FALSE);
8831         
8832         /* if bitfield then unpack the bits */
8833         if (IS_BITFIELD(retype)) 
8834                 genUnpackBits (result,left,rname,PPOINTER,0);
8835         else {
8836                 /* we have can just get the values */
8837                 int size = AOP_SIZE(result);
8838                 int offset = 0 ;  
8839                 
8840                 while (size--) {
8841                         
8842                         pic14_emitcode("movx","a,@%s",rname);
8843                         aopPut(AOP(result),"a",offset);
8844                         
8845                         offset++ ;
8846                         
8847                         if (size)
8848                                 pic14_emitcode("inc","%s",rname);
8849                 }
8850         }
8851         
8852         /* now some housekeeping stuff */
8853         if (aop) {
8854                 /* we had to allocate for this iCode */
8855                 freeAsmop(NULL,aop,ic,TRUE);
8856         } else { 
8857         /* we did not allocate which means left
8858         already in a pointer register, then
8859         if size > 0 && this could be used again
8860         we have to point it back to where it 
8861                 belongs */
8862                 if (AOP_SIZE(result) > 1 &&
8863                         !OP_SYMBOL(left)->remat &&
8864                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8865                         ic->depth )) {
8866                         int size = AOP_SIZE(result) - 1;
8867                         while (size--)
8868                                 pic14_emitcode("dec","%s",rname);
8869                 }
8870         }
8871         
8872         /* done */
8873         freeAsmop(result,NULL,ic,TRUE);
8874         
8875         
8876 }
8877
8878 /*-----------------------------------------------------------------*/
8879 /* genFarPointerGet - gget value from far space                    */
8880 /*-----------------------------------------------------------------*/
8881 static void genFarPointerGet (operand *left,
8882                                                           operand *result, iCode *ic)
8883 {
8884         int size, offset ;
8885         sym_link *retype = getSpec(operandType(result));
8886         
8887         FENTRY;
8888         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8889         
8890         aopOp(left,ic,FALSE);
8891         
8892         /* if the operand is already in dptr 
8893         then we do nothing else we move the value to dptr */
8894         if (AOP_TYPE(left) != AOP_STR) {
8895                 /* if this is remateriazable */
8896                 if (AOP_TYPE(left) == AOP_IMMD)
8897                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8898                 else { /* we need to get it byte by byte */
8899                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8900                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8901                         if (options.model == MODEL_FLAT24)
8902                         {
8903                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8904                         }
8905                 }
8906         }
8907         /* so dptr know contains the address */
8908         freeAsmop(left,NULL,ic,TRUE);
8909         aopOp(result,ic,FALSE);
8910         
8911         /* if bit then unpack */
8912         if (IS_BITFIELD(retype)) 
8913                 genUnpackBits(result,left,"dptr",FPOINTER,0);
8914         else {
8915                 size = AOP_SIZE(result);
8916                 offset = 0 ;
8917                 
8918                 while (size--) {
8919                         pic14_emitcode("movx","a,@dptr");
8920                         aopPut(AOP(result),"a",offset++);
8921                         if (size)
8922                                 pic14_emitcode("inc","dptr");
8923                 }
8924         }
8925         
8926         freeAsmop(result,NULL,ic,TRUE);
8927 }
8928 #endif
8929
8930 #if 0
8931 /*-----------------------------------------------------------------*/
8932 /* genCodePointerGet - get value from code space                  */
8933 /*-----------------------------------------------------------------*/
8934 static void genCodePointerGet (operand *left,
8935                                                            operand *result, iCode *ic)
8936 {
8937         int size, offset ;
8938         sym_link *retype = getSpec(operandType(result));
8939         
8940         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8941         
8942         aopOp(left,ic,FALSE);
8943         
8944         /* if the operand is already in dptr 
8945         then we do nothing else we move the value to dptr */
8946         if (AOP_TYPE(left) != AOP_STR) {
8947                 /* if this is remateriazable */
8948                 if (AOP_TYPE(left) == AOP_IMMD)
8949                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8950                 else { /* we need to get it byte by byte */
8951                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8952                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8953                         if (options.model == MODEL_FLAT24)
8954                         {
8955                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8956                         }
8957                 }
8958         }
8959         /* so dptr know contains the address */
8960         freeAsmop(left,NULL,ic,TRUE);
8961         aopOp(result,ic,FALSE);
8962         
8963         /* if bit then unpack */
8964         if (IS_BITFIELD(retype)) 
8965                 genUnpackBits(result,left,"dptr",CPOINTER,0);
8966         else {
8967                 size = AOP_SIZE(result);
8968                 offset = 0 ;
8969                 
8970                 while (size--) {
8971                         pic14_emitcode("clr","a");
8972                         pic14_emitcode("movc","a,@a+dptr");
8973                         aopPut(AOP(result),"a",offset++);
8974                         if (size)
8975                                 pic14_emitcode("inc","dptr");
8976                 }
8977         }
8978         
8979         freeAsmop(result,NULL,ic,TRUE);
8980 }
8981 #endif
8982 /*-----------------------------------------------------------------*/
8983 /* genGenPointerGet - gget value from generic pointer space        */
8984 /*-----------------------------------------------------------------*/
8985 static void genGenPointerGet (operand *left,
8986                                                           operand *result, iCode *ic)
8987 {
8988         FENTRY;
8989         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8990         aopOp(left,ic,FALSE);
8991         aopOp(result,ic,FALSE);
8992         
8993         
8994         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8995
8996         if (IS_BITFIELD(getSpec(operandType(result))))
8997         {
8998           genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
8999           return;
9000         }
9001
9002         {
9003           /* emit call to __gptrget */
9004           char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
9005           int size = AOP_SIZE(result);
9006           int idx = 0;
9007
9008           assert (size > 0 && size <= 4);
9009
9010           /* pass arguments */
9011           assert (AOP_SIZE(left) == 3);
9012           mov2w(AOP(left), 0);
9013           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9014           mov2w(AOP(left), 1);
9015           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9016           mov2w(AOP(left), 2);
9017           call_libraryfunc (func[size]);
9018           
9019           /* save result */
9020           movwf (AOP(result), --size);
9021           while (size--) {
9022             emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
9023             movwf (AOP(result), size);
9024           } // while
9025         }
9026         
9027         freeAsmop(left,NULL,ic,TRUE);
9028         freeAsmop(result,NULL,ic,TRUE);
9029         
9030 }
9031
9032 /*-----------------------------------------------------------------*/
9033 /* genConstPointerGet - get value from const generic pointer space */
9034 /*-----------------------------------------------------------------*/
9035 static void genConstPointerGet (operand *left,
9036                                                                 operand *result, iCode *ic)
9037 {
9038         //sym_link *retype = getSpec(operandType(result));
9039         #if 0
9040         symbol *albl, *blbl;//, *clbl;
9041         pCodeOp *pcop;
9042         #endif
9043         PIC_OPCODE poc;
9044         int i, size, lit;
9045         
9046         FENTRY;
9047         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9048         aopOp(left,ic,FALSE);
9049         aopOp(result,ic,FALSE);
9050         
9051         size = AOP_SIZE(result);
9052         
9053         DEBUGpic14_AopType(__LINE__,left,NULL,result);
9054         
9055         DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9056
9057         lit = op_isLitLike (left);
9058         poc = lit ? POC_MOVLW : POC_MOVFW;
9059
9060         if (IS_BITFIELD(getSpec(operandType(result))))
9061         {
9062                 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9063                 goto release;
9064         }
9065
9066         {
9067                 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9068                 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9069                 assert (size > 0 && size <= 4);
9070                 
9071                 mov2w_op(left, 0);
9072                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9073                 mov2w_op(left, 1);
9074                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9075                 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9076                 call_libraryfunc (func[size]);
9077
9078                 movwf(AOP(result),size-1);
9079                 for (i = 1; i < size; i++)
9080                 {
9081                         emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9082                         movwf(AOP(result),size - 1 - i);
9083                 } // for
9084         }
9085         
9086 release:
9087         freeAsmop(left,NULL,ic,TRUE);
9088         freeAsmop(result,NULL,ic,TRUE);
9089         
9090 }
9091 /*-----------------------------------------------------------------*/
9092 /* genPointerGet - generate code for pointer get                   */
9093 /*-----------------------------------------------------------------*/
9094 static void genPointerGet (iCode *ic)
9095 {
9096         operand *left, *result ;
9097         sym_link *type, *etype;
9098         int p_type = -1;
9099         
9100         FENTRY;
9101         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9102         
9103         left = IC_LEFT(ic);
9104         result = IC_RESULT(ic) ;
9105         
9106         /* depending on the type of pointer we need to
9107         move it to the correct pointer register */
9108         type = operandType(left);
9109         etype = getSpec(type);
9110         
9111         if (IS_PTR_CONST(type))
9112                 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9113         
9114         /* if left is of type of pointer then it is simple */
9115         if (IS_PTR(type) && !IS_FUNC(type->next)) 
9116                 p_type = DCL_TYPE(type);
9117         else {
9118                 /* we have to go by the storage class */
9119                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9120                 
9121                 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9122                 
9123                 if (SPEC_OCLS(etype)->codesp ) {
9124                         DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9125                         //p_type = CPOINTER ; 
9126                 }
9127                 else
9128                         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9129                                 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9130                         /*p_type = FPOINTER ;*/ 
9131                         else
9132                                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9133                                         DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9134                                 /*        p_type = PPOINTER; */
9135                                 else
9136                                         if (SPEC_OCLS(etype) == idata )
9137                                                 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9138                                         /*      p_type = IPOINTER; */
9139                                         else
9140                                                 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9141                                         /*      p_type = POINTER ; */
9142         }
9143         
9144         /* now that we have the pointer type we assign
9145         the pointer values */
9146         switch (p_type) {
9147                 
9148         case POINTER: 
9149         case FPOINTER:
9150         //case IPOINTER:
9151                 genNearPointerGet (left,result,ic);
9152                 break;
9153 /*
9154         case PPOINTER:
9155                 genPagedPointerGet(left,result,ic);
9156                 break;
9157                 
9158         case FPOINTER:
9159                 genFarPointerGet (left,result,ic);
9160                 break;
9161 */              
9162         case CPOINTER:
9163                 genConstPointerGet (left,result,ic);
9164                 break;
9165                 
9166         case GPOINTER:
9167                 genGenPointerGet (left,result,ic);
9168                 break;
9169         default:
9170                 assert ( !"unhandled pointer type" );
9171                 break;
9172         }
9173         
9174 }
9175
9176 /*-----------------------------------------------------------------*/
9177 /* genPackBits - generates code for packed bit storage             */
9178 /*-----------------------------------------------------------------*/
9179 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9180 {
9181   int blen;             /* bitfield length */
9182   int bstr;             /* bitfield starting bit within byte */
9183   int litval;           /* source literal value (if AOP_LIT) */
9184   unsigned char mask;   /* bitmask within current byte */
9185
9186   FENTRY;
9187   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9188
9189   blen = SPEC_BLEN (etype);
9190   bstr = SPEC_BSTR (etype);
9191
9192   /* If the bitfield length is less than a byte and does not cross byte boundaries */
9193   if ((blen <= 8) && ((bstr + blen) <= 8))
9194   {
9195     mask = ((unsigned char) (0xFF << (blen + bstr)) |
9196             (unsigned char) (0xFF >> (8 - bstr)));
9197
9198     if (AOP_TYPE (right) == AOP_LIT)
9199     {
9200       /* Case with a bitfield length <8 and literal source */
9201       int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9202       if (blen == 1) {
9203         pCodeOp *pcop;
9204         
9205         switch (p_type)
9206         {
9207         case -1:
9208           if (AOP(result)->type == AOP_PCODE)
9209             pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9210           else
9211             pcop = popGet(AOP(result),0);
9212           emitpcode(lit?POC_BSF:POC_BCF,pcop);
9213           break;
9214         
9215         case POINTER:
9216         case FPOINTER:
9217           setup_fsr (result);
9218           emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9219           break;
9220         
9221         case CPOINTER:
9222           assert( !"trying to assign to bitfield via pointer to __code space" );
9223           break;
9224         
9225         case GPOINTER:
9226           emitPtrByteGet(result, p_type, FALSE);
9227           if (lit) {
9228             emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9229           } else {
9230             emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9231           }
9232           emitPtrByteSet(result, p_type, TRUE);
9233           break;
9234         
9235         default:
9236           assert( !"unhandled pointer type" );
9237           break;
9238         } // switch (p_type)
9239       } else {
9240         /* blen > 1 */
9241         litval = lit << bstr;
9242         litval &= (~mask) & 0x00ff;
9243         
9244         switch (p_type)
9245         {
9246         case -1:
9247           mov2w (AOP(result), 0);
9248           if ((litval|mask) != 0x00ff)
9249             emitpcode(POC_ANDLW, popGetLit (mask));
9250           if (litval != 0x00)
9251             emitpcode(POC_IORLW, popGetLit (litval));
9252           movwf (AOP(result), 0);
9253           break;
9254         
9255         case POINTER:
9256         case FPOINTER:
9257         case GPOINTER:
9258           emitPtrByteGet(result, p_type, FALSE);
9259           if ((litval|mask) != 0x00ff)
9260             emitpcode(POC_ANDLW, popGetLit (mask));
9261           if (litval != 0x00)
9262             emitpcode(POC_IORLW, popGetLit (litval));
9263           emitPtrByteSet(result, p_type, TRUE);
9264           break;
9265         
9266         case CPOINTER:
9267           assert( !"trying to assign to bitfield via pointer to __code space" );
9268           break;
9269         
9270         default:
9271           assert( !"unhandled pointer type" );
9272           break;
9273         } // switch
9274       } // if (blen > 1)
9275     }
9276     else
9277     {
9278       /* right is no literal */
9279       if (blen==1) {
9280         switch (p_type)
9281         {
9282         case -1:
9283           /* Note more efficient code, of pre clearing bit then only setting it if required,
9284            * can only be done if it is known that the result is not a SFR */
9285           emitpcode(POC_RRFW,popGet(AOP(right),0));
9286           emitSKPC;
9287           emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9288           emitSKPNC;
9289           emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9290           break;
9291         
9292         case POINTER:
9293         case FPOINTER:
9294         case GPOINTER:
9295           emitPtrByteGet (result, p_type, FALSE);
9296           emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9297           emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9298           emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9299           emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9300           emitPtrByteSet (result, p_type, TRUE);
9301           break;
9302         
9303         case CPOINTER:
9304           assert( !"trying to assign to bitfield via pointer to __code space" );
9305           break;
9306         
9307         default:
9308           assert( !"unhandled pointer type" );
9309           break;
9310         } // switch
9311         return;
9312       } else {
9313         /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9314         pCodeOp *temp = popGetTempReg ();
9315
9316         mov2w (AOP(right), 0);
9317         if (blen < 8) {
9318           emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9319         }
9320         emitpcode(POC_MOVWF, temp);
9321         if (bstr) {
9322           AccLsh (temp, bstr);
9323         }
9324         
9325         switch (p_type)
9326         {
9327         case -1:
9328           mov2w (AOP(result), 0);
9329           emitpcode(POC_ANDLW, popGetLit (mask));
9330           emitpcode(POC_IORFW, temp);
9331           movwf (AOP(result), 0);
9332           break;
9333         
9334         case POINTER:
9335         case FPOINTER:
9336         case GPOINTER:
9337           emitPtrByteGet (result, p_type, FALSE);
9338           emitpcode(POC_ANDLW, popGetLit (mask));
9339           emitpcode(POC_IORFW, temp);
9340           emitPtrByteSet (result, p_type, TRUE);
9341           break;
9342         
9343         case CPOINTER:
9344           assert( !"trying to assign to bitfield via pointer to __code space" );
9345           break;
9346         
9347         default:
9348           assert( !"unhandled pointer type" );
9349           break;
9350         } // switch
9351
9352         popReleaseTempReg (temp);
9353       } // if (blen > 1)
9354     } // if (AOP(right)->type != AOP_LIT)
9355     return;
9356   } // if (blen <= 8 && ((blen + bstr) <= 8))
9357
9358   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9359 }
9360
9361 /*-----------------------------------------------------------------*/
9362 /* genDataPointerSet - remat pointer to data space                 */
9363 /*-----------------------------------------------------------------*/
9364 static void genDataPointerSet(operand *right,
9365         operand *result,
9366         iCode *ic)
9367 {
9368         int size, offset = 0 ;
9369         int ressize;
9370         
9371         FENTRY;
9372         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9373         aopOp(right,ic,FALSE);
9374         aopOp(result,ic,FALSE);
9375         
9376         assert (IS_SYMOP(result));
9377         assert (IS_PTR(OP_SYM_TYPE(result)));
9378         
9379         size = AOP_SIZE(right);
9380         ressize = getSize(OP_SYM_ETYPE(result));
9381         if (size > ressize) size = ressize;
9382         //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9383         
9384         //assert( !"what's going on here?" );
9385
9386         /*
9387         if ( AOP_TYPE(result) == AOP_PCODE) {
9388         fprintf(stderr,"genDataPointerSet   %s, %d\n",
9389         AOP(result)->aopu.pcop->name,
9390         PCOI(AOP(result)->aopu.pcop)->offset);
9391         }
9392         */
9393         
9394         // tsd, was l+1 - the underline `_' prefix was being stripped
9395         while (size--) {
9396                 emitpComment ("%s:%u: size=%d/%d, offset=%i", __FILE__,__LINE__, size, ressize, offset);
9397                 
9398                 if (AOP_TYPE(right) == AOP_LIT) {
9399                         unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
9400                         //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9401                         if(lit&0xff) {
9402                                 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9403                                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9404                         } else {
9405                                 emitpcode(POC_CLRF, popGet(AOP(result), offset));
9406                         }
9407                 } else {
9408                         //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9409                         emitpcode(POC_MOVFW, popGet(AOP(right), offset));
9410                         emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9411                 }
9412                 
9413                 offset++;
9414         }
9415         
9416         freeAsmop(right,NULL,ic,TRUE);
9417         freeAsmop(result,NULL,ic,TRUE);
9418 }
9419
9420 /*-----------------------------------------------------------------*/
9421 /* genNearPointerSet - pic14_emitcode for near pointer put         */
9422 /*-----------------------------------------------------------------*/
9423 static void genNearPointerSet (operand *right,
9424                                                            operand *result, 
9425                                                            iCode *ic)
9426 {
9427         asmop *aop = NULL;
9428         sym_link *ptype = operandType(result);
9429         sym_link *retype = getSpec(operandType(right));
9430         sym_link *letype = getSpec(ptype);
9431         int direct = 0;
9432         
9433         
9434         FENTRY;
9435         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9436         aopOp(result,ic,FALSE);
9437         
9438 #if 1
9439         /* if the result is rematerializable &
9440         in data space & not a bit variable */
9441         //if (AOP_TYPE(result) == AOP_IMMD &&
9442         if (AOP_TYPE(result) == AOP_PCODE &&
9443                 PIC_IS_DATA_PTR(ptype) &&
9444                 !IS_BITVAR (retype) &&
9445                 !IS_BITVAR (letype)) {
9446                 genDataPointerSet (right,result,ic);
9447                 freeAsmop(result,NULL,ic,TRUE);
9448                 return;
9449         }
9450 #endif
9451
9452         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9453         aopOp(right,ic,FALSE);
9454         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9455         
9456         /* Check if can access directly instead of via a pointer */
9457         if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9458                 direct = 1;
9459         }
9460         
9461         if (IS_BITFIELD (letype))
9462         {
9463           genPackBits (letype, result, right, direct?-1:POINTER);
9464           return;
9465         }
9466         
9467         /* If the pointer value is not in a the FSR then need to put it in */
9468         /* Must set/reset IRP bit for use with FSR. */
9469         /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9470         if (!direct)
9471                 setup_fsr (result);
9472
9473         {
9474                 /* we have can just get the values */
9475                 int size = AOP_SIZE(right);
9476                 int offset = 0 ;    
9477                 
9478                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9479                 while (size--) {
9480                         char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9481                         if (*l == '@' ) {
9482                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9483                         } else {
9484                                 if (AOP_TYPE(right) == AOP_LIT) {
9485                                         emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9486                                 } else {
9487                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9488                                 }
9489                                 if (direct)
9490                                         emitpcode(POC_MOVWF,popGet(AOP(result),0));
9491                                 else
9492                                         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9493                         }
9494                         if (size && !direct)
9495                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9496                         offset++;
9497                 }
9498         }
9499         
9500         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9501         /* now some housekeeping stuff */
9502         if (aop) {
9503                 /* we had to allocate for this iCode */
9504                 freeAsmop(NULL,aop,ic,TRUE);
9505         } else { 
9506                 /* we did not allocate which means left
9507                 already in a pointer register, then
9508                 if size > 0 && this could be used again
9509                 we have to point it back to where it 
9510                 belongs */
9511                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9512                 if (AOP_SIZE(right) > 1 &&
9513                         !OP_SYMBOL(result)->remat &&
9514                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9515                         ic->depth )) {
9516                         int size = AOP_SIZE(right) - 1;
9517                         while (size--)
9518                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9519                 }
9520         }
9521         
9522         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9523         /* done */
9524
9525         freeAsmop(right,NULL,ic,TRUE);
9526         freeAsmop(result,NULL,ic,TRUE);
9527 }
9528
9529 #if 0
9530 /*-----------------------------------------------------------------*/
9531 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
9532 /*-----------------------------------------------------------------*/
9533 static void genPagedPointerSet (operand *right,
9534                                                                 operand *result, 
9535                                                                 iCode *ic)
9536 {
9537         asmop *aop = NULL;
9538         regs *preg = NULL ;
9539         char *rname , *l;
9540         sym_link *retype;
9541         
9542         FENTRY;
9543         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9544         
9545         retype= getSpec(operandType(right));
9546         
9547         aopOp(result,ic,FALSE);
9548         
9549         /* if the value is already in a pointer register
9550         then don't need anything more */
9551         if (!AOP_INPREG(AOP(result))) {
9552                 /* otherwise get a free pointer register */
9553                 aop = newAsmop(0);
9554                 preg = getFreePtr(ic,&aop,FALSE);
9555                 pic14_emitcode("mov","%s,%s",
9556                         preg->name,
9557                         aopGet(AOP(result),0,FALSE,TRUE));
9558                 rname = preg->name ;
9559         } else
9560                 rname = aopGet(AOP(result),0,FALSE,FALSE);
9561         
9562         freeAsmop(result,NULL,ic,TRUE);
9563         aopOp (right,ic,FALSE);
9564         
9565         /* if bitfield then unpack the bits */
9566         if (IS_BITFIELD(retype)) 
9567                 genPackBits (retype,result,right,rname,PPOINTER);
9568         else {
9569                 /* we have can just get the values */
9570                 int size = AOP_SIZE(right);
9571                 int offset = 0 ;  
9572                 
9573                 while (size--) {
9574                         l = aopGet(AOP(right),offset,FALSE,TRUE);
9575                         
9576                         MOVA(l);
9577                         pic14_emitcode("movx","@%s,a",rname);
9578                         
9579                         if (size)
9580                                 pic14_emitcode("inc","%s",rname);
9581                         
9582                         offset++;
9583                 }
9584         }
9585         
9586         /* now some housekeeping stuff */
9587         if (aop) {
9588                 /* we had to allocate for this iCode */
9589                 freeAsmop(NULL,aop,ic,TRUE);
9590         } else { 
9591         /* we did not allocate which means left
9592         already in a pointer register, then
9593         if size > 0 && this could be used again
9594         we have to point it back to where it 
9595                 belongs */
9596                 if (AOP_SIZE(right) > 1 &&
9597                         !OP_SYMBOL(result)->remat &&
9598                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9599                         ic->depth )) {
9600                         int size = AOP_SIZE(right) - 1;
9601                         while (size--)
9602                                 pic14_emitcode("dec","%s",rname);
9603                 }
9604         }
9605         
9606         /* done */
9607         freeAsmop(right,NULL,ic,TRUE);
9608         
9609         
9610 }
9611
9612 /*-----------------------------------------------------------------*/
9613 /* genFarPointerSet - set value from far space                     */
9614 /*-----------------------------------------------------------------*/
9615 static void genFarPointerSet (operand *right,
9616                                                           operand *result, iCode *ic)
9617 {
9618         int size, offset ;
9619         sym_link *retype = getSpec(operandType(right));
9620         
9621         FENTRY;
9622         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9623         aopOp(result,ic,FALSE);
9624         
9625         /* if the operand is already in dptr 
9626         then we do nothing else we move the value to dptr */
9627         if (AOP_TYPE(result) != AOP_STR) {
9628                 /* if this is remateriazable */
9629                 if (AOP_TYPE(result) == AOP_IMMD)
9630                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9631                 else { /* we need to get it byte by byte */
9632                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9633                         pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9634                         if (options.model == MODEL_FLAT24)
9635                         {
9636                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9637                         }
9638                 }
9639         }
9640         /* so dptr know contains the address */
9641         freeAsmop(result,NULL,ic,TRUE);
9642         aopOp(right,ic,FALSE);
9643         
9644         /* if bit then unpack */
9645         if (IS_BITFIELD(retype)) 
9646                 genPackBits(retype,result,right,"dptr",FPOINTER);
9647         else {
9648                 size = AOP_SIZE(right);
9649                 offset = 0 ;
9650                 
9651                 while (size--) {
9652                         char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9653                         MOVA(l);
9654                         pic14_emitcode("movx","@dptr,a");
9655                         if (size)
9656                                 pic14_emitcode("inc","dptr");
9657                 }
9658         }
9659         
9660         freeAsmop(right,NULL,ic,TRUE);
9661 }
9662 #endif
9663
9664 /*-----------------------------------------------------------------*/
9665 /* genGenPointerSet - set value from generic pointer space         */
9666 /*-----------------------------------------------------------------*/
9667 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9668 {
9669         sym_link *retype = getSpec(operandType(result));
9670         
9671         FENTRY;
9672         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9673         aopOp(right,ic,FALSE);
9674         aopOp(result,ic,FALSE);
9675
9676         
9677         DEBUGpic14_AopType(__LINE__,right,NULL,result);
9678
9679         if (IS_BITFIELD(retype))
9680         {
9681           genPackBits (retype, result, right, GPOINTER);
9682           return;
9683         }
9684
9685         {
9686           /* emit call to __gptrput */
9687           char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9688           int size = AOP_SIZE(right);
9689           int idx = 0;
9690
9691           assert (size == getSize(OP_SYM_ETYPE(result)));
9692           assert (size > 0 && size <= 4);
9693
9694           /* pass arguments */
9695           /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9696           {
9697             int off = size;
9698             idx = 2;
9699             while (off--)
9700             {
9701               mov2w_op (right, off);
9702               emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9703             }
9704             idx = 0;
9705           }
9706           /* - address */
9707           assert (AOP_SIZE(result) == 3);
9708           mov2w(AOP(result), 0);
9709           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9710           mov2w(AOP(result), 1);
9711           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9712           mov2w(AOP(result), 2);
9713           call_libraryfunc (func[size]);
9714         }
9715         
9716         freeAsmop(right,NULL,ic,TRUE);
9717         freeAsmop(result,NULL,ic,TRUE);
9718 }
9719
9720 /*-----------------------------------------------------------------*/
9721 /* genPointerSet - stores the value into a pointer location        */
9722 /*-----------------------------------------------------------------*/
9723 static void genPointerSet (iCode *ic)
9724 {    
9725         operand *right, *result ;
9726         sym_link *type, *etype;
9727         int p_type;
9728         
9729         FENTRY;
9730         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9731         
9732         right = IC_RIGHT(ic);
9733         result = IC_RESULT(ic) ;
9734         
9735         /* depending on the type of pointer we need to
9736         move it to the correct pointer register */
9737         type = operandType(result);
9738         etype = getSpec(type);
9739         /* if left is of type of pointer then it is simple */
9740         if (IS_PTR(type) && !IS_FUNC(type->next)) {
9741                 p_type = DCL_TYPE(type);
9742         }
9743         else {
9744                 /* we have to go by the storage class */
9745                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9746                 
9747                 /*  if (SPEC_OCLS(etype)->codesp ) { */
9748                 /*      p_type = CPOINTER ;  */
9749                 /*  } */
9750                 /*  else */
9751                 /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9752                 /*    p_type = FPOINTER ; */
9753                 /*      else */
9754                 /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9755                 /*        p_type = PPOINTER ; */
9756                 /*    else */
9757                 /*        if (SPEC_OCLS(etype) == idata ) */
9758                 /*      p_type = IPOINTER ; */
9759                 /*        else */
9760                 /*      p_type = POINTER ; */
9761         }
9762         
9763         /* now that we have the pointer type we assign
9764         the pointer values */
9765         switch (p_type) {
9766                 
9767         case POINTER:
9768         case FPOINTER:
9769         //case IPOINTER:
9770                 genNearPointerSet (right,result,ic);
9771                 break;
9772 /*
9773         case PPOINTER:
9774                 genPagedPointerSet (right,result,ic);
9775                 break;
9776                 
9777         case FPOINTER:
9778                 genFarPointerSet (right,result,ic);
9779                 break;
9780 */
9781         case GPOINTER:
9782                 genGenPointerSet (right,result,ic);
9783                 break;
9784                 
9785         default:
9786                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9787                         "genPointerSet: illegal pointer type");
9788         }
9789 }
9790
9791 /*-----------------------------------------------------------------*/
9792 /* genIfx - generate code for Ifx statement                        */
9793 /*-----------------------------------------------------------------*/
9794 static void genIfx (iCode *ic, iCode *popIc)
9795 {
9796         operand *cond = IC_COND(ic);
9797         int isbit =0;
9798         
9799         FENTRY;
9800         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9801         
9802         aopOp(cond,ic,FALSE);
9803         
9804         /* get the value into acc */
9805         if (AOP_TYPE(cond) != AOP_CRY)
9806                 pic14_toBoolean(cond);
9807         else
9808                 isbit = 1;
9809         
9810         /* if there was something to be popped then do it */
9811         if (popIc)
9812                 genIpop(popIc);
9813         
9814         if (isbit)
9815         {
9816                 /* This assumes that CARRY is set iff cond is true */
9817                 if (IC_TRUE(ic))
9818                 {
9819                         assert (!IC_FALSE(ic));
9820                         emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9821                         //emitSKPNC;
9822                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9823                 } else {
9824                         assert (IC_FALSE(ic));
9825                         emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9826                         //emitSKPC;
9827                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9828                 }
9829                 if (0)
9830                 {
9831                         static int hasWarned = 0;
9832                         if (!hasWarned)
9833                         {
9834                                 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9835                                 hasWarned = 1;
9836                         }
9837                 }
9838         }
9839         else
9840         {
9841                 /* now Z is set iff !cond */
9842                 if (IC_TRUE(ic))
9843                 {
9844                         assert (!IC_FALSE(ic));
9845                         emitSKPZ;
9846                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9847                 } else {
9848                         emitSKPNZ;
9849                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9850                 }
9851         }
9852         
9853         ic->generated = 1;
9854         
9855         /* the result is now in the accumulator */
9856         freeAsmop(cond,NULL,ic,TRUE);
9857 }
9858
9859 /*-----------------------------------------------------------------*/
9860 /* genAddrOf - generates code for address of                       */
9861 /*-----------------------------------------------------------------*/
9862 static void genAddrOf (iCode *ic)
9863 {
9864         operand *right, *result, *left;
9865         int size, offset ;
9866         
9867         FENTRY;
9868         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9869         
9870         
9871         //aopOp(IC_RESULT(ic),ic,FALSE);
9872         
9873         aopOp((left=IC_LEFT(ic)),ic,FALSE);
9874         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9875         aopOp((result=IC_RESULT(ic)),ic,TRUE);
9876         
9877         DEBUGpic14_AopType(__LINE__,left,right,result);
9878         assert (IS_SYMOP (left));
9879         
9880         /* sanity check: generic pointers to code space are not yet supported,
9881          * pionters to codespace must not be assigned addresses of __data values. */
9882  #if 0
9883         fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9884         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)));
9885         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)));
9886         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)));
9887         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)));
9888 #endif
9889
9890         if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9891           fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9892                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9893                 OP_SYMBOL(left)->name);
9894         } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9895           fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9896                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9897                 OP_SYMBOL(left)->name);
9898         }
9899         
9900         size = AOP_SIZE(IC_RESULT(ic));
9901         if (IS_GENPTR(OP_SYM_TYPE(result))) {
9902                 /* strip tag */
9903                 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9904         }
9905         offset = 0;
9906         
9907         while (size--) {
9908                 /* fixing bug #863624, reported from (errolv) */
9909                 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9910                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9911                 
9912 #if 0
9913                 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9914                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9915 #endif
9916                 offset++;
9917         }
9918
9919         if (IS_GENPTR(OP_SYM_TYPE(result)))
9920         {
9921                 /* provide correct tag */
9922                 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9923                 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9924                 movwf (AOP(result), 2);
9925         }
9926         
9927         freeAsmop(left,NULL,ic,FALSE);
9928         freeAsmop(result,NULL,ic,TRUE);
9929         
9930 }
9931
9932 #if 0
9933 /*-----------------------------------------------------------------*/
9934 /* genFarFarAssign - assignment when both are in far space         */
9935 /*-----------------------------------------------------------------*/
9936 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9937 {
9938         int size = AOP_SIZE(right);
9939         int offset = 0;
9940         char *l ;
9941         /* first push the right side on to the stack */
9942         while (size--) {
9943                 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9944                 MOVA(l);
9945                 pic14_emitcode ("push","acc");
9946         }
9947         
9948         freeAsmop(right,NULL,ic,FALSE);
9949         /* now assign DPTR to result */
9950         aopOp(result,ic,FALSE);
9951         size = AOP_SIZE(result);
9952         while (size--) {
9953                 pic14_emitcode ("pop","acc");
9954                 aopPut(AOP(result),"a",--offset);
9955         }
9956         freeAsmop(result,NULL,ic,FALSE);
9957         
9958 }
9959 #endif
9960
9961 /*-----------------------------------------------------------------*/
9962 /* genAssign - generate code for assignment                        */
9963 /*-----------------------------------------------------------------*/
9964 static void genAssign (iCode *ic)
9965 {
9966         operand *result, *right;
9967         int size, offset,know_W;
9968         unsigned long lit = 0L;
9969         
9970         result = IC_RESULT(ic);
9971         right  = IC_RIGHT(ic) ;
9972         
9973         FENTRY;
9974         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9975         
9976         /* if they are the same */
9977         if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9978                 return ;
9979         
9980         aopOp(right,ic,FALSE);
9981         aopOp(result,ic,TRUE);
9982         
9983         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9984         
9985         /* if they are the same registers */
9986         if (pic14_sameRegs(AOP(right),AOP(result)))
9987                 goto release;
9988
9989         /* special case: assign from __code */
9990         if (!IS_ITEMP(right)                            /* --> iTemps never reside in __code */
9991                 && IS_SYMOP (right)                     /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
9992                 && !IS_FUNC(OP_SYM_TYPE(right))         /* --> we would want its address instead of the first instruction */
9993                 && !IS_CODEPTR(OP_SYM_TYPE(right))      /* --> get symbols address instread */
9994                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
9995         {
9996           emitpComment ("genAssign from CODESPACE");
9997           genConstPointerGet (right, result, ic);
9998           goto release;
9999         }
10000         
10001         /* just for symmetry reasons... */
10002         if (!IS_ITEMP(result)
10003                 && IS_SYMOP (result)
10004                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
10005         {
10006           assert ( !"cannot write to CODESPACE" );
10007         }
10008
10009         /* if the result is a bit */
10010         if (AOP_TYPE(result) == AOP_CRY) {
10011                 
10012         /* if the right size is a literal then
10013                 we know what the value is */
10014                 if (AOP_TYPE(right) == AOP_LIT) {
10015                         
10016                         emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10017                                 popGet(AOP(result),0));
10018                         
10019                         if (((int) operandLitValue(right))) 
10020                                 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10021                                 AOP(result)->aopu.aop_dir,
10022                                 AOP(result)->aopu.aop_dir);
10023                         else
10024                                 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10025                                 AOP(result)->aopu.aop_dir,
10026                                 AOP(result)->aopu.aop_dir);
10027                         goto release;
10028                 }
10029                 
10030                 /* the right is also a bit variable */
10031                 if (AOP_TYPE(right) == AOP_CRY) {
10032                         emitpcode(POC_BCF,    popGet(AOP(result),0));
10033                         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10034                         emitpcode(POC_BSF,    popGet(AOP(result),0));
10035                         
10036                         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10037                                 AOP(result)->aopu.aop_dir,
10038                                 AOP(result)->aopu.aop_dir);
10039                         pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10040                                 AOP(right)->aopu.aop_dir,
10041                                 AOP(right)->aopu.aop_dir);
10042                         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10043                                 AOP(result)->aopu.aop_dir,
10044                                 AOP(result)->aopu.aop_dir);
10045                         goto release ;
10046                 }
10047                 
10048                 /* we need to or */
10049                 emitpcode(POC_BCF,    popGet(AOP(result),0));
10050                 pic14_toBoolean(right);
10051                 emitSKPZ;
10052                 emitpcode(POC_BSF,    popGet(AOP(result),0));
10053                 //aopPut(AOP(result),"a",0);
10054                 goto release ;
10055         }
10056         
10057         /* bit variables done */
10058         /* general case */
10059         size = AOP_SIZE(result);
10060         offset = 0 ;
10061         if(AOP_TYPE(right) == AOP_LIT)
10062                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10063         
10064         if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10065                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10066                 if(aopIdx(AOP(result),0) == 4) {
10067                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10068                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10069                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10070                         goto release;
10071                 } else
10072                         DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10073         }
10074         
10075         know_W=-1;
10076         while (size--) {
10077                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10078                 if(AOP_TYPE(right) == AOP_LIT) {
10079                         if(lit&0xff) {
10080                                 if(know_W != (int)(lit&0xff))
10081                                         emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10082                                 know_W = lit&0xff;
10083                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10084                         } else
10085                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10086                         
10087                         lit >>= 8;
10088                         
10089                 } else if (AOP_TYPE(right) == AOP_CRY) {
10090                         emitpcode(POC_CLRF, popGet(AOP(result),offset));
10091                         if(offset == 0) {
10092                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10093                                 emitpcode(POC_INCF, popGet(AOP(result),0));
10094                         }
10095                 } else {
10096                         mov2w_op (right, offset);
10097                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10098                 }
10099                 
10100                 offset++;
10101         }
10102         
10103         
10104 release:
10105         freeAsmop (right,NULL,ic,FALSE);
10106         freeAsmop (result,NULL,ic,TRUE);
10107 }   
10108
10109 /*-----------------------------------------------------------------*/
10110 /* genJumpTab - genrates code for jump table                       */
10111 /*-----------------------------------------------------------------*/
10112 static void genJumpTab (iCode *ic)
10113 {
10114         symbol *jtab;
10115         char *l;
10116         
10117         FENTRY;
10118         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10119         
10120         aopOp(IC_JTCOND(ic),ic,FALSE);
10121         /* get the condition into accumulator */
10122         l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10123         MOVA(l);
10124         /* multiply by three */
10125         pic14_emitcode("add","a,acc");
10126         pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10127         
10128         jtab = newiTempLabel(NULL);
10129         pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10130         pic14_emitcode("jmp","@a+dptr");
10131         pic14_emitcode("","%05d_DS_:",jtab->key+100);
10132         
10133         emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10134         emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10135         emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10136         emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10137         emitSKPNC;
10138         emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10139         emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10140         emitpLabel(jtab->key);
10141         
10142         freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10143         
10144         /* now generate the jump labels */
10145         for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10146         jtab = setNextItem(IC_JTLABELS(ic))) {
10147                 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10148                 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10149                 
10150         }
10151         
10152 }
10153
10154 /*-----------------------------------------------------------------*/
10155 /* genMixedOperation - gen code for operators between mixed types  */
10156 /*-----------------------------------------------------------------*/
10157 /*
10158 TSD - Written for the PIC port - but this unfortunately is buggy.
10159 This routine is good in that it is able to efficiently promote 
10160 types to different (larger) sizes. Unfortunately, the temporary
10161 variables that are optimized out by this routine are sometimes
10162 used in other places. So until I know how to really parse the 
10163 iCode tree, I'm going to not be using this routine :(.
10164 */
10165 static int genMixedOperation (iCode *ic)
10166 {
10167         FENTRY;
10168 #if 0
10169         operand *result = IC_RESULT(ic);
10170         sym_link *ctype = operandType(IC_LEFT(ic));
10171         operand *right = IC_RIGHT(ic);
10172         int ret = 0;
10173         int big,small;
10174         int offset;
10175         
10176         iCode *nextic;
10177         operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10178         
10179         pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10180         
10181         nextic = ic->next;
10182         if(!nextic)
10183                 return 0;
10184         
10185         nextright = IC_RIGHT(nextic);
10186         nextleft  = IC_LEFT(nextic);
10187         nextresult = IC_RESULT(nextic);
10188         
10189         aopOp(right,ic,FALSE);
10190         aopOp(result,ic,FALSE);
10191         aopOp(nextright,  nextic, FALSE);
10192         aopOp(nextleft,   nextic, FALSE);
10193         aopOp(nextresult, nextic, FALSE);
10194         
10195         if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10196                 
10197                 operand *t = right;
10198                 right = nextright;
10199                 nextright = t; 
10200                 
10201                 pic14_emitcode(";remove right +","");
10202                 
10203         } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10204         /*
10205         operand *t = right;
10206         right = nextleft;
10207         nextleft = t; 
10208                 */
10209                 pic14_emitcode(";remove left +","");
10210         } else
10211                 return 0;
10212         
10213         big = AOP_SIZE(nextleft);
10214         small = AOP_SIZE(nextright);
10215         
10216         switch(nextic->op) {
10217                 
10218         case '+':
10219                 pic14_emitcode(";optimize a +","");
10220                 /* if unsigned or not an integral type */
10221                 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10222                         pic14_emitcode(";add a bit to something","");
10223                 } else {
10224                         
10225                         pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10226                         
10227                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10228                                 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10229                                 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10230                         } else
10231                                 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10232                         
10233                         offset = 0;
10234                         while(--big) {
10235                                 
10236                                 offset++;
10237                                 
10238                                 if(--small) {
10239                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10240                                                 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10241                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10242                                         }
10243                                         
10244                                         pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10245                                         emitSKPNC;
10246                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10247                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10248                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10249                                         pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10250                                         pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10251                                         
10252                                 } else {
10253                                         pic14_emitcode("rlf","known_zero,w");
10254                                         
10255                                         /*
10256                                         if right is signed
10257                                         btfsc  right,7
10258                                         addlw ff
10259                                         */
10260                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10261                                                 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10262                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10263                                         } else {
10264                                                 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10265                                         }
10266                                 }
10267                         }
10268                         ret = 1;
10269                 }
10270         }
10271         ret = 1;
10272         
10273 release:
10274         freeAsmop(right,NULL,ic,TRUE);
10275         freeAsmop(result,NULL,ic,TRUE);
10276         freeAsmop(nextright,NULL,ic,TRUE);
10277         freeAsmop(nextleft,NULL,ic,TRUE);
10278         if(ret)
10279                 nextic->generated = 1;
10280         
10281         return ret;
10282 #else
10283         return 0;
10284 #endif
10285 }
10286 /*-----------------------------------------------------------------*/
10287 /* genCast - gen code for casting                                  */
10288 /*-----------------------------------------------------------------*/
10289 static void genCast (iCode *ic)
10290 {
10291         operand *result = IC_RESULT(ic);
10292         sym_link *restype = operandType(result);
10293         sym_link *rtype = operandType(IC_RIGHT(ic));
10294         operand *right = IC_RIGHT(ic);
10295         int size, offset ;
10296         
10297         FENTRY;
10298         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10299         /* if they are equivalent then do nothing */
10300         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10301                 return ;
10302         
10303         aopOp(right,ic,FALSE) ;
10304         aopOp(result,ic,FALSE);
10305         
10306         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10307         
10308         /* if the result is a bit */
10309         if (AOP_TYPE(result) == AOP_CRY) {
10310                 assert(!"assigning to bit variables is not supported");
10311         }
10312         
10313         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10314                 int offset = 1;
10315                 size = AOP_SIZE(result);
10316                 
10317                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10318                 
10319                 emitpcode(POC_CLRF,   popGet(AOP(result),0));
10320                 emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10321                 emitpcode(POC_INCF,   popGet(AOP(result),0));
10322                 
10323                 while (size--)
10324                         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
10325                 
10326                 goto release;
10327         }
10328         
10329         if (IS_PTR(restype))
10330         {
10331           operand *result = IC_RESULT(ic);
10332           //operand *left = IC_LEFT(ic);
10333           operand *right = IC_RIGHT(ic);
10334           int tag = 0xff;
10335           
10336           /* copy common part */
10337           int max, size = AOP_SIZE(result);
10338           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10339           DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10340
10341           /* warn if we discard generic opinter tag */
10342           if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10343           {
10344             //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10345           } // if
10346
10347           max = size;
10348           while (size--)
10349           {
10350             mov2w_op (right, size);
10351             movwf (AOP(result), size);
10352           } // while
10353
10354           /* upcast into generic pointer type? */
10355           if (IS_GENPTR(restype)
10356                 && (size < AOP_SIZE(result))
10357                 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10358           {
10359             //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10360             if (IS_PTR(rtype))
10361             {
10362               switch (DCL_TYPE(rtype))
10363               {
10364               case POINTER:     /* __data */
10365               case FPOINTER:    /* __data */
10366                 assert (AOP_SIZE(right) == 2);
10367                 tag = GPTRTAG_DATA;
10368                 break;
10369
10370               case CPOINTER:    /* __code */
10371                 assert (AOP_SIZE(right) == 2);
10372                 tag = GPTRTAG_CODE;
10373                 break;
10374                 
10375               case GPOINTER:    /* unknown destination, __data or __code */
10376                 /* assume __data space (address of immediate) */
10377                 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10378                 if (AOP(right)->code)
10379                   tag = GPTRTAG_CODE;
10380                 else
10381                   tag = GPTRTAG_DATA;
10382                 break;
10383                 
10384               default:
10385                 assert (!"unhandled pointer type");
10386               } // switch
10387             } else {
10388               /* convert other values into pointers to __data space */
10389               tag = GPTRTAG_DATA;
10390             }
10391
10392             assert (AOP_SIZE(result) == 3);
10393             if (tag == 0) {
10394               emitpcode(POC_CLRF, popGet(AOP(result), 2));
10395             } else {
10396               emitpcode(POC_MOVLW, popGetLit(tag));
10397               movwf(AOP(result), 2);
10398             }
10399           } else {
10400             addSign(result, max, 0);
10401           } // if
10402           goto release;
10403         }
10404         
10405         /* if they are the same size : or less */
10406         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10407                 
10408                 /* if they are in the same place */
10409                 if (pic14_sameRegs(AOP(right),AOP(result)))
10410                         goto release;
10411                 
10412                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10413                 if (IS_PTR_CONST(rtype))
10414                         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10415                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10416                         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10417                 
10418                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10419                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10420                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
10421                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10422                         emitpcode(POC_MOVWF, popGet(AOP(result),1));
10423                         if(AOP_SIZE(result) <2)
10424                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10425                         
10426                 } else {
10427                         
10428                         /* if they in different places then copy */
10429                         size = AOP_SIZE(result);
10430                         offset = 0 ;
10431                         while (size--) {
10432                                 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10433                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10434                                 
10435                                 //aopPut(AOP(result),
10436                                 // aopGet(AOP(right),offset,FALSE,FALSE),
10437                                 // offset);
10438                                 
10439                                 offset++;
10440                         }
10441                 }
10442                 goto release;
10443         }
10444         
10445         /* so we now know that the size of destination is greater
10446         than the size of the source.
10447         Now, if the next iCode is an operator then we might be
10448         able to optimize the operation without performing a cast.
10449         */
10450         if(0 && genMixedOperation(ic)) {
10451                 /* XXX: cannot optimize: must copy regs! */
10452                 goto release;
10453         }
10454         
10455         /* we move to result for the size of source */
10456         size = AOP_SIZE(right);
10457         offset = 0 ;
10458         while (size--) {
10459                 emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
10460                 emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
10461                 offset++;
10462         }
10463
10464         addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10465
10466 release:
10467         freeAsmop(right,NULL,ic,TRUE);
10468         freeAsmop(result,NULL,ic,TRUE);
10469         
10470 }
10471
10472 /*-----------------------------------------------------------------*/
10473 /* genDjnz - generate decrement & jump if not zero instrucion      */
10474 /*-----------------------------------------------------------------*/
10475 static int genDjnz (iCode *ic, iCode *ifx)
10476 {
10477         symbol *lbl, *lbl1;
10478         FENTRY;
10479         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10480         
10481         if (!ifx)
10482                 return 0;
10483         
10484                 /* if the if condition has a false label
10485         then we cannot save */
10486         if (IC_FALSE(ifx))
10487                 return 0;
10488         
10489                 /* if the minus is not of the form 
10490         a = a - 1 */
10491         if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10492                 !IS_OP_LITERAL(IC_RIGHT(ic)))
10493                 return 0;
10494         
10495         if (operandLitValue(IC_RIGHT(ic)) != 1)
10496                 return 0;
10497         
10498                 /* if the size of this greater than one then no
10499         saving */
10500         if (getSize(operandType(IC_RESULT(ic))) > 1)
10501                 return 0;
10502         
10503         /* otherwise we can save BIG */
10504         lbl = newiTempLabel(NULL);
10505         lbl1= newiTempLabel(NULL);
10506         
10507         aopOp(IC_RESULT(ic),ic,FALSE);
10508         
10509         if (IS_AOP_PREG(IC_RESULT(ic))) {
10510                 pic14_emitcode("dec","%s",
10511                         aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10512                 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10513                 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10514         } else {  
10515                 
10516                 
10517                 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10518                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10519                 
10520                 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10521                 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10522                 
10523         }
10524         /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10525         /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10526         /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10527         /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10528         
10529         
10530         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10531         ifx->generated = 1;
10532         return 1;
10533 }
10534
10535 /*-----------------------------------------------------------------*/
10536 /* genReceive - generate code for a receive iCode                  */
10537 /*-----------------------------------------------------------------*/
10538 static void genReceive (iCode *ic)
10539 {
10540         FENTRY;
10541         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10542         
10543         if (isOperandInFarSpace(IC_RESULT(ic)) &&
10544                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10545                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10546                 
10547                 int size = getSize(operandType(IC_RESULT(ic)));
10548                 int offset =  fReturnSizePic - size;
10549                 while (size--) {
10550                         pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10551                                 fReturn[fReturnSizePic - offset - 1] : "acc"));
10552                         offset++;
10553                 }
10554                 aopOp(IC_RESULT(ic),ic,FALSE);
10555                 size = AOP_SIZE(IC_RESULT(ic));
10556                 offset = 0;
10557                 while (size--) {
10558                         pic14_emitcode ("pop","acc");
10559                         aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10560                 }
10561                 
10562         } else {
10563                 _G.accInUse++;
10564                 aopOp(IC_RESULT(ic),ic,FALSE);
10565                 _G.accInUse--;
10566                 assignResultValue(IC_RESULT(ic));
10567         }
10568         
10569         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10570 }
10571
10572 /*-----------------------------------------------------------------*/
10573 /* genDummyRead - generate code for dummy read of volatiles        */
10574 /*-----------------------------------------------------------------*/
10575 static void
10576 genDummyRead (iCode * ic)
10577 {
10578         FENTRY;
10579         pic14_emitcode ("; genDummyRead","");
10580         pic14_emitcode ("; not implemented","");
10581         
10582         ic = ic;
10583 }
10584
10585 /*-----------------------------------------------------------------*/
10586 /* genpic14Code - generate code for pic14 based controllers        */
10587 /*-----------------------------------------------------------------*/
10588 /*
10589 * At this point, ralloc.c has gone through the iCode and attempted
10590 * to optimize in a way suitable for a PIC. Now we've got to generate
10591 * PIC instructions that correspond to the iCode.
10592 *
10593 * Once the instructions are generated, we'll pass through both the
10594 * peep hole optimizer and the pCode optimizer.
10595 *-----------------------------------------------------------------*/
10596
10597 void genpic14Code (iCode *lic)
10598 {
10599         iCode *ic;
10600         int cln = 0;
10601         const char *cline;
10602         
10603         FENTRY;
10604         lineHead = lineCurr = NULL;
10605         
10606         pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10607         addpBlock(pb);
10608         
10609         /* if debug information required */
10610         if (options.debug && currFunc) { 
10611                 if (currFunc) {
10612                         debugFile->writeFunction (currFunc, lic);
10613                 }
10614         }
10615         
10616         
10617         for (ic = lic ; ic ; ic = ic->next ) {
10618                 
10619                 //DEBUGpic14_emitcode(";ic","");
10620                 //fprintf (stderr, "in ic loop\n");
10621                 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10622                 //ic->lineno, printCLine(ic->filename, ic->lineno));
10623                 
10624                 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10625                   cln = ic->lineno;
10626                   //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10627                   cline = printCLine (ic->filename, ic->lineno);
10628                   if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10629                   addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10630                   //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10631                 }
10632                 
10633                 if (options.iCodeInAsm) {
10634                   emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10635                 }
10636                 /* if the result is marked as
10637                 spilt and rematerializable or code for
10638                 this has already been generated then
10639                 do nothing */
10640                 if (resultRemat(ic) || ic->generated ) 
10641                         continue ;
10642                 
10643                 /* depending on the operation */
10644                 switch (ic->op) {
10645                 case '!' :
10646                         genNot(ic);
10647                         break;
10648                         
10649                 case '~' :
10650                         genCpl(ic);
10651                         break;
10652                         
10653                 case UNARYMINUS:
10654                         genUminus (ic);
10655                         break;
10656                         
10657                 case IPUSH:
10658                         genIpush (ic);
10659                         break;
10660                         
10661                 case IPOP:
10662                         /* IPOP happens only when trying to restore a 
10663                         spilt live range, if there is an ifx statement
10664                         following this pop then the if statement might
10665                         be using some of the registers being popped which
10666                         would destory the contents of the register so
10667                         we need to check for this condition and handle it */
10668                         if (ic->next            && 
10669                                 ic->next->op == IFX &&
10670                                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10671                                 genIfx (ic->next,ic);
10672                         else
10673                                 genIpop (ic);
10674                         break; 
10675                         
10676                 case CALL:
10677                         genCall (ic);
10678                         break;
10679                         
10680                 case PCALL:
10681                         genPcall (ic);
10682                         break;
10683                         
10684                 case FUNCTION:
10685                         genFunction (ic);
10686                         break;
10687                         
10688                 case ENDFUNCTION:
10689                         genEndFunction (ic);
10690                         break;
10691                         
10692                 case RETURN:
10693                         genRet (ic);
10694                         break;
10695                         
10696                 case LABEL:
10697                         genLabel (ic);
10698                         break;
10699                         
10700                 case GOTO:
10701                         genGoto (ic);
10702                         break;
10703                         
10704                 case '+' :
10705                         genPlus (ic) ;
10706                         break;
10707                         
10708                 case '-' :
10709                         if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10710                                 genMinus (ic);
10711                         break;
10712                         
10713                 case '*' :
10714                         genMult (ic);
10715                         break;
10716                         
10717                 case '/' :
10718                         genDiv (ic) ;
10719                         break;
10720                         
10721                 case '%' :
10722                         genMod (ic);
10723                         break;
10724                         
10725                 case '>' :
10726                         genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));         
10727                         break;
10728                         
10729                 case '<' :
10730                         genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10731                         break;
10732                         
10733                 case LE_OP:
10734                 case GE_OP:
10735                 case NE_OP:
10736                         
10737                         /* note these two are xlated by algebraic equivalence
10738                         during parsing SDCC.y */
10739                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10740                                 "got '>=' or '<=' shouldn't have come here");
10741                         break;  
10742                         
10743                 case EQ_OP:
10744                         genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10745                         break;      
10746                         
10747                 case AND_OP:
10748                         genAndOp (ic);
10749                         break;
10750                         
10751                 case OR_OP:
10752                         genOrOp (ic);
10753                         break;
10754                         
10755                 case '^' :
10756                         genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10757                         break;
10758                         
10759                 case '|' :
10760                         genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10761                         break;
10762                         
10763                 case BITWISEAND:
10764                         genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10765                         break;
10766                         
10767                 case INLINEASM:
10768                         genInline (ic);
10769                         break;
10770                         
10771                 case RRC:
10772                         genRRC (ic);
10773                         break;
10774                         
10775                 case RLC:
10776                         genRLC (ic);
10777                         break;
10778                         
10779                 case GETHBIT:
10780                         genGetHbit (ic);
10781                         break;
10782                         
10783                 case LEFT_OP:
10784                         genLeftShift (ic);
10785                         break;
10786                         
10787                 case RIGHT_OP:
10788                         genRightShift (ic);
10789                         break;
10790                         
10791                 case GET_VALUE_AT_ADDRESS:
10792                         genPointerGet(ic);
10793                         break;
10794                         
10795                 case '=' :
10796                         if (POINTER_SET(ic))
10797                                 genPointerSet(ic);
10798                         else
10799                                 genAssign(ic);
10800                         break;
10801                         
10802                 case IFX:
10803                         genIfx (ic,NULL);
10804                         break;
10805                         
10806                 case ADDRESS_OF:
10807                         genAddrOf (ic);
10808                         break;
10809                         
10810                 case JUMPTABLE:
10811                         genJumpTab (ic);
10812                         break;
10813                         
10814                 case CAST:
10815                         genCast (ic);
10816                         break;
10817                         
10818                 case RECEIVE:
10819                         genReceive(ic);
10820                         break;
10821                         
10822                 case SEND:
10823                         addSet(&_G.sendSet,ic);
10824                         break;
10825                         
10826                 case DUMMY_READ_VOLATILE:
10827                         genDummyRead (ic);
10828                         break;
10829                         
10830                 default :
10831                         fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10832                         ic = ic;
10833                         break;
10834                 }
10835         }
10836
10837         
10838         /* now we are ready to call the
10839         peep hole optimizer */
10840         if (!options.nopeep) {
10841                 peepHole (&lineHead);
10842         }
10843         /* now do the actual printing */
10844         printLine (lineHead,codeOutFile);
10845         
10846 #ifdef PCODE_DEBUG
10847         DFPRINTF((stderr,"printing pBlock\n\n"));
10848         printpBlock(stdout,pb);
10849 #endif
10850         
10851         return;
10852 }
10853
10854 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10855  * (meaning: representing its own address) or not (referencing its contents).
10856  * This can only be decided based on the operand's type. */
10857 int
10858 aop_isLitLike (asmop *aop)
10859 {
10860   assert (aop);
10861   if (aop->type == AOP_LIT) return 1;
10862 if (aop->type == AOP_IMMD) return 1;
10863   if ((aop->type == AOP_PCODE) &&
10864                 ((aop->aopu.pcop->type == PO_LITERAL)))
10865   {
10866     /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10867      * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10868     return 1;
10869   }
10870   return 0;
10871 }
10872
10873 int
10874 op_isLitLike (operand *op)
10875 {
10876   assert (op);
10877   if (aop_isLitLike (AOP(op))) return 1;
10878   if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10879   if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;
10880   return 0;
10881 }