* src/pic/glue.h: added pic14aopLiteral prototype
[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         pic14_emitcode("","%s:",sym->rname);
2890         addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2891         
2892         ftype = operandType(IC_LEFT(ic));
2893         
2894         /* if critical function then turn interrupts off */
2895         if (IFFUNC_ISCRITICAL(ftype))
2896                 pic14_emitcode("clr","ea");
2897         
2898                 /* here we need to generate the equates for the
2899         register bank if required */
2900 #if 0
2901         if (FUNC_REGBANK(ftype) != rbank) {
2902                 int i ;
2903                 
2904                 rbank = FUNC_REGBANK(ftype);
2905                 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2906                         if (strcmp(regspic14[i].base,"0") == 0)
2907                                 pic14_emitcode("","%s = 0x%02x",
2908                                 regspic14[i].dname,
2909                                 8*rbank+regspic14[i].offset);
2910                         else
2911                                 pic14_emitcode ("","%s = %s + 0x%02x",
2912                                 regspic14[i].dname,
2913                                 regspic14[i].base,
2914                                 8*rbank+regspic14[i].offset);
2915                 }
2916         }
2917 #endif
2918         
2919         /* if this is an interrupt service routine */
2920         if (IFFUNC_ISISR(sym->type)) {
2921         /*  already done in pic14createInterruptVect() - delete me
2922         addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2923         emitpcodeNULLop(POC_NOP);
2924         emitpcodeNULLop(POC_NOP);
2925         emitpcodeNULLop(POC_NOP);
2926                 */
2927                 emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2928                 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2929                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2930                 emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2931                 emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2932                 emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2933                 emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2934                 
2935                 pBlockConvert2ISR(pb);
2936                 pic14_hasInterrupt = 1;
2937 #if 0  
2938                 if (!inExcludeList("acc"))              
2939                         pic14_emitcode ("push","acc");  
2940                 if (!inExcludeList("b"))
2941                         pic14_emitcode ("push","b");
2942                 if (!inExcludeList("dpl"))
2943                         pic14_emitcode ("push","dpl");
2944                 if (!inExcludeList("dph"))
2945                         pic14_emitcode ("push","dph");
2946                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2947                 {
2948                         pic14_emitcode ("push", "dpx");
2949                         /* Make sure we're using standard DPTR */
2950                         pic14_emitcode ("push", "dps");
2951                         pic14_emitcode ("mov", "dps, #0x00");
2952                         if (options.stack10bit)
2953                         { 
2954                                 /* This ISR could conceivably use DPTR2. Better save it. */
2955                                 pic14_emitcode ("push", "dpl1");
2956                                 pic14_emitcode ("push", "dph1");
2957                                 pic14_emitcode ("push", "dpx1");
2958                         }
2959                 }
2960                 /* if this isr has no bank i.e. is going to
2961                 run with bank 0 , then we need to save more
2962                 registers :-) */
2963                 if (!FUNC_REGBANK(sym->type)) {
2964                         
2965                 /* if this function does not call any other
2966                 function then we can be economical and
2967                         save only those registers that are used */
2968                         if (! IFFUNC_HASFCALL(sym->type)) {
2969                                 int i;
2970                                 
2971                                 /* if any registers used */
2972                                 if (sym->regsUsed) {
2973                                         /* save the registers used */
2974                                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2975                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2976                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2977                                                         pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);               
2978                                         }
2979                                 }
2980                                 
2981                         } else {
2982                         /* this function has    a function call cannot
2983                         determines register usage so we will have the
2984                                 entire bank */
2985                                 saverbank(0,ic,FALSE);
2986                         }       
2987                 }
2988 #endif
2989         } else {
2990         /* if callee-save to be used for this function
2991                 then save the registers being used in this function */
2992                 if (IFFUNC_CALLEESAVES(sym->type)) {
2993                         int i;
2994                         
2995                         /* if any registers used */
2996                         if (sym->regsUsed) {
2997                                 /* save the registers used */
2998                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2999                                         if (bitVectBitValue(sym->regsUsed,i) ||
3000                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
3001                                                 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
3002                                                 _G.nRegsSaved++;
3003                                         }
3004                                 }
3005                         }
3006                 }
3007         }
3008         
3009         /* set the register bank to the desired value */
3010         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
3011                 pic14_emitcode("push","psw");
3012                 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);       
3013         }
3014         
3015         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3016                 
3017                 if (options.useXstack) {
3018                         pic14_emitcode("mov","r0,%s",spname);
3019                         pic14_emitcode("mov","a,_bp");
3020                         pic14_emitcode("movx","@r0,a");
3021                         pic14_emitcode("inc","%s",spname);
3022                 }
3023                 else
3024                 {
3025                         /* set up the stack */
3026                         pic14_emitcode ("push","_bp");   /* save the callers stack      */
3027                 }
3028                 pic14_emitcode ("mov","_bp,%s",spname);
3029         }
3030         
3031         /* adjust the stack for the function */
3032         if (sym->stack) {
3033                 
3034                 int i = sym->stack;
3035                 if (i > 256 ) 
3036                         werror(W_STACK_OVERFLOW,sym->name);
3037                 
3038                 if (i > 3 && sym->recvSize < 4) {                
3039                         
3040                         pic14_emitcode ("mov","a,sp");
3041                         pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3042                         pic14_emitcode ("mov","sp,a");
3043                         
3044                 }
3045                 else
3046                         while(i--)
3047                                 pic14_emitcode("inc","sp");
3048         }
3049         
3050         if (sym->xstack) {
3051                 
3052                 pic14_emitcode ("mov","a,_spx");
3053                 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3054                 pic14_emitcode ("mov","_spx,a");
3055         }
3056         
3057 }
3058
3059 /*-----------------------------------------------------------------*/
3060 /* genEndFunction - generates epilogue for functions                       */
3061 /*-----------------------------------------------------------------*/
3062 static void genEndFunction (iCode *ic)
3063 {
3064         symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3065         
3066         FENTRY;
3067
3068         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3069         
3070         if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3071         {
3072                 pic14_emitcode ("mov","%s,_bp",spname);
3073         }
3074         
3075         /* if use external stack but some variables were
3076         added to the local stack then decrement the
3077         local stack */
3078         if (options.useXstack && sym->stack) {    
3079                 pic14_emitcode("mov","a,sp");
3080                 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3081                 pic14_emitcode("mov","sp,a");
3082         }
3083         
3084         
3085         if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3086                 if (options.useXstack) {
3087                         pic14_emitcode("mov","r0,%s",spname);
3088                         pic14_emitcode("movx","a,@r0");
3089                         pic14_emitcode("mov","_bp,a");
3090                         pic14_emitcode("dec","%s",spname);
3091                 }
3092                 else
3093                 {
3094                         pic14_emitcode ("pop","_bp");
3095                 }
3096         }
3097         
3098         /* restore the register bank    */        
3099         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3100                 pic14_emitcode ("pop","psw");
3101         
3102         if (IFFUNC_ISISR(sym->type)) {
3103                 
3104                 /* now we need to restore the registers */
3105                 /* if this isr has no bank i.e. is going to
3106                 run with bank 0 , then we need to save more
3107 registers :-) */
3108                 if (!FUNC_REGBANK(sym->type)) {
3109                         
3110                 /* if this function does not call any other
3111                 function then we can be economical and
3112                         save only those registers that are used */
3113                         if (! IFFUNC_HASFCALL(sym->type)) {
3114                                 int i;
3115                                 
3116                                 /* if any registers used */
3117                                 if (sym->regsUsed) {
3118                                         /* save the registers used */
3119                                         for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3120                                                 if (bitVectBitValue(sym->regsUsed,i) ||
3121                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3122                                                         pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3123                                         }
3124                                 }
3125                                 
3126                         } else {
3127                         /* this function has    a function call cannot
3128                         determines register usage so we will have the
3129                                 entire bank */
3130                                 unsaverbank(0,ic,FALSE);
3131                         }       
3132                 }
3133 #if 0
3134                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3135                 {
3136                         if (options.stack10bit)
3137                         {
3138                                 pic14_emitcode ("pop", "dpx1");
3139                                 pic14_emitcode ("pop", "dph1");
3140                                 pic14_emitcode ("pop", "dpl1");
3141                         } 
3142                         pic14_emitcode ("pop", "dps");
3143                         pic14_emitcode ("pop", "dpx");
3144                 }
3145                 if (!inExcludeList("dph"))
3146                         pic14_emitcode ("pop","dph");
3147                 if (!inExcludeList("dpl"))
3148                         pic14_emitcode ("pop","dpl");
3149                 if (!inExcludeList("b"))
3150                         pic14_emitcode ("pop","b");
3151                 if (!inExcludeList("acc"))
3152                         pic14_emitcode ("pop","acc");
3153                 
3154                 if (IFFUNC_ISCRITICAL(sym->type))
3155                         pic14_emitcode("setb","ea");
3156 #endif
3157                 
3158                 /* if debug then send end of function */
3159                 /*      if (options.debug && currFunc) { */
3160                 if (currFunc) {
3161                         debugFile->writeEndFunction (currFunc, ic, 1);
3162                 }
3163                 
3164                 pic14_emitcode ("reti","");
3165                 emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
3166                 emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
3167                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
3168                 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3169                 emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
3170                 emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
3171                 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3172                 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3173                 emitpcodeNULLop(POC_RETFIE);
3174         }
3175         else {
3176                 if (IFFUNC_ISCRITICAL(sym->type))
3177                         pic14_emitcode("setb","ea");
3178                 
3179                 if (IFFUNC_CALLEESAVES(sym->type)) {
3180                         int i;
3181                         
3182                         /* if any registers used */
3183                         if (sym->regsUsed) {
3184                                 /* save the registers used */
3185                                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3186                                         if (bitVectBitValue(sym->regsUsed,i) ||
3187                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3188                                                 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3189                                 }
3190                         }
3191                         
3192                 }
3193                 
3194                 /* if debug then send end of function */
3195                 if (currFunc) {
3196                         debugFile->writeEndFunction (currFunc, ic, 1);
3197                 }
3198                 
3199                 pic14_emitcode ("return","");
3200                 emitpcodeNULLop(POC_RETURN);
3201                 
3202                 /* Mark the end of a function */
3203                 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3204         }
3205         
3206 }
3207
3208 /*-----------------------------------------------------------------*/
3209 /* genRet - generate code for return statement                                     */
3210 /*-----------------------------------------------------------------*/
3211 static void genRet (iCode *ic)
3212 {
3213         int size,offset = 0;
3214         
3215         FENTRY;
3216
3217         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3218         /* if we have no return value then
3219         just generate the "ret" */
3220         if (!IC_LEFT(ic)) 
3221                 goto jumpret;           
3222         
3223                 /* we have something to return then
3224         move the return value into place */
3225         aopOp(IC_LEFT(ic),ic,FALSE);
3226         size = AOP_SIZE(IC_LEFT(ic));
3227
3228         for (offset = 0; offset < size; offset++)
3229         {
3230                 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3231         }
3232         
3233         freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3234         
3235 jumpret:
3236         /* generate a jump to the return label
3237         if the next is not the return statement */
3238         if (!(ic->next && ic->next->op == LABEL &&
3239                 IC_LABEL(ic->next) == returnLabel)) {
3240                 
3241                 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3242         }
3243         
3244 }
3245
3246 /*-----------------------------------------------------------------*/
3247 /* genLabel - generates a label                                                                    */
3248 /*-----------------------------------------------------------------*/
3249 static void genLabel (iCode *ic)
3250 {
3251         FENTRY;
3252
3253         /* special case never generate */
3254         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3255         if (IC_LABEL(ic) == entryLabel)
3256                 return ;
3257         
3258         emitpLabel(IC_LABEL(ic)->key);
3259         pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3260 }
3261
3262 /*-----------------------------------------------------------------*/
3263 /* genGoto - generates a goto                                                                      */
3264 /*-----------------------------------------------------------------*/
3265 //tsd
3266 static void genGoto (iCode *ic)
3267 {
3268         FENTRY;
3269
3270         emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3271         pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3272 }
3273
3274
3275 /*-----------------------------------------------------------------*/
3276 /* genMultbits :- multiplication of bits                                                   */
3277 /*-----------------------------------------------------------------*/
3278 static void genMultbits (operand *left, 
3279                                                  operand *right, 
3280                                                  operand *result)
3281 {
3282         FENTRY;
3283         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3284         
3285         if(!pic14_sameRegs(AOP(result),AOP(right)))
3286                 emitpcode(POC_BSF,      popGet(AOP(result),0));
3287         
3288         emitpcode(POC_BTFSC,popGet(AOP(right),0));
3289         emitpcode(POC_BTFSS,popGet(AOP(left),0));
3290         emitpcode(POC_BCF,  popGet(AOP(result),0));
3291         
3292 }
3293
3294
3295 /*-----------------------------------------------------------------*/
3296 /* genMultOneByte : 8 bit multiplication & division                        */
3297 /*-----------------------------------------------------------------*/
3298 static void genMultOneByte (operand *left,
3299                                                         operand *right,
3300                                                         operand *result)
3301 {
3302         char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3303         
3304         // symbol *lbl ;
3305         int size,offset,i;
3306         
3307         
3308         FENTRY;
3309         
3310         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3311         DEBUGpic14_AopType(__LINE__,left,right,result);
3312         DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3313         
3314         /* (if two literals, the value is computed before) */
3315         /* if one literal, literal on the right */
3316         if (AOP_TYPE(left) == AOP_LIT){
3317                 operand *t = right;
3318                 right = left;
3319                 left = t;
3320         }
3321
3322         assert (AOP_SIZE(left) == AOP_SIZE(right));
3323         
3324         size = min(AOP_SIZE(result),AOP_SIZE(left));
3325         offset = Gstack_base_addr - (2*size - 1);
3326
3327         /* pass right operand as argument */
3328         for (i=0; i < size; i++)
3329         {
3330                 mov2w (AOP(right), i);
3331                 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3332         } // for
3333         
3334         /* pass left operand as argument */
3335         for (i=0; i < size; i++)
3336         {
3337                 mov2w (AOP(left), i);
3338                 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3339         } // for
3340         assert (offset == Gstack_base_addr);
3341         
3342         /* call library routine */
3343         assert (size > 0 && size <= 4);
3344         call_libraryfunc (func[size]);
3345         
3346         /* assign result */
3347         movwf (AOP(result), size-1);
3348         for (i=0; i < size - 1; i++)
3349         {
3350                 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3351                 movwf (AOP(result), size - 2 - i);
3352         } // for
3353
3354         /* now (zero-/sign) extend the result to its size */
3355         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3356 }
3357
3358 /*-----------------------------------------------------------------*/
3359 /* genMult - generates code for multiplication                                     */
3360 /*-----------------------------------------------------------------*/
3361 static void genMult (iCode *ic)
3362 {
3363         operand *left = IC_LEFT(ic);
3364         operand *right = IC_RIGHT(ic);
3365         operand *result= IC_RESULT(ic); 
3366         
3367         FENTRY;
3368
3369         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3370         /* assign the amsops */
3371         aopOp (left,ic,FALSE);
3372         aopOp (right,ic,FALSE);
3373         aopOp (result,ic,TRUE);
3374         
3375         DEBUGpic14_AopType(__LINE__,left,right,result);
3376         
3377         /* special cases first */
3378         /* both are bits */
3379         if (AOP_TYPE(left) == AOP_CRY &&
3380                 AOP_TYPE(right)== AOP_CRY) {
3381                 genMultbits(left,right,result);
3382                 goto release ;
3383         }
3384         
3385         /* if both are of size == 1 */
3386         if (AOP_SIZE(left) == 1 &&
3387                 AOP_SIZE(right) == 1 ) {
3388                 genMultOneByte(left,right,result);
3389                 goto release ;
3390         }
3391         
3392         /* should have been converted to function call */
3393         assert(0) ;
3394         
3395 release :
3396         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3397         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3398         freeAsmop(result,NULL,ic,TRUE); 
3399 }
3400
3401 /*-----------------------------------------------------------------*/
3402 /* genDivbits :- division of bits                                                                  */
3403 /*-----------------------------------------------------------------*/
3404 static void genDivbits (operand *left, 
3405                                                 operand *right, 
3406                                                 operand *result)
3407 {
3408         
3409         char *l;
3410         
3411         FENTRY;
3412
3413         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3414         /* the result must be bit */      
3415         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3416         l = aopGet(AOP(left),0,FALSE,FALSE);
3417         
3418         MOVA(l);          
3419         
3420         pic14_emitcode("div","ab");
3421         pic14_emitcode("rrc","a");
3422         aopPut(AOP(result),"c",0);
3423 }
3424
3425 /*-----------------------------------------------------------------*/
3426 /* genDivOneByte : 8 bit division                                                                  */
3427 /*-----------------------------------------------------------------*/
3428 static void genDivOneByte (operand *left,
3429                                                    operand *right,
3430                                                    operand *result)
3431 {
3432         int size;
3433         
3434         FENTRY;
3435         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3436         
3437         assert (AOP_SIZE(result) == 1);
3438         assert (AOP_SIZE(right) == 1);
3439         assert (AOP_SIZE(left) == 1);
3440
3441         size = min(AOP_SIZE(result),AOP_SIZE(left));
3442
3443         if (AOP_TYPE(right) == AOP_LIT)
3444         {
3445                 /* XXX: might add specialized code */
3446         }
3447
3448         if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3449         {
3450                 /* unsigned division */
3451         #if 1
3452                 mov2w(AOP(right),0);
3453                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3454                 mov2w(AOP(left),0);
3455                 call_libraryfunc("__divuchar");
3456                 movwf(AOP(result),0);
3457         #else
3458                 pCodeOp *temp;
3459                 symbol *lbl;
3460
3461                 temp = popGetTempReg();
3462                 lbl = newiTempLabel(NULL);
3463                 
3464                 /* XXX: improve this naive approach:
3465                    [result] = [a] / [b]
3466                         ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3467
3468                    In PIC assembler:
3469                    movf  left,W
3470                    movwf temp           // temp <-- left
3471                    movf  right,W        // W <-- right
3472                    clrf  result
3473                    label1:
3474                    incf  result
3475                    subwf temp,F         // temp <-- temp - W
3476                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if temp < W
3477                    goto  label1
3478                    decf result          // we just subtract once too often
3479                  */
3480
3481                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3482                 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3483                 
3484                 mov2w(AOP(left),0);
3485                 emitpcode(POC_MOVWF, temp);
3486                 mov2w(AOP(right),0);
3487                 emitpcode(POC_CLRF, popGet(AOP(result),0));
3488
3489                 emitpLabel(lbl->key);
3490                 emitpcode(POC_INCF, popGet(AOP(result),0));
3491                 emitpcode(POC_SUBWF, temp);
3492                 emitSKPNC;
3493                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3494                 emitpcode(POC_DECF, popGet(AOP(result),0));
3495         #endif
3496         }
3497         else
3498         {
3499                 /* signed division */
3500                 mov2w(AOP(right),0);
3501                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3502                 mov2w(AOP(left),0);
3503                 call_libraryfunc("__divschar");
3504                 movwf(AOP(result),0);
3505         }
3506
3507         /* now performed the signed/unsigned division -- extend result */
3508         addSign(result, 1, !SPEC_USIGN(operandType(result)));
3509 }
3510
3511 /*-----------------------------------------------------------------*/
3512 /* genDiv - generates code for division                            */
3513 /*-----------------------------------------------------------------*/
3514 static void genDiv (iCode *ic)
3515 {
3516         operand *left = IC_LEFT(ic);
3517         operand *right = IC_RIGHT(ic);
3518         operand *result= IC_RESULT(ic); 
3519         
3520         FENTRY;
3521         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3522         /* assign the amsops */
3523         aopOp (left,ic,FALSE);
3524         aopOp (right,ic,FALSE);
3525         aopOp (result,ic,TRUE);
3526         
3527         /* special cases first */
3528         /* both are bits */
3529         if (AOP_TYPE(left) == AOP_CRY &&
3530                 AOP_TYPE(right)== AOP_CRY) {
3531                 genDivbits(left,right,result);
3532                 goto release ;
3533         }
3534         
3535         /* if both are of size == 1 */
3536         if (AOP_SIZE(left) == 1 &&
3537                 AOP_SIZE(right) == 1 ) {
3538                 genDivOneByte(left,right,result);
3539                 goto release ;
3540         }
3541         
3542         /* should have been converted to function call */
3543         assert(0);
3544 release :
3545         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3546         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3547         freeAsmop(result,NULL,ic,TRUE); 
3548 }
3549
3550 /*-----------------------------------------------------------------*/
3551 /* genModbits :- modulus of bits                                                                   */
3552 /*-----------------------------------------------------------------*/
3553 static void genModbits (operand *left, 
3554                                                 operand *right, 
3555                                                 operand *result)
3556 {
3557         
3558         char *l;
3559         
3560         FENTRY;
3561         /* the result must be bit */      
3562         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3563         l = aopGet(AOP(left),0,FALSE,FALSE);
3564         
3565         MOVA(l);
3566         
3567         pic14_emitcode("div","ab");
3568         pic14_emitcode("mov","a,b");
3569         pic14_emitcode("rrc","a");
3570         aopPut(AOP(result),"c",0);
3571 }
3572
3573 /*-----------------------------------------------------------------*/
3574 /* genModOneByte : 8 bit modulus                                                                   */
3575 /*-----------------------------------------------------------------*/
3576 static void genModOneByte (operand *left,
3577                                                    operand *right,
3578                                                    operand *result)
3579 {
3580         int size;
3581         
3582         FENTRY;
3583         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3584         
3585         assert (AOP_SIZE(result) == 1);
3586         assert (AOP_SIZE(right) == 1);
3587         assert (AOP_SIZE(left) == 1);
3588
3589         size = min(AOP_SIZE(result),AOP_SIZE(left));
3590
3591         if (AOP_TYPE(right) == AOP_LIT)
3592         {
3593                 /* XXX: might add specialized code */
3594         }
3595
3596         if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3597         {
3598                 /* unsigned division */
3599         #if 1
3600                 mov2w(AOP(right),0);
3601                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3602                 mov2w(AOP(left),0);
3603                 call_libraryfunc("__moduchar");
3604                 movwf(AOP(result),0);
3605         #else
3606                 pCodeOp *temp;
3607                 symbol *lbl;
3608
3609                 lbl = newiTempLabel(NULL);
3610                 
3611                 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3612
3613                 /* XXX: improve this naive approach:
3614                    [result] = [a] % [b]
3615                         ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3616
3617                    In PIC assembler:
3618                    movf  left,W
3619                    movwf result         // result <-- left
3620                    movf  right,W        // W <-- right
3621                    label1:
3622                    subwf result,F       // result <-- result - W
3623                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if result < W
3624                    goto  label1
3625                    addwf result, F      // we just subtract once too often
3626                  */
3627
3628                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3629                 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3630                 
3631                 if (!pic14_sameRegs(AOP(left), AOP(result)))
3632                 {
3633                         mov2w(AOP(left),0);
3634                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
3635                 }
3636                 mov2w(AOP(right),0);
3637
3638                 emitpLabel(lbl->key);
3639                 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3640                 emitSKPNC;
3641                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3642                 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3643         #endif
3644         }
3645         else
3646         {
3647                 /* signed division */
3648                 mov2w(AOP(right),0);
3649                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3650                 mov2w(AOP(left),0);
3651                 call_libraryfunc("__modschar");
3652                 movwf(AOP(result),0);
3653         }
3654
3655         /* now we performed the signed/unsigned modulus -- extend result */
3656         addSign(result, 1, !SPEC_USIGN(operandType(result)));
3657 }
3658
3659 /*-----------------------------------------------------------------*/
3660 /* genMod - generates code for division                                                    */
3661 /*-----------------------------------------------------------------*/
3662 static void genMod (iCode *ic)
3663 {
3664         operand *left = IC_LEFT(ic);
3665         operand *right = IC_RIGHT(ic);
3666         operand *result= IC_RESULT(ic);  
3667         
3668         FENTRY;
3669         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3670         /* assign the amsops */
3671         aopOp (left,ic,FALSE);
3672         aopOp (right,ic,FALSE);
3673         aopOp (result,ic,TRUE);
3674         
3675         /* special cases first */
3676         /* both are bits */
3677         if (AOP_TYPE(left) == AOP_CRY &&
3678                 AOP_TYPE(right)== AOP_CRY) {
3679                 genModbits(left,right,result);
3680                 goto release ;
3681         }
3682         
3683         /* if both are of size == 1 */
3684         if (AOP_SIZE(left) == 1 &&
3685                 AOP_SIZE(right) == 1 ) {
3686                 genModOneByte(left,right,result);
3687                 goto release ;
3688         }
3689         
3690         /* should have been converted to function call */
3691         assert(0);
3692         
3693 release :
3694         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3695         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3696         freeAsmop(result,NULL,ic,TRUE); 
3697 }
3698
3699 /*-----------------------------------------------------------------*/
3700 /* genIfxJump :- will create a jump depending on the ifx                   */
3701 /*-----------------------------------------------------------------*/
3702 /*
3703 note: May need to add parameter to indicate when a variable is in bit space.
3704 */
3705 static void genIfxJump (iCode *ic, char *jval)
3706 {
3707         
3708         FENTRY;
3709         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3710         /* if true label then we jump if condition
3711         supplied is true */
3712         if ( IC_TRUE(ic) ) {
3713                 
3714                 if(strcmp(jval,"a") == 0)
3715                         emitSKPZ;
3716                 else if (strcmp(jval,"c") == 0)
3717                         emitSKPC;
3718                 else {
3719                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3720                         emitpcode(POC_BTFSC,    newpCodeOpBit(jval,-1,1));
3721                 }
3722                 
3723                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3724                 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3725                 
3726         }
3727         else {
3728                 /* false label is present */
3729                 if(strcmp(jval,"a") == 0)
3730                         emitSKPNZ;
3731                 else if (strcmp(jval,"c") == 0)
3732                         emitSKPNC;
3733                 else {
3734                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3735                         emitpcode(POC_BTFSS,    newpCodeOpBit(jval,-1,1));
3736                 }
3737                 
3738                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3739                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3740                 
3741         }
3742         
3743         
3744         /* mark the icode as generated */
3745         ic->generated = 1;
3746 }
3747
3748 #if 0
3749 /*-----------------------------------------------------------------*/
3750 /* genSkip                                                                                                                 */
3751 /*-----------------------------------------------------------------*/
3752 static void genSkip(iCode *ifx,int status_bit)
3753 {
3754         FENTRY;
3755         if(!ifx)
3756                 return;
3757         
3758         if ( IC_TRUE(ifx) ) {
3759                 switch(status_bit) {
3760                 case 'z':
3761                         emitSKPNZ;
3762                         break;
3763                         
3764                 case 'c':
3765                         emitSKPNC;
3766                         break;
3767                         
3768                 case 'd':
3769                         emitSKPDC;
3770                         break;
3771                         
3772                 }
3773                 
3774                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3775                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3776                 
3777         } else {
3778                 
3779                 switch(status_bit) {
3780                         
3781                 case 'z':
3782                         emitSKPZ;
3783                         break;
3784                         
3785                 case 'c':
3786                         emitSKPC;
3787                         break;
3788                         
3789                 case 'd':
3790                         emitSKPDC;
3791                         break;
3792                 }
3793                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3794                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3795                 
3796         }
3797         
3798 }
3799 #endif
3800
3801 /*-----------------------------------------------------------------*/
3802 /* genSkipc                                                                                                        */
3803 /*-----------------------------------------------------------------*/
3804 static void genSkipc(resolvedIfx *rifx)
3805 {
3806         FENTRY;
3807         if(!rifx)
3808                 return;
3809         
3810         if(rifx->condition)
3811                 emitSKPNC;
3812         else
3813                 emitSKPC;
3814         
3815         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3816         emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3817         rifx->generated = 1;
3818 }
3819
3820 #if 0
3821 /*-----------------------------------------------------------------*/
3822 /* genSkipz2                                                                                                       */
3823 /*-----------------------------------------------------------------*/
3824 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3825 {
3826         FENTRY;
3827         if(!rifx)
3828                 return;
3829         
3830         if( (rifx->condition ^ invert_condition) & 1)
3831                 emitSKPZ;
3832         else
3833                 emitSKPNZ;
3834         
3835         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3836         rifx->generated = 1;
3837 }
3838 #endif
3839
3840 #if 0
3841 /*-----------------------------------------------------------------*/
3842 /* genSkipz                                                        */
3843 /*-----------------------------------------------------------------*/
3844 static void genSkipz(iCode *ifx, int condition)
3845 {
3846         FENTRY;
3847         assert (ifx != NULL);
3848         
3849         if(condition)
3850                 emitSKPNZ;
3851         else
3852                 emitSKPZ;
3853         
3854         if ( IC_TRUE(ifx) )
3855                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3856         else
3857                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3858         
3859         if ( IC_TRUE(ifx) )
3860                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3861         else
3862                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3863         
3864 }
3865 #endif
3866
3867 #if 0
3868 /*-----------------------------------------------------------------*/
3869 /* genSkipCond                                                     */
3870 /*-----------------------------------------------------------------*/
3871 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3872 {
3873         FENTRY;
3874         if(!rifx)
3875                 return;
3876         
3877         if(rifx->condition)
3878                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3879         else
3880                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3881         
3882         
3883         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3884         rifx->generated = 1;
3885 }
3886 #endif
3887
3888 #if 0
3889 /*-----------------------------------------------------------------*/
3890 /* genChkZeroes :- greater or less than comparison                 */
3891 /*     For each byte in a literal that is zero, inclusive or the   */
3892 /*     the corresponding byte in the operand with W                */
3893 /*     returns true if any of the bytes are zero                   */
3894 /*-----------------------------------------------------------------*/
3895 static int genChkZeroes(operand *op, int lit,  int size)
3896 {
3897         
3898         int i;
3899         int flag =1;
3900         
3901         while(size--) {
3902                 i = (lit >> (size*8)) & 0xff;
3903                 
3904                 if(i==0) {
3905                         if(flag) 
3906                                 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3907                         else
3908                                 emitpcode(POC_IORFW, popGet(AOP(op),size));
3909                         flag = 0;
3910                 }
3911         }
3912         
3913         return (flag==0);
3914 }
3915 #endif
3916
3917
3918 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3919 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
3920 #define DEBUGpc           emitpComment
3921
3922 /*-----------------------------------------------------------------*/
3923 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
3924 /*                  aop (if it's NOT a literal) or from lit (if    */
3925 /*                  aop is a literal)                              */
3926 /*-----------------------------------------------------------------*/
3927 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3928   if (aop->type == AOP_LIT) {
3929     emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3930   } else {
3931     emitpcode (POC_MOVFW, popGet (aop, offset));
3932   }
3933 }
3934
3935 /* genCmp performs a left < right comparison, stores
3936  * the outcome in result (if != NULL) and generates
3937  * control flow code for the ifx (if != NULL).
3938  *
3939  * This version leaves in sequences like
3940  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3941  * which should be optmized by the peephole
3942  * optimizer - RN 2005-01-01 */
3943 static void genCmp (operand *left,operand *right,
3944                     operand *result, iCode *ifx, int sign)
3945 {
3946   resolvedIfx rIfx;
3947   int size;
3948   int offs;
3949   symbol *templbl;
3950   operand *dummy;
3951   unsigned long lit;
3952   unsigned long mask;
3953   int performedLt;
3954   int invert_result = 0;
3955
3956   FENTRY;
3957   
3958   assert (AOP_SIZE(left) == AOP_SIZE(right));
3959   assert (left && right);
3960
3961   size = AOP_SIZE(right) - 1;
3962   mask = (0x100UL << (size*8)) - 1;
3963   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3964   performedLt = 1;
3965   templbl = NULL;
3966   lit = 0;
3967   
3968   resolveIfx (&rIfx, ifx);
3969
3970   /**********************************************************************
3971    * handle bits - bit compares are promoted to int compares seemingly! *
3972    **********************************************************************/
3973 #if 0
3974   // THIS IS COMPLETELY UNTESTED!
3975   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3976     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3977     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3978     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3979
3980     emitSETC;
3981     // 1 < {0,1} is false --> clear C by skipping the next instruction
3982     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3983     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3984     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3985     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3986     emitCLRC; // only skipped for left=0 && right=1
3987
3988     goto correct_result_in_carry;
3989   } // if
3990 #endif
3991
3992   /*************************************************
3993    * make sure that left is register (or the like) *
3994    *************************************************/
3995   if (!isAOP_REGlike(left)) {
3996     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3997     assert (isAOP_LIT(left));
3998     assert (isAOP_REGlike(right));
3999     // swap left and right
4000     // left < right <==> right > left <==> (right >= left + 1)
4001     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4002
4003     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4004       // MAXVALUE < right? always false
4005       if (performedLt) emitCLRC; else emitSETC;
4006       goto correct_result_in_carry;
4007     } // if
4008
4009     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4010     // that's why we handled it above.
4011     lit++;
4012
4013     dummy = left;
4014     left = right;
4015     right = dummy;
4016
4017     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4018   } else if (isAOP_LIT(right)) {
4019     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4020   } // if
4021
4022   assert (isAOP_REGlike(left)); // left must be register or the like
4023   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4024
4025   /*************************************************
4026    * special cases go here                         *
4027    *************************************************/
4028
4029   if (isAOP_LIT(right)) {
4030     if (!sign) {
4031       // unsigned comparison to a literal
4032       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4033       if (lit == 0) {
4034         // unsigned left < 0? always false
4035         if (performedLt) emitCLRC; else emitSETC;
4036         goto correct_result_in_carry;
4037       }
4038     } else {
4039       // signed comparison to a literal
4040       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4041       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4042         // signed left < 0x80000000? always false
4043         if (performedLt) emitCLRC; else emitSETC;
4044         goto correct_result_in_carry;
4045       } else if (lit == 0) {
4046         // compare left < 0; set CARRY if SIGNBIT(left) is set
4047         if (performedLt) emitSETC; else emitCLRC;
4048         emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
4049         if (performedLt) emitCLRC; else emitSETC;
4050         goto correct_result_in_carry;
4051       }
4052     } // if (!sign)
4053   } // right is literal
4054
4055   /*************************************************
4056    * perform a general case comparison             *
4057    * make sure we get CARRY==1 <==> left >= right  *
4058    *************************************************/
4059   // compare most significant bytes
4060   //DEBUGpc ("comparing bytes at offset %d", size);
4061   if (!sign) {
4062     // unsigned comparison
4063     pic14_mov2w_regOrLit (AOP(right), lit, size);
4064     emitpcode (POC_SUBFW, popGet (AOP(left), size));
4065   } else {
4066     // signed comparison
4067     // (add 2^n to both operands then perform an unsigned comparison)
4068     if (isAOP_LIT(right)) {
4069       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4070       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4071
4072       if (litbyte == 0x80) {
4073         // left >= 0x80 -- always true, but more bytes to come
4074         mov2w (AOP(left), size);
4075         emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
4076         emitSETC;
4077       } else {
4078         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4079         mov2w (AOP(left), size);
4080         emitpcode (POC_ADDLW, popGetLit (0x80));
4081         emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4082       } // if
4083     } else {
4084       pCodeOp *pctemp = popGetTempReg();
4085       mov2w (AOP(left), size);
4086       emitpcode (POC_ADDLW, popGetLit (0x80));
4087       emitpcode (POC_MOVWF, pctemp);
4088       mov2w (AOP(right), size);
4089       emitpcode (POC_ADDLW, popGetLit (0x80));
4090       emitpcode (POC_SUBFW, pctemp);
4091       popReleaseTempReg(pctemp);
4092     }
4093   } // if (!sign)
4094
4095   // compare remaining bytes (treat as unsigned case from above)
4096   templbl = newiTempLabel ( NULL );
4097   offs = size;
4098   while (offs--) {
4099     //DEBUGpc ("comparing bytes at offset %d", offs);
4100     emitSKPZ;
4101     emitpcode (POC_GOTO, popGetLabel (templbl->key));
4102     pic14_mov2w_regOrLit (AOP(right), lit, offs);
4103     emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4104   } // while (offs)
4105   emitpLabel (templbl->key);
4106   goto result_in_carry;
4107
4108 result_in_carry:
4109   
4110   /****************************************************
4111    * now CARRY contains the result of the comparison: *
4112    * SUBWF sets CARRY iff                             *
4113    * F-W >= 0 <==> F >= W <==> !(F < W)               *
4114    * (F=left, W=right)                                *
4115    ****************************************************/
4116
4117   if (performedLt) {
4118     invert_result = 1;
4119     // value will be used in the following genSkipc()
4120     rIfx.condition ^= 1;
4121   } // if
4122
4123 correct_result_in_carry:
4124
4125   // assign result to variable (if neccessary)
4126   if (result && AOP_TYPE(result) != AOP_CRY) {
4127     //DEBUGpc ("assign result");
4128     size = AOP_SIZE(result);
4129     while (size--) {
4130       emitpcode (POC_CLRF, popGet (AOP(result), size));
4131     } // while
4132     if (invert_result) {
4133       emitSKPC;
4134       emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4135     } else {
4136       emitpcode (POC_RLF, popGet (AOP(result), 0));
4137     }
4138   } // if (result)
4139
4140   // perform conditional jump
4141   if (ifx) {
4142     //DEBUGpc ("generate control flow");
4143     genSkipc (&rIfx);
4144     ifx->generated = 1;
4145   } // if
4146 }
4147
4148
4149 #if 0
4150 /* OLD VERSION -- BUGGY, DO NOT USE */
4151
4152 /*-----------------------------------------------------------------*/
4153 /* genCmp :- greater or less than comparison                       */
4154 /*-----------------------------------------------------------------*/
4155 static void genCmp (operand *left,operand *right,
4156                                         operand *result, iCode *ifx, int sign)
4157 {
4158         int size; //, offset = 0 ;
4159         unsigned long lit = 0L,i = 0;
4160         resolvedIfx rFalseIfx;
4161         //  resolvedIfx rTrueIfx;
4162         symbol *truelbl;
4163
4164         FENTRY;
4165         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4166         /*
4167         if(ifx) {
4168         DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4169         DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4170         }
4171         */
4172         
4173         resolveIfx(&rFalseIfx,ifx);
4174         truelbl  = newiTempLabel(NULL);
4175         size = max(AOP_SIZE(left),AOP_SIZE(right));
4176         
4177         DEBUGpic14_AopType(__LINE__,left,right,result);
4178         
4179 #define _swapp
4180         
4181         /* if literal is on the right then swap with left */
4182         if ((AOP_TYPE(right) == AOP_LIT)) {
4183                 operand *tmp = right ;
4184                 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4185                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4186 #ifdef _swapp
4187                 
4188                 lit = (lit - 1) & mask;
4189                 right = left;
4190                 left = tmp;
4191                 rFalseIfx.condition ^= 1;
4192 #endif
4193                 
4194         } else if ((AOP_TYPE(left) == AOP_LIT)) {
4195                 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4196         }
4197         
4198         
4199         //if(IC_TRUE(ifx) == NULL)
4200         /* if left & right are bit variables */
4201         if (AOP_TYPE(left) == AOP_CRY &&
4202                 AOP_TYPE(right) == AOP_CRY ) {
4203                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4204                 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4205         } else {
4206         /* subtract right from left if at the
4207         end the carry flag is set then we know that
4208                 left is greater than right */
4209                 
4210                 symbol *lbl  = newiTempLabel(NULL);
4211                 
4212 #ifndef _swapp
4213                 if(AOP_TYPE(right) == AOP_LIT) {
4214                         
4215                         //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4216                         
4217                         DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4218                         
4219                         /* special cases */
4220                         
4221                         if(lit == 0) {
4222                                 
4223                                 if(sign != 0) 
4224                                         genSkipCond(&rFalseIfx,left,size-1,7);
4225                                 else 
4226                                         /* no need to compare to 0...*/
4227                                         /* NOTE: this is a de-generate compare that most certainly 
4228                                         *       creates some dead code. */
4229                                         emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4230                                 
4231                                 if(ifx) ifx->generated = 1;
4232                                 return;
4233                                 
4234                         }
4235                         size--;
4236                         
4237                         if(size == 0) {
4238                                 //i = (lit >> (size*8)) & 0xff;
4239                                 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4240                                 
4241                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4242                                 
4243                                 i = ((0-lit) & 0xff);
4244                                 if(sign) {
4245                                         if( i == 0x81) { 
4246                                         /* lit is 0x7f, all signed chars are less than
4247                                                 * this except for 0x7f itself */
4248                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4249                                                 genSkipz2(&rFalseIfx,0);
4250                                         } else {
4251                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4252                                                 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4253                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4254                                         }
4255                                         
4256                                 } else {
4257                                         if(lit == 1) {
4258                                                 genSkipz2(&rFalseIfx,1);
4259                                         } else {
4260                                                 emitpcode(POC_ADDLW, popGetLit(i));
4261                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4262                                         }
4263                                 }
4264                                 
4265                                 if(ifx) ifx->generated = 1;
4266                                 return;
4267                         }
4268                         
4269                         /* chars are out of the way. now do ints and longs */
4270                         
4271                         
4272                         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4273                         
4274                         /* special cases */
4275                         
4276                         if(sign) {
4277                                 
4278                                 if(lit == 0) {
4279                                         genSkipCond(&rFalseIfx,left,size,7);
4280                                         if(ifx) ifx->generated = 1;
4281                                         return;
4282                                 }
4283                                 
4284                                 if(lit <0x100) {
4285                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4286                                         
4287                                         //rFalseIfx.condition ^= 1;
4288                                         //genSkipCond(&rFalseIfx,left,size,7);
4289                                         //rFalseIfx.condition ^= 1;
4290                                         
4291                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4292                                         if(rFalseIfx.condition)
4293                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4294                                         else
4295                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4296                                         
4297                                         emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4298                                         emitpcode(POC_ADDFW, popGet(AOP(left),0));
4299                                         emitpcode(POC_MOVFW, popGet(AOP(left),1));
4300                                         
4301                                         while(size > 1)
4302                                                 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4303                                         
4304                                         if(rFalseIfx.condition) {
4305                                                 emitSKPZ;
4306                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4307                                                 
4308                                         } else {
4309                                                 emitSKPNZ;
4310                                         }
4311                                         
4312                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4313                                         emitpLabel(truelbl->key);
4314                                         if(ifx) ifx->generated = 1;
4315                                         return;
4316                                         
4317                                 }
4318                                 
4319                                 if(size == 1) {
4320                                         
4321                                         if( (lit & 0xff) == 0) {
4322                                                 /* lower byte is zero */
4323                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4324                                                 i = ((lit >> 8) & 0xff) ^0x80;
4325                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4326                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4327                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4328                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4329                                                 
4330                                                 
4331                                                 if(ifx) ifx->generated = 1;
4332                                                 return;
4333                                                 
4334                                         }
4335                                 } else {
4336                                         /* Special cases for signed longs */
4337                                         if( (lit & 0xffffff) == 0) {
4338                                                 /* lower byte is zero */
4339                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4340                                                 i = ((lit >> 8*3) & 0xff) ^0x80;
4341                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4342                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4343                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4344                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4345                                                 
4346                                                 
4347                                                 if(ifx) ifx->generated = 1;
4348                                                 return;
4349                                                 
4350                                         }
4351                                         
4352                                 }
4353                                 
4354                                 
4355                                 if(lit & (0x80 << (size*8))) {
4356                                         /* lit is negative */
4357                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4358                                         
4359                                         //genSkipCond(&rFalseIfx,left,size,7);
4360                                         
4361                                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4362                                         
4363                                         if(rFalseIfx.condition)
4364                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4365                                         else
4366                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4367                                         
4368                                         
4369                                 } else {
4370                                         /* lit is positive */
4371                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4372                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4373                                         if(rFalseIfx.condition)
4374                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4375                                         else
4376                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4377                                         
4378                                 }
4379                                 
4380                                 /* There are no more special cases, so perform a general compare */
4381                                 
4382                                 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4383                                 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4384                                 
4385                                 while(size--) {
4386                                         
4387                                         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4388                                         emitSKPNZ;
4389                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4390                                 }
4391                                 //rFalseIfx.condition ^= 1;
4392                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4393                                 
4394                                 emitpLabel(truelbl->key);
4395                                 
4396                                 if(ifx) ifx->generated = 1;
4397                                 return;
4398                                 
4399                                 
4400                         }
4401
4402
4403                         /* sign is out of the way. So now do an unsigned compare */
4404                         DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4405
4406
4407                         /* General case - compare to an unsigned literal on the right.*/
4408
4409                         i = (lit >> (size*8)) & 0xff;
4410                         emitpcode(POC_MOVLW, popGetLit(i));
4411                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4412                         while(size--) {
4413                                 i = (lit >> (size*8)) & 0xff;
4414                                 
4415                                 if(i) {
4416                                         emitpcode(POC_MOVLW, popGetLit(i));
4417                                         emitSKPNZ;
4418                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4419                                 } else {
4420                                 /* this byte of the lit is zero, 
4421                                         *if it's not the last then OR in the variable */
4422                                         if(size)
4423                                                 emitpcode(POC_IORFW, popGet(AOP(left),size));
4424                                 }
4425                         }
4426
4427
4428                 emitpLabel(lbl->key);
4429                 //if(emitFinalCheck)
4430                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4431                 if(sign)
4432                         emitpLabel(truelbl->key);
4433
4434                 if(ifx) ifx->generated = 1;
4435                 return;
4436
4437
4438                 }
4439 #endif  // _swapp
4440
4441                 if(AOP_TYPE(left) == AOP_LIT) {
4442                         //symbol *lbl = newiTempLabel(NULL);
4443                         
4444                         //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4445                         
4446                         
4447                         DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4448                         
4449                         /* Special cases */
4450                         if((lit == 0) && (sign == 0)){
4451                                 
4452                                 size--;
4453                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4454                                 while(size) 
4455                                         emitpcode(POC_IORFW, popGet(AOP(right),--size));
4456                                 
4457                                 genSkipz2(&rFalseIfx,0);
4458                                 if(ifx) ifx->generated = 1;
4459                                 return;
4460                         }
4461                         
4462                         if(size==1) {
4463                                 /* Special cases */
4464                                 lit &= 0xff;
4465                                 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4466                                         /* degenerate compare can never be true */
4467                                         if(rFalseIfx.condition == 0)
4468                                                 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4469                                         
4470                                         if(ifx) ifx->generated = 1;
4471                                         return;
4472                                 }
4473                                 
4474                                 if(sign) {
4475                                         /* signed comparisons to a literal byte */
4476                                         
4477                                         int lp1 = (lit+1) & 0xff;
4478                                         
4479                                         DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4480                                         switch (lp1) {
4481                                         case 0:
4482                                                 rFalseIfx.condition ^= 1;
4483                                                 genSkipCond(&rFalseIfx,right,0,7);
4484                                                 break;
4485                                         case 0x7f:
4486                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4487                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4488                                                 genSkipz2(&rFalseIfx,1);
4489                                                 break;
4490                                         default:
4491                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4492                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4493                                                 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4494                                                 rFalseIfx.condition ^= 1;
4495                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4496                                                 break;
4497                                         }
4498                                         if(ifx) ifx->generated = 1;
4499                                 } else {
4500                                         /* unsigned comparisons to a literal byte */
4501                                         
4502                                         switch(lit & 0xff ) {
4503                                         case 0:
4504                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4505                                                 genSkipz2(&rFalseIfx,0);
4506                                                 if(ifx) ifx->generated = 1;
4507                                                 break;
4508                                         case 0x7f:
4509                                                 genSkipCond(&rFalseIfx,right,0,7);
4510                                                 if(ifx) ifx->generated = 1;
4511                                                 break;
4512                                                 
4513                                         default:
4514                                                 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4515                                                 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4516                                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4517                                                 rFalseIfx.condition ^= 1;
4518                                                 if (AOP_TYPE(result) == AOP_CRY) {
4519                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4520                                                         if(ifx) ifx->generated = 1;
4521                                                 } else {
4522                                                         DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4523                                                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4524                                                         emitpcode(POC_RLF, popGet(AOP(result),0));
4525                                                         emitpcode(POC_MOVLW, popGetLit(0x01));
4526                                                         emitpcode(POC_XORWF, popGet(AOP(result),0));
4527                                                 }       
4528                                                 break;
4529                                         }
4530                                 }
4531                                 
4532                                 //goto check_carry;
4533                                 return;
4534                                 
4535                         } else {
4536                                 
4537                                 /* Size is greater than 1 */
4538                                 
4539                                 if(sign) {
4540                                         int lp1 = lit+1;
4541                                         
4542                                         size--;
4543                                         
4544                                         if(lp1 == 0) {
4545                                                 /* this means lit = 0xffffffff, or -1 */
4546                                                 
4547                                                 
4548                                                 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4549                                                 rFalseIfx.condition ^= 1;
4550                                                 genSkipCond(&rFalseIfx,right,size,7);
4551                                                 if(ifx) ifx->generated = 1;
4552                                                 return;
4553                                         }
4554                                         
4555                                         if(lit == 0) {
4556                                                 int s = size;
4557                                                 
4558                                                 if(rFalseIfx.condition) {
4559                                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4560                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4561                                                 }
4562                                                 
4563                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4564                                                 while(size--)
4565                                                         emitpcode(POC_IORFW, popGet(AOP(right),size));
4566                                                 
4567                                                 
4568                                                 emitSKPZ;
4569                                                 if(rFalseIfx.condition) {
4570                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4571                                                         emitpLabel(truelbl->key);
4572                                                 }else {
4573                                                         rFalseIfx.condition ^= 1;
4574                                                         genSkipCond(&rFalseIfx,right,s,7);
4575                                                 }
4576                                                 
4577                                                 if(ifx) ifx->generated = 1;
4578                                                 return;
4579                                         }
4580                                         
4581                                         if((size == 1) &&  (0 == (lp1&0xff))) {
4582                                                 /* lower byte of signed word is zero */
4583                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4584                                                 i = ((lp1 >> 8) & 0xff) ^0x80;
4585                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4586                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4587                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4588                                                 rFalseIfx.condition ^= 1;
4589                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4590                                                 
4591                                                 
4592                                                 if(ifx) ifx->generated = 1;
4593                                                 return;
4594                                         }
4595                                         
4596                                         if(lit & (0x80 << (size*8))) {
4597                                                 /* Lit is less than zero */
4598                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4599                                                 //rFalseIfx.condition ^= 1;
4600                                                 //genSkipCond(&rFalseIfx,left,size,7);
4601                                                 //rFalseIfx.condition ^= 1;
4602                                                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4603                                                 //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4604                                                 
4605                                                 if(rFalseIfx.condition)
4606                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4607                                                 else
4608                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4609                                                 
4610                                                 
4611                                         } else {
4612                                                 /* Lit is greater than or equal to zero */
4613                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4614                                                 //rFalseIfx.condition ^= 1;
4615                                                 //genSkipCond(&rFalseIfx,right,size,7);
4616                                                 //rFalseIfx.condition ^= 1;
4617                                                 
4618                                                 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4619                                                 //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4620                                                 
4621                                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4622                                                 if(rFalseIfx.condition)
4623                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4624                                                 else
4625                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4626                                                 
4627                                         }
4628                                         
4629                                         
4630                                         emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4631                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4632                                         
4633                                         while(size--) {
4634                                                 
4635                                                 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4636                                                 emitSKPNZ;
4637                                                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4638                                         }
4639                                         rFalseIfx.condition ^= 1;
4640                                         //rFalseIfx.condition = 1;
4641                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4642                                         
4643                                         emitpLabel(truelbl->key);
4644                                         
4645                                         if(ifx) ifx->generated = 1;
4646                                         return;
4647                                         // end of if (sign)
4648                                 } else {
4649                                         
4650                                         /* compare word or long to an unsigned literal on the right.*/
4651                                         
4652                                         
4653                                         size--;
4654                                         if(lit < 0xff) {
4655                                                 DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4656                                                 switch (lit) {
4657                                                 case 0:
4658                                                         break; /* handled above */
4659                                                 /*
4660                                                 case 0xff:
4661                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4662                                                         while(size--)
4663                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4664                                                         genSkipz2(&rFalseIfx,0);
4665                                                         break;
4666                                                 */
4667                                                 default:
4668                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4669                                                         while(--size)
4670                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4671                                                         
4672                                                         emitSKPZ;
4673                                                         if(rFalseIfx.condition)
4674                                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4675                                                         else
4676                                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4677                                                         
4678                                                         
4679                                                         emitpcode(POC_MOVLW, popGetLit(lit+1));
4680                                                         emitpcode(POC_SUBFW, popGet(AOP(right),0));
4681                                                         
4682                                                         rFalseIfx.condition ^= 1;
4683                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4684                                                 }
4685                                                 
4686                                                 emitpLabel(truelbl->key);
4687                                                 
4688                                                 if(ifx) ifx->generated = 1;
4689                                                 return;
4690                                         }
4691                                         
4692                                         
4693                                         lit++;
4694                                         DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4695                                         i = (lit >> (size*8)) & 0xff;
4696                                         
4697                                         emitpcode(POC_MOVLW, popGetLit(i));
4698                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4699                                         
4700                                         while(size--) {
4701                                                 i = (lit >> (size*8)) & 0xff;
4702                                                 
4703                                                 if(i) {
4704                                                         emitpcode(POC_MOVLW, popGetLit(i));
4705                                                         emitSKPNZ;
4706                                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4707                                                 } else {
4708                                                 /* this byte of the lit is zero, 
4709                                                         *if it's not the last then OR in the variable */
4710                                                         if(size)
4711                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4712                                                 }
4713                                         }
4714                                         
4715                                         
4716                                         emitpLabel(lbl->key);
4717                                         
4718                                         rFalseIfx.condition ^= 1;
4719                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4720                                 }
4721                                 
4722                                 if(sign)
4723                                         emitpLabel(truelbl->key);
4724                                 if(ifx) ifx->generated = 1;
4725                                 return;
4726                         }
4727                 }
4728                 /* Compare two variables */
4729                 
4730                 DEBUGpic14_emitcode(";sign","%d",sign);
4731                 
4732                 size--;
4733                 if(sign) {
4734                         /* Sigh. thus sucks... */
4735                         if(size) {
4736                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4737                                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4738                                 emitpcode(POC_MOVLW, popGetLit(0x80));
4739                                 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4740                                 emitpcode(POC_XORFW, popGet(AOP(right),size));
4741                                 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4742                         } else {
4743                                 /* Signed char comparison */
4744                                 /* Special thanks to Nikolai Golovchenko for this snippet */
4745                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4746                                 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4747                                 emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4748                                 emitpcode(POC_XORFW, popGet(AOP(left),0));
4749                                 emitpcode(POC_XORFW, popGet(AOP(right),0));
4750                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4751                                 
4752                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4753                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4754                                 
4755                                 if(ifx) ifx->generated = 1;
4756                                 return;
4757                         }
4758                         
4759                 } else {
4760                         
4761                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4762                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4763                 }
4764                 
4765                 
4766                 /* The rest of the bytes of a multi-byte compare */
4767                 while (size) {
4768                         
4769                         emitSKPZ;
4770                         emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4771                         size--;
4772                         
4773                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4774                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4775                         
4776                         
4777                 }
4778                 
4779                 emitpLabel(lbl->key);
4780                 
4781                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4782                 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4783                         (AOP_TYPE(result) == AOP_REG)) {
4784                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4785                         emitpcode(POC_RLF, popGet(AOP(result),0));
4786                 } else {
4787                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4788                 }       
4789                 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4790                 if(ifx) ifx->generated = 1;
4791                 
4792                 return;
4793                 
4794         }
4795         
4796         // check_carry:
4797         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4798                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4799                 pic14_outBitC(result);
4800         } else {
4801                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4802                 /* if the result is used in the next
4803                 ifx conditional branch then generate
4804                 code a little differently */
4805                 if (ifx )
4806                         genIfxJump (ifx,"c");
4807                 else
4808                         pic14_outBitC(result);
4809                 /* leave the result in acc */
4810         }
4811         
4812 }
4813 #endif
4814
4815 /*-----------------------------------------------------------------*/
4816 /* genCmpGt :- greater than comparison                             */
4817 /*-----------------------------------------------------------------*/
4818 static void genCmpGt (iCode *ic, iCode *ifx)
4819 {
4820         operand *left, *right, *result;
4821         sym_link *letype , *retype;
4822         int sign ;
4823         
4824         FENTRY;
4825         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4826         left = IC_LEFT(ic);
4827         right= IC_RIGHT(ic);
4828         result = IC_RESULT(ic);
4829         
4830         letype = getSpec(operandType(left));
4831         retype =getSpec(operandType(right));
4832         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4833         /* assign the amsops */
4834         aopOp (left,ic,FALSE);
4835         aopOp (right,ic,FALSE);
4836         aopOp (result,ic,TRUE);
4837         
4838         genCmp(right, left, result, ifx, sign);
4839         
4840         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4841         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4842         freeAsmop(result,NULL,ic,TRUE); 
4843 }
4844
4845 /*-----------------------------------------------------------------*/
4846 /* genCmpLt - less than comparisons                                */
4847 /*-----------------------------------------------------------------*/
4848 static void genCmpLt (iCode *ic, iCode *ifx)
4849 {
4850         operand *left, *right, *result;
4851         sym_link *letype , *retype;
4852         int sign ;
4853         
4854         FENTRY;
4855         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4856         left = IC_LEFT(ic);
4857         right= IC_RIGHT(ic);
4858         result = IC_RESULT(ic);
4859         
4860         letype = getSpec(operandType(left));
4861         retype =getSpec(operandType(right));
4862         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4863         
4864         /* assign the amsops */
4865         aopOp (left,ic,FALSE);
4866         aopOp (right,ic,FALSE);
4867         aopOp (result,ic,TRUE);
4868         
4869         genCmp(left, right, result, ifx, sign);
4870         
4871         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4872         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4873         freeAsmop(result,NULL,ic,TRUE); 
4874 }
4875
4876 #if 0
4877 /*-----------------------------------------------------------------*/
4878 /* genc16bit2lit - compare a 16 bit value to a literal             */
4879 /*-----------------------------------------------------------------*/
4880 static void genc16bit2lit(operand *op, int lit, int offset)
4881 {
4882         int i;
4883         
4884         FENTRY;
4885         DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4886         if( (lit&0xff) == 0) 
4887                 i=1;
4888         else
4889                 i=0;
4890         
4891         switch( BYTEofLONG(lit,i)) { 
4892         case 0:
4893                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4894                 break;
4895         case 1:
4896                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4897                 break;
4898         case 0xff:
4899                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4900                 break;
4901         default:
4902                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4903                 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4904         }
4905         
4906         i ^= 1;
4907         
4908         switch( BYTEofLONG(lit,i)) { 
4909         case 0:
4910                 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4911                 break;
4912         case 1:
4913                 emitSKPNZ;
4914                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4915                 break;
4916         case 0xff:
4917                 emitSKPNZ;
4918                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4919                 break;
4920         default:
4921                 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4922                 emitSKPNZ;
4923                 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4924                 
4925         }
4926         
4927 }
4928 #endif
4929
4930 #if 0
4931 /*-----------------------------------------------------------------*/
4932 /* gencjneshort - compare and jump if not equal                    */
4933 /*-----------------------------------------------------------------*/
4934 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4935 {
4936         int size = min(AOP_SIZE(left),AOP_SIZE(right));
4937         int offset = 0;
4938         //resolvedIfx rIfx;
4939         symbol *lbl;
4940         
4941         //unsigned long lit = 0L;
4942         FENTRY;
4943         if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4944           emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4945           return;
4946         }
4947         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4948         DEBUGpic14_AopType(__LINE__,left,right,result);
4949         
4950         assert (!pic14_sameRegs (AOP(left), AOP(result)));
4951         assert (!pic14_sameRegs (AOP(right), AOP(result)));
4952         if (AOP_SIZE(result)) {
4953           for (offset = 0; offset < AOP_SIZE(result); offset++)
4954             emitpcode (POC_CLRF, popGet (AOP(result), offset));
4955         }
4956         
4957         assert (AOP_SIZE(left) == AOP_SIZE(right));
4958         //resolveIfx(&rIfx,ifx);
4959         lbl = newiTempLabel (NULL);
4960         while (size--)
4961         {
4962           mov2w (AOP(right),size);
4963           emitpcode (POC_XORFW, popGet (AOP(left), size));
4964           if (size)
4965           {
4966             emitSKPZ;
4967             emitpcode (POC_GOTO, popGetLabel (lbl->key));
4968           }
4969         } // while
4970         emitpLabel (lbl->key);
4971         if (AOP_SIZE(result)) {
4972           emitSKPNZ;
4973           emitpcode (POC_INCF, popGet (AOP(result), 0));
4974         } else {
4975           assert (ifx);
4976           genSkipz (ifx, NULL != IC_TRUE(ifx));
4977           ifx->generated = 1;
4978         }
4979         return;
4980 #if 0   
4981         if(result)
4982         {
4983                 DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4984                 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4985                 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4986                 for (offset=0; offset < AOP_SIZE(result); offset++)
4987                 {
4988                         emitpcode (POC_CLRF, popGet (AOP(result), offset));
4989                 } // for offset
4990         }
4991         
4992         
4993         /* if the left side is a literal or 
4994         if the right is in a pointer register and left 
4995         is not */
4996         if ((AOP_TYPE(left) == AOP_LIT) || 
4997                 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4998                 operand *t = right;
4999                 right = left;
5000                 left = t;
5001         }
5002         if(AOP_TYPE(right) == AOP_LIT)
5003                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5004         
5005         /* if the right side is a literal then anything goes */
5006         if (AOP_TYPE(right) == AOP_LIT &&
5007                 AOP_TYPE(left) != AOP_DIR ) {
5008                 switch(size) {
5009                 case 2:
5010                         genc16bit2lit(left, lit, 0);
5011                         emitSKPNZ;
5012                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
5013                         break;
5014                 default:
5015                         offset = 0;
5016                         while (size--) {
5017                                 if(lit & 0xff) {
5018                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5019                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5020                                 } else {
5021                                         emitpcode(POC_MOVF,popGet(AOP(left),offset));
5022                                 }
5023                                 
5024                                 emitSKPNZ;
5025                                 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5026                                 offset++;
5027                                 lit >>= 8;
5028                         }
5029                         break;
5030                 }
5031         }
5032         
5033         /* if the right side is in a register or in direct space or
5034         if the left is a pointer register & right is not */    
5035         else if (AOP_TYPE(right) == AOP_REG ||
5036                 AOP_TYPE(right) == AOP_DIR || 
5037                 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5038                 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5039                 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5040                 int lbl_key = lbl->key;
5041                 
5042                 if(!result) {
5043                         DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5044                         fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5045                                 __FUNCTION__,__LINE__);
5046                         return;
5047                 }
5048                 
5049                 /*     switch(size) { */
5050                 /*     case 2: */
5051                 /*       genc16bit2lit(left, lit, 0); */
5052                 /*       emitSKPNZ; */
5053                 /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
5054                 /*       break; */
5055                 /*     default: */
5056                 offset = 0;
5057                 while (size--) {
5058                         int emit_skip=1;
5059                         if((AOP_TYPE(left) == AOP_DIR) && 
5060                                 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5061                                 
5062                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5063                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5064                                 
5065                         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5066                                 
5067                                 switch (lit & 0xff) {
5068                                 case 0:
5069                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5070                                         break;
5071                                 case 1:
5072                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5073                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5074                                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
5075                                         emit_skip=0;
5076                                         break;
5077                                 case 0xff:
5078                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5079                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5080                                         //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5081                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5082                                         emit_skip=0;
5083                                         break;
5084                                 default:
5085                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5086                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5087                                 }
5088                                 lit >>= 8;
5089                                 
5090                         } else {
5091                                 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5092                         }
5093                         if(emit_skip) {
5094                                 if(AOP_TYPE(result) == AOP_CRY) {
5095                                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5096                                         if(rIfx.condition)
5097                                                 emitSKPNZ;
5098                                         else
5099                                                 emitSKPZ;
5100                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5101                                 } else {
5102                                         /* fix me. probably need to check result size too */
5103                                         //emitpcode(POC_CLRF,popGet(AOP(result),0));
5104                                         if(rIfx.condition)
5105                                                 emitSKPZ;
5106                                         else
5107                                                 emitSKPNZ;
5108                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5109                                 }
5110                                 if(ifx)
5111                                         ifx->generated=1;
5112                         }
5113                         emit_skip++;
5114                         offset++;
5115                 }
5116                 /*       break; */
5117                 /*     } */
5118         } else if(AOP_TYPE(right) == AOP_REG &&
5119                 AOP_TYPE(left) != AOP_DIR){
5120
5121                 offset = 0;
5122                 while(size--) {
5123                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5124                         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5125                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5126                         if(rIfx.condition)
5127                                 emitSKPNZ;
5128                         else
5129                                 emitSKPZ;
5130                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5131                         offset++;
5132                 }
5133                 
5134         }else{
5135                 /* right is a pointer reg need both a & b */
5136                 offset = 0;
5137                 while(size--) {
5138                         char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5139                         if(strcmp(l,"b"))
5140                                 pic14_emitcode("mov","b,%s",l);
5141                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5142                         pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5143                         offset++;
5144                 }
5145         }
5146         
5147         emitpcode(POC_INCF,popGet(AOP(result),0));
5148         if(!rIfx.condition)
5149                 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5150         
5151         emitpLabel(lbl->key);
5152         
5153         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5154         
5155         if(ifx)
5156                 ifx->generated = 1;
5157 #endif
5158 }
5159 #endif
5160
5161 #if 0
5162 /*-----------------------------------------------------------------*/
5163 /* gencjne - compare and jump if not equal                         */
5164 /*-----------------------------------------------------------------*/
5165 static void gencjne(operand *left, operand *right, iCode *ifx)
5166 {
5167         symbol *tlbl  = newiTempLabel(NULL);
5168         
5169         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5170         gencjneshort(left, right, lbl);
5171         
5172         pic14_emitcode("mov","a,%s",one);
5173         pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5174         pic14_emitcode("","%05d_DS_:",lbl->key+100);
5175         pic14_emitcode("clr","a");
5176         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5177         
5178         emitpLabel(lbl->key);
5179         emitpLabel(tlbl->key);
5180         
5181 }
5182 #endif
5183
5184 /*-----------------------------------------------------------------*/
5185 /* genCmpEq - generates code for equal to                          */
5186 /*-----------------------------------------------------------------*/
5187 static void genCmpEq (iCode *ic, iCode *ifx)
5188 {
5189   operand *left, *right, *result;
5190   int size;
5191   symbol *false_label;
5192
5193   FENTRY;
5194   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5195
5196   if(ifx)
5197     DEBUGpic14_emitcode ("; ifx is non-null","");
5198   else
5199     DEBUGpic14_emitcode ("; ifx is null","");
5200
5201   aopOp((left=IC_LEFT(ic)),ic,FALSE);
5202   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5203   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5204
5205   DEBUGpic14_AopType(__LINE__,left,right,result);
5206
5207   /* if literal, move literal to right */ 
5208   if (op_isLitLike (IC_LEFT(ic))) {
5209     operand *tmp = right ;
5210     right = left;
5211     left = tmp;
5212   }
5213
5214   false_label = NULL;
5215   if (ifx && !IC_TRUE(ifx))
5216   {
5217     assert (IC_FALSE(ifx));
5218     false_label = IC_FALSE(ifx);
5219   }
5220
5221   size = min(AOP_SIZE(left),AOP_SIZE(right));
5222   assert(!pic14_sameRegs(AOP(result),AOP(left)));
5223   assert(!pic14_sameRegs(AOP(result),AOP(right)));
5224
5225   /* assume left != right */
5226   {
5227     int i;
5228     for (i=0; i < AOP_SIZE(result); i++)
5229     {
5230       emitpcode(POC_CLRF, popGet(AOP(result),i));
5231     }
5232   }
5233
5234   if (AOP_TYPE(right) == AOP_LIT)
5235   {
5236     unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5237     int i;
5238     size = AOP_SIZE(left);
5239     assert(!op_isLitLike(left));
5240
5241     switch (lit)
5242     {
5243       case 0:
5244         mov2w(AOP(left), 0);
5245         for (i=1; i < size; i++)
5246           emitpcode(POC_IORFW,popGet(AOP(left),i));
5247         /* now Z is set iff `left == right' */
5248         emitSKPZ;
5249         if (!false_label) false_label = newiTempLabel(NULL);
5250         emitpcode(POC_GOTO, popGetLabel(false_label->key));
5251         break;
5252
5253       default:
5254         for (i=0; i < size; i++)
5255         {
5256           mov2w(AOP(left),i);
5257           emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5258           /* now Z is cleared if `left != right' */
5259           emitSKPZ;
5260           if (!false_label) false_label = newiTempLabel(NULL);
5261           emitpcode(POC_GOTO, popGetLabel(false_label->key));
5262         } // for i
5263         break;
5264     } // switch (lit)
5265   }
5266   else
5267   {
5268     /* right is no literal */
5269     int i;
5270
5271     for (i=0; i < size; i++)
5272     {
5273       mov2w(AOP(right),i);
5274       emitpcode(POC_XORFW,popGet(AOP(left),i));
5275       /* now Z is cleared if `left != right' */
5276       emitSKPZ;
5277       if (!false_label) false_label = newiTempLabel(NULL);
5278       emitpcode(POC_GOTO, popGetLabel(false_label->key));
5279     } // for i
5280   }
5281
5282   /* if we reach here, left == right */
5283
5284   if (AOP_SIZE(result) > 0)
5285   {
5286     emitpcode(POC_INCF, popGet(AOP(result),0));
5287   }
5288
5289   if (ifx && IC_TRUE(ifx))
5290   {
5291     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5292   }
5293
5294   if (false_label && (!ifx || IC_TRUE(ifx)))
5295     emitpLabel(false_label->key);
5296
5297   if (ifx) ifx->generated = 1;
5298
5299   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5300   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5301   freeAsmop(result,NULL,ic,TRUE);
5302 }
5303
5304 /*-----------------------------------------------------------------*/
5305 /* ifxForOp - returns the icode containing the ifx for operand     */
5306 /*-----------------------------------------------------------------*/
5307 static iCode *ifxForOp ( operand *op, iCode *ic )
5308 {
5309         FENTRY;
5310         /* if true symbol then needs to be assigned */
5311         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5312         if (IS_TRUE_SYMOP(op))
5313                 return NULL ;
5314         
5315         /* if this has register type condition and
5316         the next instruction is ifx with the same operand
5317         and live to of the operand is upto the ifx only then */
5318         if (ic->next &&
5319                 ic->next->op == IFX &&
5320                 IC_COND(ic->next)->key == op->key &&
5321                 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5322                 return ic->next;
5323         
5324         if (ic->next &&
5325                 ic->next->op == IFX &&
5326                 IC_COND(ic->next)->key == op->key) {
5327                 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5328                 return ic->next;
5329         }
5330         
5331         DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5332         if (ic->next &&
5333                 ic->next->op == IFX)
5334                 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5335         
5336         if (ic->next &&
5337                 ic->next->op == IFX &&
5338                 IC_COND(ic->next)->key == op->key) {
5339                 DEBUGpic14_emitcode ("; "," key is okay");
5340                 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5341                         OP_SYMBOL(op)->liveTo,
5342                         ic->next->seq);
5343         }
5344         
5345         
5346         return NULL;
5347 }
5348 /*-----------------------------------------------------------------*/
5349 /* genAndOp - for && operation                                     */
5350 /*-----------------------------------------------------------------*/
5351 static void genAndOp (iCode *ic)
5352 {
5353         operand *left,*right, *result;
5354         /*     symbol *tlbl; */
5355         
5356         FENTRY;
5357         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5358         /* note here that && operations that are in an
5359         if statement are taken away by backPatchLabels
5360         only those used in arthmetic operations remain */
5361         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5362         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5363         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5364         
5365         DEBUGpic14_AopType(__LINE__,left,right,result);
5366         
5367         emitpcode(POC_MOVFW,popGet(AOP(left),0));
5368         emitpcode(POC_ANDFW,popGet(AOP(right),0));
5369         emitpcode(POC_MOVWF,popGet(AOP(result),0));
5370         
5371         /* if both are bit variables */
5372         /*     if (AOP_TYPE(left) == AOP_CRY && */
5373         /*         AOP_TYPE(right) == AOP_CRY ) { */
5374         /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5375         /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5376         /*         pic14_outBitC(result); */
5377         /*     } else { */
5378         /*         tlbl = newiTempLabel(NULL); */
5379         /*         pic14_toBoolean(left);     */
5380         /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5381         /*         pic14_toBoolean(right); */
5382         /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5383         /*         pic14_outBitAcc(result); */
5384         /*     } */
5385         
5386         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5387         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5388         freeAsmop(result,NULL,ic,TRUE);
5389 }
5390
5391
5392 /*-----------------------------------------------------------------*/
5393 /* genOrOp - for || operation                                      */
5394 /*-----------------------------------------------------------------*/
5395 /*
5396 tsd pic port -
5397 modified this code, but it doesn't appear to ever get called
5398 */
5399
5400 static void genOrOp (iCode *ic)
5401 {
5402         operand *left,*right, *result;
5403         symbol *tlbl;
5404         int i;
5405         
5406         /* note here that || operations that are in an
5407         if statement are taken away by backPatchLabels
5408         only those used in arthmetic operations remain */
5409         FENTRY;
5410         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5411         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5412         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5413         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5414         
5415         DEBUGpic14_AopType(__LINE__,left,right,result);
5416
5417         for (i=0; i < AOP_SIZE(result); i++)
5418         {
5419                 emitpcode(POC_CLRF, popGet(AOP(result), i));
5420         } // for i
5421
5422         tlbl = newiTempLabel(NULL);
5423         pic14_toBoolean(left);
5424         emitSKPZ;
5425         emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5426         pic14_toBoolean(right);
5427         emitpLabel(tlbl->key);
5428         /* here Z is clear IFF `left || right' */
5429         emitSKPZ;
5430         emitpcode(POC_INCF, popGet(AOP(result), 0));
5431         
5432         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5433         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5434         freeAsmop(result,NULL,ic,TRUE);            
5435 }
5436
5437 /*-----------------------------------------------------------------*/
5438 /* isLiteralBit - test if lit == 2^n                               */
5439 /*-----------------------------------------------------------------*/
5440 static int isLiteralBit(unsigned long lit)
5441 {
5442         unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5443                 0x100L,0x200L,0x400L,0x800L,
5444                 0x1000L,0x2000L,0x4000L,0x8000L,
5445                 0x10000L,0x20000L,0x40000L,0x80000L,
5446                 0x100000L,0x200000L,0x400000L,0x800000L,
5447                 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5448                 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5449         int idx;
5450         
5451         FENTRY;
5452         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5453         for(idx = 0; idx < 32; idx++)
5454                 if(lit == pw[idx])
5455                         return idx+1;
5456                 return 0;
5457 }
5458
5459 /*-----------------------------------------------------------------*/
5460 /* continueIfTrue -                                                */
5461 /*-----------------------------------------------------------------*/
5462 static void continueIfTrue (iCode *ic)
5463 {
5464         FENTRY;
5465         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5466         if(IC_TRUE(ic))
5467                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5468         ic->generated = 1;
5469 }
5470
5471 /*-----------------------------------------------------------------*/
5472 /* jmpIfTrue -                                                     */
5473 /*-----------------------------------------------------------------*/
5474 static void jumpIfTrue (iCode *ic)
5475 {
5476         FENTRY;
5477         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5478         if(!IC_TRUE(ic))
5479                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5480         ic->generated = 1;
5481 }
5482
5483 /*-----------------------------------------------------------------*/
5484 /* jmpTrueOrFalse -                                                */
5485 /*-----------------------------------------------------------------*/
5486 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5487 {
5488         FENTRY;
5489         // ugly but optimized by peephole
5490         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5491         if(IC_TRUE(ic)){
5492                 symbol *nlbl = newiTempLabel(NULL);
5493                 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5494                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5495                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5496                 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5497         }
5498         else{
5499                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5500                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5501         }
5502         ic->generated = 1;
5503 }
5504
5505 /*-----------------------------------------------------------------*/
5506 /* genAnd  - code for and                                          */
5507 /*-----------------------------------------------------------------*/
5508 static void genAnd (iCode *ic, iCode *ifx)
5509 {
5510         operand *left, *right, *result;
5511         int size, offset=0;  
5512         unsigned long lit = 0L;
5513         int bytelit = 0;
5514         resolvedIfx rIfx;
5515         
5516         FENTRY;
5517         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5518         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5519         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5520         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5521         
5522         resolveIfx(&rIfx,ifx);
5523         
5524         /* if left is a literal & right is not then exchange them */
5525         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5526                 AOP_NEEDSACC(left)) {
5527                 operand *tmp = right ;
5528                 right = left;
5529                 left = tmp;
5530         }
5531         
5532         /* if result = right then exchange them */
5533         if(pic14_sameRegs(AOP(result),AOP(right))){
5534                 operand *tmp = right ;
5535                 right = left;
5536                 left = tmp;
5537         }
5538         
5539         /* if right is bit then exchange them */
5540         if (AOP_TYPE(right) == AOP_CRY &&
5541                 AOP_TYPE(left) != AOP_CRY){
5542                 operand *tmp = right ;
5543                 right = left;
5544                 left = tmp;
5545         }
5546         if(AOP_TYPE(right) == AOP_LIT)
5547                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5548         
5549         size = AOP_SIZE(result);
5550         
5551         DEBUGpic14_AopType(__LINE__,left,right,result);
5552         
5553         // if(bit & yy)
5554         // result = bit & yy;
5555         if (AOP_TYPE(left) == AOP_CRY){
5556                 // c = bit & literal;
5557                 if(AOP_TYPE(right) == AOP_LIT){
5558                         if(lit & 1) {
5559                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5560                                         // no change
5561                                         goto release;
5562                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5563                         } else {
5564                                 // bit(result) = 0;
5565                                 if(size && (AOP_TYPE(result) == AOP_CRY)){
5566                                         pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5567                                         goto release;
5568                                 }
5569                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5570                                         jumpIfTrue(ifx);
5571                                         goto release;
5572                                 }
5573                                 pic14_emitcode("clr","c");
5574                         }
5575                 } else {
5576                         if (AOP_TYPE(right) == AOP_CRY){
5577                                 // c = bit & bit;
5578                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5579                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5580                         } else {
5581                                 // c = bit & val;
5582                                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5583                                 // c = lsb
5584                                 pic14_emitcode("rrc","a");
5585                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5586                         }
5587                 }
5588                 // bit = c
5589                 // val = c
5590                 if(size)
5591                         pic14_outBitC(result);
5592                 // if(bit & ...)
5593                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5594                         genIfxJump(ifx, "c");           
5595                 goto release ;
5596         }
5597         
5598         // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5599         // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5600         if((AOP_TYPE(right) == AOP_LIT) &&
5601                 (AOP_TYPE(result) == AOP_CRY) &&
5602                 (AOP_TYPE(left) != AOP_CRY)){
5603                 int posbit = isLiteralBit(lit);
5604                 /* left &  2^n */
5605                 if(posbit){
5606                         posbit--;
5607                         //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5608                         // bit = left & 2^n
5609                         if(size)
5610                                 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5611                         // if(left &  2^n)
5612                         else{
5613                                 if(ifx){
5614                                         int offset = 0;
5615                                         while (posbit > 7) {
5616                                                 posbit -= 8;
5617                                                 offset++;
5618                                         }
5619                                         emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5620                                                 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5621                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5622                                         
5623                                         ifx->generated = 1;
5624                                 }
5625                                 goto release;
5626                         }
5627                 } else {
5628                         symbol *tlbl = newiTempLabel(NULL);
5629                         int sizel = AOP_SIZE(left);
5630                         if(size)
5631                                 pic14_emitcode("setb","c");
5632                         while(sizel--){
5633                                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5634                                         MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5635                                         // byte ==  2^n ?
5636                                         if((posbit = isLiteralBit(bytelit)) != 0)
5637                                                 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5638                                         else{
5639                                                 if(bytelit != 0x0FFL)
5640                                                         pic14_emitcode("anl","a,%s",
5641                                                         aopGet(AOP(right),offset,FALSE,TRUE));
5642                                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5643                                         }
5644                                 }
5645                                 offset++;
5646                         }
5647                         // bit = left & literal
5648                         if(size){
5649                                 pic14_emitcode("clr","c");
5650                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5651                         }
5652                         // if(left & literal)
5653                         else{
5654                                 if(ifx)
5655                                         jmpTrueOrFalse(ifx, tlbl);
5656                                 goto release ;
5657                         }
5658                 }
5659                 pic14_outBitC(result);
5660                 goto release ;
5661         }
5662         
5663         /* if left is same as result */
5664         if(pic14_sameRegs(AOP(result),AOP(left))){
5665                 int know_W = -1;
5666                 for(;size--; offset++,lit>>=8) {
5667                         if(AOP_TYPE(right) == AOP_LIT){
5668                                 switch(lit & 0xff) {
5669                                 case 0x00:
5670                                         /*  and'ing with 0 has clears the result */
5671                                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
5672                                         break;
5673                                 case 0xff:
5674                                         /* and'ing with 0xff is a nop when the result and left are the same */
5675                                         break;
5676                                         
5677                                 default:
5678                                         {
5679                                                 int p = my_powof2( (~lit) & 0xff );
5680                                                 if(p>=0) {
5681                                                         /* only one bit is set in the literal, so use a bcf instruction */
5682                                                         emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5683                                                         
5684                                                 } else {
5685                                                         if(know_W != (int)(lit&0xff))
5686                                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5687                                                         know_W = lit &0xff;
5688                                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5689                                                 }
5690                                         }    
5691                                 }
5692                         } else {
5693                                 if (AOP_TYPE(left) == AOP_ACC) {
5694                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5695                                 } else {        
5696                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5697                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5698                                         
5699                                 }
5700                         }
5701                 }
5702                 
5703         } else {
5704                 // left & result in different registers
5705                 if(AOP_TYPE(result) == AOP_CRY){
5706                         // result = bit
5707                         // if(size), result in bit
5708                         // if(!size && ifx), conditional oper: if(left & right)
5709                         symbol *tlbl = newiTempLabel(NULL);
5710                         int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5711                         if(size)
5712                                 pic14_emitcode("setb","c");
5713                         while(sizer--){
5714                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5715                                 pic14_emitcode("anl","a,%s",
5716                                         aopGet(AOP(left),offset,FALSE,FALSE));
5717                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5718                                 offset++;
5719                         }
5720                         if(size){
5721                                 CLRC;
5722                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5723                                 pic14_outBitC(result);
5724                         } else if(ifx)
5725                                 jmpTrueOrFalse(ifx, tlbl);
5726                 } else {
5727                         for(;(size--);offset++) {
5728                                 // normal case
5729                                 // result = left & right
5730                                 if(AOP_TYPE(right) == AOP_LIT){
5731                                         int t = (lit >> (offset*8)) & 0x0FFL;
5732                                         switch(t) { 
5733                                         case 0x00:
5734                                                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5735                                                 break;
5736                                         case 0xff:
5737                                                 if(AOP_TYPE(left) != AOP_ACC) {
5738                                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5739                                                 }
5740                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5741                                                 break;
5742                                         default:
5743                                                 if(AOP_TYPE(left) == AOP_ACC) {
5744                                                         emitpcode(POC_ANDLW, popGetLit(t));
5745                                                 } else {
5746                                                         emitpcode(POC_MOVLW, popGetLit(t));
5747                                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5748                                                 }
5749                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5750                                         }
5751                                         continue;
5752                                 }
5753                                 
5754                                 if (AOP_TYPE(left) == AOP_ACC) {
5755                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5756                                 } else {
5757                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5758                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5759                                 }
5760                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5761                         }
5762                 }
5763         }
5764         
5765 release :
5766         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5767         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5768         freeAsmop(result,NULL,ic,TRUE);     
5769 }
5770
5771 /*-----------------------------------------------------------------*/
5772 /* genOr  - code for or                                            */
5773 /*-----------------------------------------------------------------*/
5774 static void genOr (iCode *ic, iCode *ifx)
5775 {
5776         operand *left, *right, *result;
5777         int size, offset=0;
5778         unsigned long lit = 0L;
5779         
5780         FENTRY;
5781         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5782         
5783         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5784         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5785         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5786         
5787         DEBUGpic14_AopType(__LINE__,left,right,result);
5788         
5789         /* if left is a literal & right is not then exchange them */
5790         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5791                 AOP_NEEDSACC(left)) {
5792                 operand *tmp = right ;
5793                 right = left;
5794                 left = tmp;
5795         }
5796         
5797         /* if result = right then exchange them */
5798         if(pic14_sameRegs(AOP(result),AOP(right))){
5799                 operand *tmp = right ;
5800                 right = left;
5801                 left = tmp;
5802         }
5803         
5804         /* if right is bit then exchange them */
5805         if (AOP_TYPE(right) == AOP_CRY &&
5806                 AOP_TYPE(left) != AOP_CRY){
5807                 operand *tmp = right ;
5808                 right = left;
5809                 left = tmp;
5810         }
5811         
5812         DEBUGpic14_AopType(__LINE__,left,right,result);
5813         
5814         if(AOP_TYPE(right) == AOP_LIT)
5815                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5816         
5817         size = AOP_SIZE(result);
5818         
5819         // if(bit | yy)
5820         // xx = bit | yy;
5821         if (AOP_TYPE(left) == AOP_CRY){
5822                 if(AOP_TYPE(right) == AOP_LIT){
5823                         // c = bit & literal;
5824                         if(lit){
5825                                 // lit != 0 => result = 1
5826                                 if(AOP_TYPE(result) == AOP_CRY){
5827                                         if(size)
5828                                                 emitpcode(POC_BSF, popGet(AOP(result),0));
5829                                         //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5830                                         //   AOP(result)->aopu.aop_dir,
5831                                         //   AOP(result)->aopu.aop_dir);
5832                                         else if(ifx)
5833                                                 continueIfTrue(ifx);
5834                                         goto release;
5835                                 }
5836                         } else {
5837                                 // lit == 0 => result = left
5838                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5839                                         goto release;
5840                                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5841                         }
5842                 } else {
5843                         if (AOP_TYPE(right) == AOP_CRY){
5844                                 if(pic14_sameRegs(AOP(result),AOP(left))){
5845                                         // c = bit | bit;
5846                                         emitpcode(POC_BCF,   popGet(AOP(result),0));
5847                                         emitpcode(POC_BTFSC, popGet(AOP(right),0));
5848                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5849                                         
5850                                         pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5851                                                 AOP(result)->aopu.aop_dir,
5852                                                 AOP(result)->aopu.aop_dir);
5853                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5854                                                 AOP(right)->aopu.aop_dir,
5855                                                 AOP(right)->aopu.aop_dir);
5856                                         pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5857                                                 AOP(result)->aopu.aop_dir,
5858                                                 AOP(result)->aopu.aop_dir);
5859                                 } else {
5860                                         if( AOP_TYPE(result) == AOP_ACC) {
5861                                                 emitpcode(POC_MOVLW, popGetLit(0));
5862                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5863                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5864                                                 emitpcode(POC_MOVLW, popGetLit(1));
5865                                                 
5866                                         } else {
5867                                                 
5868                                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5869                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5870                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5871                                                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5872                                                 
5873                                                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5874                                                         AOP(result)->aopu.aop_dir,
5875                                                         AOP(result)->aopu.aop_dir);
5876                                                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5877                                                         AOP(right)->aopu.aop_dir,
5878                                                         AOP(right)->aopu.aop_dir);
5879                                                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5880                                                         AOP(left)->aopu.aop_dir,
5881                                                         AOP(left)->aopu.aop_dir);
5882                                                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5883                                                         AOP(result)->aopu.aop_dir,
5884                                                         AOP(result)->aopu.aop_dir);
5885                                         }
5886                                 }
5887                         } else {
5888                                 // c = bit | val;
5889                                 symbol *tlbl = newiTempLabel(NULL);
5890                                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5891                                 
5892                                 
5893                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5894                                 if( AOP_TYPE(right) == AOP_ACC) {
5895                                         emitpcode(POC_IORLW, popGetLit(0));
5896                                         emitSKPNZ;
5897                                         emitpcode(POC_BTFSC, popGet(AOP(left),0));
5898                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5899                                 }
5900                                 
5901                                 
5902                                 
5903                                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5904                                         pic14_emitcode(";XXX setb","c");
5905                                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5906                                         AOP(left)->aopu.aop_dir,tlbl->key+100);
5907                                 pic14_toBoolean(right);
5908                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5909                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5910                                         jmpTrueOrFalse(ifx, tlbl);
5911                                         goto release;
5912                                 } else {
5913                                         CLRC;
5914                                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5915                                 }
5916                         }
5917                 }
5918                 // bit = c
5919                 // val = c
5920                 if(size)
5921                         pic14_outBitC(result);
5922                 // if(bit | ...)
5923                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5924                         genIfxJump(ifx, "c");           
5925                 goto release ;
5926         }
5927
5928         // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5929         // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5930         if((AOP_TYPE(right) == AOP_LIT) &&
5931           (AOP_TYPE(result) == AOP_CRY) &&
5932           (AOP_TYPE(left) != AOP_CRY)){
5933                 if(lit){
5934                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5935                         // result = 1
5936                         if(size)
5937                                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5938                         else 
5939                                 continueIfTrue(ifx);
5940                         goto release;
5941                 } else {
5942                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5943                         // lit = 0, result = boolean(left)
5944                         if(size)
5945                                 pic14_emitcode(";XXX setb","c");
5946                         pic14_toBoolean(right);
5947                         if(size){
5948                                 symbol *tlbl = newiTempLabel(NULL);
5949                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5950                                 CLRC;
5951                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5952                         } else {
5953                                 genIfxJump (ifx,"a");
5954                                 goto release;
5955                         }
5956                 }
5957                 pic14_outBitC(result);
5958                 goto release ;
5959         }
5960
5961         /* if left is same as result */
5962         if(pic14_sameRegs(AOP(result),AOP(left))){
5963                 int know_W = -1;
5964                 for(;size--; offset++,lit>>=8) {
5965                         if(AOP_TYPE(right) == AOP_LIT){
5966                                 if((lit & 0xff) == 0)
5967                                         /*  or'ing with 0 has no effect */
5968                                         continue;
5969                                 else {
5970                                         int p = my_powof2(lit & 0xff);
5971                                         if(p>=0) {
5972                                                 /* only one bit is set in the literal, so use a bsf instruction */
5973                                                 emitpcode(POC_BSF,
5974                                                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5975                                         } else {
5976                                                 if(know_W != (int)(lit & 0xff))
5977                                                         emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5978                                                 know_W = lit & 0xff;
5979                                                 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5980                                         }
5981                                         
5982                                 }
5983                         } else {
5984                                 if (AOP_TYPE(left) == AOP_ACC) {
5985                                         emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5986                                         pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5987                                 } else {        
5988                                         emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5989                                         emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5990                                         
5991                                         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5992                                         pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5993                                         
5994                                 }
5995                         }
5996                 }
5997         } else {
5998                 // left & result in different registers
5999                 if(AOP_TYPE(result) == AOP_CRY){
6000                         // result = bit
6001                         // if(size), result in bit
6002                         // if(!size && ifx), conditional oper: if(left | right)
6003                         symbol *tlbl = newiTempLabel(NULL);
6004                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6005                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6006                         
6007                         
6008                         if(size)
6009                                 pic14_emitcode(";XXX setb","c");
6010                         while(sizer--){
6011                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6012                                 pic14_emitcode(";XXX orl","a,%s",
6013                                         aopGet(AOP(left),offset,FALSE,FALSE));
6014                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6015                                 offset++;
6016                         }
6017                         if(size){
6018                                 CLRC;
6019                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6020                                 pic14_outBitC(result);
6021                         } else if(ifx)
6022                                 jmpTrueOrFalse(ifx, tlbl);
6023                 } else for(;(size--);offset++){
6024                         // normal case
6025                         // result = left | right
6026                         if(AOP_TYPE(right) == AOP_LIT){
6027                                 int t = (lit >> (offset*8)) & 0x0FFL;
6028                                 switch(t) { 
6029                                 case 0x00:
6030                                         if (AOP_TYPE(left) != AOP_ACC) {
6031                                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
6032                                         }
6033                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6034                                         
6035                                         break;
6036                                 default:
6037                                         if (AOP_TYPE(left) == AOP_ACC) {
6038                                                 emitpcode(POC_IORLW,  popGetLit(t));
6039                                         } else {
6040                                                 emitpcode(POC_MOVLW,  popGetLit(t));
6041                                                 emitpcode(POC_IORFW,  popGet(AOP(left),offset));
6042                                         }
6043                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));        
6044                                 }
6045                                 continue;
6046                         }
6047                         
6048                         // faster than result <- left, anl result,right
6049                         // and better if result is SFR
6050                         if (AOP_TYPE(left) == AOP_ACC) {
6051                                 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6052                         } else {
6053                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6054                                 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6055                         }
6056                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6057                 }
6058         }
6059
6060 release :
6061         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6062         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6063         freeAsmop(result,NULL,ic,TRUE);     
6064 }
6065
6066 /*-----------------------------------------------------------------*/
6067 /* genXor - code for xclusive or                                   */
6068 /*-----------------------------------------------------------------*/
6069 static void genXor (iCode *ic, iCode *ifx)
6070 {
6071         operand *left, *right, *result;
6072         int size, offset=0;
6073         unsigned long lit = 0L;
6074         
6075         FENTRY;
6076         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6077         
6078         aopOp((left = IC_LEFT(ic)),ic,FALSE);
6079         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6080         aopOp((result=IC_RESULT(ic)),ic,TRUE);
6081         
6082         /* if left is a literal & right is not ||
6083         if left needs acc & right does not */
6084         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6085                 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6086                 operand *tmp = right ;
6087                 right = left;
6088                 left = tmp;
6089         }
6090         
6091         /* if result = right then exchange them */
6092         if(pic14_sameRegs(AOP(result),AOP(right))){
6093                 operand *tmp = right ;
6094                 right = left;
6095                 left = tmp;
6096         }
6097         
6098         /* if right is bit then exchange them */
6099         if (AOP_TYPE(right) == AOP_CRY &&
6100                 AOP_TYPE(left) != AOP_CRY){
6101                 operand *tmp = right ;
6102                 right = left;
6103                 left = tmp;
6104         }
6105         if(AOP_TYPE(right) == AOP_LIT)
6106                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6107         
6108         size = AOP_SIZE(result);
6109         
6110         // if(bit ^ yy)
6111         // xx = bit ^ yy;
6112         if (AOP_TYPE(left) == AOP_CRY){
6113                 if(AOP_TYPE(right) == AOP_LIT){
6114                         // c = bit & literal;
6115                         if(lit>>1){
6116                                 // lit>>1  != 0 => result = 1
6117                                 if(AOP_TYPE(result) == AOP_CRY){
6118                                         if(size)
6119                                         {emitpcode(POC_BSF,  popGet(AOP(result),offset));
6120                                         pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6121                                         else if(ifx)
6122                                                 continueIfTrue(ifx);
6123                                         goto release;
6124                                 }
6125                                 pic14_emitcode("setb","c");
6126                         } else{
6127                                 // lit == (0 or 1)
6128                                 if(lit == 0){
6129                                         // lit == 0, result = left
6130                                         if(size && pic14_sameRegs(AOP(result),AOP(left)))
6131                                                 goto release;
6132                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6133                                 } else{
6134                                         // lit == 1, result = not(left)
6135                                         if(size && pic14_sameRegs(AOP(result),AOP(left))){
6136                                                 emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
6137                                                 emitpcode(POC_XORWF,  popGet(AOP(result),offset));
6138                                                 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6139                                                 goto release;
6140                                         } else {
6141                                                 assert ( !"incomplete genXor" );
6142                                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6143                                                 pic14_emitcode("cpl","c");
6144                                         }
6145                                 }
6146                         }
6147                         
6148                 } else {
6149                         // right != literal
6150                         symbol *tlbl = newiTempLabel(NULL);
6151                         if (AOP_TYPE(right) == AOP_CRY){
6152                                 // c = bit ^ bit;
6153                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6154                         }
6155                         else{
6156                                 int sizer = AOP_SIZE(right);
6157                                 // c = bit ^ val
6158                                 // if val>>1 != 0, result = 1
6159                                 pic14_emitcode("setb","c");
6160                                 while(sizer){
6161                                         MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6162                                         if(sizer == 1)
6163                                                 // test the msb of the lsb
6164                                                 pic14_emitcode("anl","a,#0xfe");
6165                                         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6166                                         sizer--;
6167                                 }
6168                                 // val = (0,1)
6169                                 pic14_emitcode("rrc","a");
6170                         }
6171                         pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6172                         pic14_emitcode("cpl","c");
6173                         pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6174                 }
6175                 // bit = c
6176                 // val = c
6177                 if(size)
6178                         pic14_outBitC(result);
6179                 // if(bit | ...)
6180                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6181                         genIfxJump(ifx, "c");           
6182                 goto release ;
6183         }
6184         
6185         if(pic14_sameRegs(AOP(result),AOP(left))){
6186                 /* if left is same as result */
6187                 for(;size--; offset++) {
6188                         if(AOP_TYPE(right) == AOP_LIT){
6189                                 int t  = (lit >> (offset*8)) & 0x0FFL;
6190                                 if(t == 0x00L)
6191                                         continue;
6192                                 else
6193                                         if (IS_AOP_PREG(left)) {
6194                                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6195                                                 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6196                                                 aopPut(AOP(result),"a",offset);
6197                                         } else {
6198                                                 emitpcode(POC_MOVLW, popGetLit(t));
6199                                                 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6200                                                 pic14_emitcode("xrl","%s,%s",
6201                                                         aopGet(AOP(left),offset,FALSE,TRUE),
6202                                                         aopGet(AOP(right),offset,FALSE,FALSE));
6203                                         }
6204                         } else {
6205                                 if (AOP_TYPE(left) == AOP_ACC)
6206                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6207                                 else {
6208                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6209                                         emitpcode(POC_XORWF,popGet(AOP(left),offset));
6210                                         /*
6211                                         if (IS_AOP_PREG(left)) {
6212                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6213                                         aopPut(AOP(result),"a",offset);
6214                                         } else
6215                                         pic14_emitcode("xrl","%s,a",
6216                                         aopGet(AOP(left),offset,FALSE,TRUE));
6217                                         */
6218                                 }
6219                         }
6220                 }
6221         } else {
6222                 // left & result in different registers
6223                 if(AOP_TYPE(result) == AOP_CRY){
6224                         // result = bit
6225                         // if(size), result in bit
6226                         // if(!size && ifx), conditional oper: if(left ^ right)
6227                         symbol *tlbl = newiTempLabel(NULL);
6228                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6229                         if(size)
6230                                 pic14_emitcode("setb","c");
6231                         while(sizer--){
6232                                 if((AOP_TYPE(right) == AOP_LIT) &&
6233                                         (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6234                                         MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6235                                 } else {
6236                                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6237                                         pic14_emitcode("xrl","a,%s",
6238                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6239                                 }
6240                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6241                                 offset++;
6242                         }
6243                         if(size){
6244                                 CLRC;
6245                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6246                                 pic14_outBitC(result);
6247                         } else if(ifx)
6248                                 jmpTrueOrFalse(ifx, tlbl);
6249                 } else for(;(size--);offset++){
6250                         // normal case
6251                         // result = left & right
6252                         if(AOP_TYPE(right) == AOP_LIT){
6253                                 int t = (lit >> (offset*8)) & 0x0FFL;
6254                                 switch(t) { 
6255                                 case 0x00:
6256                                         if (AOP_TYPE(left) != AOP_ACC) {
6257                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6258                                         }
6259                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6260                                         pic14_emitcode("movf","%s,w",
6261                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6262                                         pic14_emitcode("movwf","%s",
6263                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6264                                         break;
6265                                 case 0xff:
6266                                         if (AOP_TYPE(left) == AOP_ACC) {
6267                                                 emitpcode(POC_XORLW, popGetLit(t));
6268                                         } else {
6269                                                 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6270                                         }
6271                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6272                                         break;
6273                                 default:
6274                                         if (AOP_TYPE(left) == AOP_ACC) {
6275                                                 emitpcode(POC_XORLW, popGetLit(t));
6276                                         } else {
6277                                                 emitpcode(POC_MOVLW, popGetLit(t));
6278                                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6279                                         }
6280                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6281                                         pic14_emitcode("movlw","0x%x",t);
6282                                         pic14_emitcode("xorwf","%s,w",
6283                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6284                                         pic14_emitcode("movwf","%s",
6285                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6286                                         
6287                                 }
6288                                 continue;
6289                         }
6290                         
6291                         // faster than result <- left, anl result,right
6292                         // and better if result is SFR
6293                         if (AOP_TYPE(left) == AOP_ACC) {
6294                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6295                         } else {
6296                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6297                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6298                         }
6299                         if ( AOP_TYPE(result) != AOP_ACC){
6300                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6301                         }
6302                 }
6303         }
6304         
6305 release :
6306         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6307         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6308         freeAsmop(result,NULL,ic,TRUE);     
6309 }
6310
6311 /*-----------------------------------------------------------------*/
6312 /* genInline - write the inline code out                           */
6313 /*-----------------------------------------------------------------*/
6314 static void genInline (iCode *ic)
6315 {
6316   char *buffer, *bp, *bp1;
6317
6318   FENTRY;
6319   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6320
6321   _G.inLine += (!options.asmpeep);
6322
6323   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6324   strcpy(buffer,IC_INLINE(ic));
6325
6326   /* emit each line as a code */
6327   while (*bp) {
6328     if (*bp == '\n') {
6329       *bp++ = '\0';
6330       
6331       if(*bp1)
6332         addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6333       bp1 = bp;
6334     } else {
6335       if (*bp == ':') {
6336         bp++;
6337         *bp = '\0';
6338         bp++;
6339
6340         /* print label, use this special format with NULL directive
6341          * to denote that the argument should not be indented with tab */
6342         addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6343
6344         bp1 = bp;
6345       } else
6346         bp++;
6347     }
6348   }
6349   if ((bp1 != bp) && *bp1)
6350     addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6351
6352   Safe_free(buffer);
6353
6354   _G.inLine -= (!options.asmpeep);
6355 }
6356
6357 /*-----------------------------------------------------------------*/
6358 /* genRRC - rotate right with carry                                */
6359 /*-----------------------------------------------------------------*/
6360 static void genRRC (iCode *ic)
6361 {
6362         operand *left , *result ;
6363         int size, offset = 0, same;
6364         
6365         FENTRY;
6366         /* rotate right with carry */
6367         left = IC_LEFT(ic);
6368         result=IC_RESULT(ic);
6369         aopOp (left,ic,FALSE);
6370         aopOp (result,ic,FALSE);
6371         
6372         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6373         
6374         same = pic14_sameRegs(AOP(result),AOP(left));
6375         
6376         size = AOP_SIZE(result);    
6377         
6378         /* get the lsb and put it into the carry */
6379         emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6380         
6381         offset = 0 ;
6382         
6383         while(size--) {
6384                 
6385                 if(same) {
6386                         emitpcode(POC_RRF, popGet(AOP(left),offset));
6387                 } else {
6388                         emitpcode(POC_RRFW, popGet(AOP(left),offset));
6389                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6390                 }
6391                 
6392                 offset++;
6393         }
6394         
6395         freeAsmop(left,NULL,ic,TRUE);
6396         freeAsmop(result,NULL,ic,TRUE);
6397 }
6398
6399 /*-----------------------------------------------------------------*/
6400 /* genRLC - generate code for rotate left with carry               */
6401 /*-----------------------------------------------------------------*/
6402 static void genRLC (iCode *ic)
6403 {    
6404         operand *left , *result ;
6405         int size, offset = 0;
6406         int same;
6407         
6408         FENTRY;
6409         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6410         /* rotate right with carry */
6411         left = IC_LEFT(ic);
6412         result=IC_RESULT(ic);
6413         aopOp (left,ic,FALSE);
6414         aopOp (result,ic,FALSE);
6415         
6416         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6417         
6418         same = pic14_sameRegs(AOP(result),AOP(left));
6419         
6420         /* move it to the result */
6421         size = AOP_SIZE(result);    
6422         
6423         /* get the msb and put it into the carry */
6424         emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6425         
6426         offset = 0 ;
6427         
6428         while(size--) {
6429                 
6430                 if(same) {
6431                         emitpcode(POC_RLF, popGet(AOP(left),offset));
6432                 } else {
6433                         emitpcode(POC_RLFW, popGet(AOP(left),offset));
6434                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6435                 }
6436                 
6437                 offset++;
6438         }
6439         
6440         
6441         freeAsmop(left,NULL,ic,TRUE);
6442         freeAsmop(result,NULL,ic,TRUE);
6443 }
6444
6445 /*-----------------------------------------------------------------*/
6446 /* genGetHbit - generates code get highest order bit               */
6447 /*-----------------------------------------------------------------*/
6448 static void genGetHbit (iCode *ic)
6449 {
6450         operand *left, *result;
6451         left = IC_LEFT(ic);
6452         result=IC_RESULT(ic);
6453         aopOp (left,ic,FALSE);
6454         aopOp (result,ic,FALSE);
6455         
6456         FENTRY;
6457         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6458         /* get the highest order byte into a */
6459         MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6460         if(AOP_TYPE(result) == AOP_CRY){
6461                 pic14_emitcode("rlc","a");
6462                 pic14_outBitC(result);
6463         }
6464         else{
6465                 pic14_emitcode("rl","a");
6466                 pic14_emitcode("anl","a,#0x01");
6467                 pic14_outAcc(result);
6468         }
6469         
6470         
6471         freeAsmop(left,NULL,ic,TRUE);
6472         freeAsmop(result,NULL,ic,TRUE);
6473 }
6474
6475 /*-----------------------------------------------------------------*/
6476 /* AccLsh - shift left accumulator by known count                  */
6477 /* MARK: pic14 always rotates through CARRY!                       */
6478 /*-----------------------------------------------------------------*/
6479 static void AccLsh (pCodeOp *pcop,int shCount)
6480 {
6481         FENTRY;
6482         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6483         shCount &= 0x0007;              // shCount : 0..7
6484         switch(shCount){
6485         case 0 :
6486                 return;
6487                 break;
6488         case 1 :
6489                 emitCLRC;
6490                 emitpcode(POC_RLF,pcop);
6491                 return;
6492                 break;
6493         case 2 :
6494                 emitpcode(POC_RLF,pcop);
6495                 emitpcode(POC_RLF,pcop);
6496                 break;
6497         case 3 :
6498                 emitpcode(POC_RLF,pcop);
6499                 emitpcode(POC_RLF,pcop);
6500                 emitpcode(POC_RLF,pcop);
6501                 break;
6502         case 4 :
6503                 emitpcode(POC_SWAPF,pcop);
6504                 break;
6505         case 5 :
6506                 emitpcode(POC_SWAPF,pcop);
6507                 emitpcode(POC_RLF,pcop);
6508                 break;
6509         case 6 :
6510                 emitpcode(POC_SWAPF,pcop);
6511                 emitpcode(POC_RLF,pcop);
6512                 emitpcode(POC_RLF,pcop);
6513                 break;
6514         case 7 :
6515                 emitpcode(POC_RRFW,pcop);
6516                 emitpcode(POC_RRF,pcop);
6517                 break;
6518         }
6519         /* clear invalid bits */
6520         emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6521         emitpcode(POC_ANDWF, pcop);
6522 }
6523
6524 /*-----------------------------------------------------------------*/
6525 /* AccRsh - shift right accumulator by known count                 */
6526 /* MARK: pic14 always rotates through CARRY!                       */
6527 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6528 /*            1: mask out invalid bits (zero-extend)               */
6529 /*            2: sign-extend result (pretty slow)                  */
6530 /*-----------------------------------------------------------------*/
6531 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6532 {
6533         FENTRY;
6534         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6535         shCount &= 0x0007;              // shCount : 0..7
6536         switch(shCount){
6537         case 0 :
6538                 return;
6539                 break;
6540         case 1 :
6541                 /* load sign if needed */
6542                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6543                 else if (mask_mode == 1) emitCLRC;
6544                 emitpcode(POC_RRF,pcop);
6545                 return;
6546                 break;
6547         case 2 :
6548                 /* load sign if needed */
6549                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6550                 emitpcode(POC_RRF,pcop);
6551                 /* load sign if needed */
6552                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6553                 emitpcode(POC_RRF,pcop);
6554                 if (mask_mode == 2) return;
6555                 break;
6556         case 3 :
6557                 /* load sign if needed */
6558                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6559                 emitpcode(POC_RRF,pcop);
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                 if (mask_mode == 2) return;
6567                 break;
6568         case 4 :
6569                 emitpcode(POC_SWAPF,pcop);
6570                 break;
6571         case 5 :
6572                 emitpcode(POC_SWAPF,pcop);
6573                 emitpcode(POC_RRF,pcop);
6574                 break;
6575         case 6 :
6576                 emitpcode(POC_SWAPF,pcop);
6577                 emitpcode(POC_RRF,pcop);
6578                 emitpcode(POC_RRF,pcop);
6579                 break;
6580         case 7 :
6581                 if (mask_mode == 2)
6582                 {
6583                         /* load sign */
6584                         emitpcode(POC_RLFW,pcop);
6585                         emitpcode(POC_CLRF,pcop);
6586                         emitSKPNC;
6587                         emitpcode(POC_COMF,pcop);
6588                         return;
6589                 } else {
6590                         emitpcode(POC_RLFW,pcop);
6591                         emitpcode(POC_RLF,pcop);
6592                 }
6593                 break;
6594         }
6595
6596         if (mask_mode == 0)
6597         {
6598                 /* leave invalid bits undefined */
6599                 return;
6600         }
6601         
6602         /* clear invalid bits -- zero-extend */
6603         emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6604         emitpcode(POC_ANDWF, pcop);
6605
6606         if (mask_mode == 2) {
6607           /* sign-extend */
6608           emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6609           emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6610           emitpcode(POC_IORWF, pcop);
6611         }
6612 }
6613
6614 #if 0
6615 /*-----------------------------------------------------------------*/
6616 /* AccSRsh - signed right shift accumulator by known count                 */
6617 /*-----------------------------------------------------------------*/
6618 static void AccSRsh (int shCount)
6619 {
6620         symbol *tlbl ;
6621         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6622         if(shCount != 0){
6623                 if(shCount == 1){
6624                         pic14_emitcode("mov","c,acc.7");
6625                         pic14_emitcode("rrc","a");
6626                 } else if(shCount == 2){
6627                         pic14_emitcode("mov","c,acc.7");
6628                         pic14_emitcode("rrc","a");
6629                         pic14_emitcode("mov","c,acc.7");
6630                         pic14_emitcode("rrc","a");
6631                 } else {
6632                         tlbl = newiTempLabel(NULL);
6633                         /* rotate right accumulator */
6634                         AccRol(8 - shCount);
6635                         /* and kill the higher order bits */
6636                         pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6637                         pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6638                         pic14_emitcode("orl","a,#0x%02x",
6639                                 (unsigned char)~SRMask[shCount]);
6640                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6641                 }
6642         }
6643 }
6644
6645 /*-----------------------------------------------------------------*/
6646 /* shiftR1Left2Result - shift right one byte from left to result   */
6647 /*-----------------------------------------------------------------*/
6648 static void shiftR1Left2ResultSigned (operand *left, int offl,
6649                                                                           operand *result, int offr,
6650                                                                           int shCount)
6651 {
6652         int same;
6653         
6654         FENTRY;
6655         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6656         
6657         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6658         
6659         switch(shCount) {
6660         case 1:
6661                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6662                 if(same) 
6663                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6664                 else {
6665                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6666                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6667                 }
6668                 
6669                 break;
6670         case 2:
6671                 
6672                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6673                 if(same) 
6674                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6675                 else {
6676                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6677                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6678                 }
6679                 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6680                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6681                 
6682                 break;
6683                 
6684         case 3:
6685                 if(same)
6686                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6687                 else {
6688                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6689                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6690                 }
6691                 
6692                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6693                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6694                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6695                 
6696                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6697                 emitpcode(POC_IORLW, popGetLit(0xe0));
6698                 
6699                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6700                 break;
6701                 
6702         case 4:
6703                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6704                 emitpcode(POC_ANDLW,  popGetLit(0x0f));
6705                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6706                 emitpcode(POC_IORLW,  popGetLit(0xf0));
6707                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6708                 break;
6709         case 5:
6710                 if(same) {
6711                         emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6712                 } else {
6713                         emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6714                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6715                 }
6716                 emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6717                 emitpcode(POC_ANDLW,  popGetLit(0x07));
6718                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6719                 emitpcode(POC_IORLW,  popGetLit(0xf8));
6720                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6721                 break;
6722                 
6723         case 6:
6724                 if(same) {
6725                         emitpcode(POC_MOVLW, popGetLit(0x00));
6726                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6727                         emitpcode(POC_MOVLW, popGetLit(0xfe));
6728                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6729                         emitpcode(POC_IORLW, popGetLit(0x01));
6730                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6731                 } else {
6732                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6733                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6734                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6735                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6736                         emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6737                 }
6738                 break;
6739                 
6740         case 7:
6741                 if(same) {
6742                         emitpcode(POC_MOVLW, popGetLit(0x00));
6743                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6744                         emitpcode(POC_MOVLW, popGetLit(0xff));
6745                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6746                 } else {
6747                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6748                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6749                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6750                 }
6751                 
6752         default:
6753                 break;
6754         }
6755 }
6756
6757 /*-----------------------------------------------------------------*/
6758 /* shiftR1Left2Result - shift right one byte from left to result   */
6759 /*-----------------------------------------------------------------*/
6760 static void shiftR1Left2Result (operand *left, int offl,
6761                                                                 operand *result, int offr,
6762                                                                 int shCount, int sign)
6763 {
6764         int same;
6765         
6766         FENTRY;
6767         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6768         
6769         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6770         
6771         /* Copy the msb into the carry if signed. */
6772         if(sign) {
6773                 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6774                 return;
6775         }
6776         
6777         
6778         
6779         switch(shCount) {
6780         case 1:
6781                 emitCLRC;
6782                 if(same) 
6783                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6784                 else {
6785                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6786                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6787                 }
6788                 break;
6789         case 2:
6790                 emitCLRC;
6791                 if(same) {
6792                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6793                 } else {
6794                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6795                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6796                 }
6797                 emitCLRC;
6798                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6799                 
6800                 break;
6801         case 3:
6802                 if(same)
6803                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6804                 else {
6805                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6806                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6807                 }
6808                 
6809                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6810                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6811                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6812                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6813                 break;
6814                 
6815         case 4:
6816                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6817                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6818                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6819                 break;
6820                 
6821         case 5:
6822                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6823                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6824                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6825                 emitCLRC;
6826                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6827                 
6828                 break;
6829         case 6:
6830                 
6831                 emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6832                 emitpcode(POC_ANDLW, popGetLit(0x80));
6833                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6834                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6835                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6836                 break;
6837                 
6838         case 7:
6839                 
6840                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6841                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6842                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6843                 
6844                 break;
6845                 
6846         default:
6847                 break;
6848         }
6849 }
6850
6851 /*-----------------------------------------------------------------*/
6852 /* shiftL1Left2Result - shift left one byte from left to result    */
6853 /*-----------------------------------------------------------------*/
6854 static void shiftL1Left2Result (operand *left, int offl,
6855                                                                 operand *result, int offr, int shCount)
6856 {
6857         int same;
6858         
6859         //    char *l;
6860         FENTRY;
6861         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6862         
6863         same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6864         DEBUGpic14_emitcode ("; ***","same =  %d",same);
6865         //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6866         //    MOVA(l);
6867         /* shift left accumulator */
6868         //AccLsh(shCount); // don't comment out just yet...
6869         //    aopPut(AOP(result),"a",offr);
6870         
6871         switch(shCount) {
6872         case 1:
6873                 /* Shift left 1 bit position */
6874                 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6875                 if(same) {
6876                         emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6877                 } else {
6878                         emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6879                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6880                 }
6881                 break;
6882         case 2:
6883                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6884                 emitpcode(POC_ANDLW,popGetLit(0x7e));
6885                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6886                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6887                 break;
6888         case 3:
6889                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6890                 emitpcode(POC_ANDLW,popGetLit(0x3e));
6891                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6892                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6893                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6894                 break;
6895         case 4:
6896                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6897                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6898                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6899                 break;
6900         case 5:
6901                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6902                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6903                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6904                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6905                 break;
6906         case 6:
6907                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6908                 emitpcode(POC_ANDLW, popGetLit(0x30));
6909                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6910                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6911                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6912                 break;
6913         case 7:
6914                 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6915                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6916                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6917                 break;
6918                 
6919         default:
6920                 DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6921         }
6922         
6923 }
6924 #endif
6925
6926 /*-----------------------------------------------------------------*/
6927 /* movLeft2Result - move byte from left to result                  */
6928 /*-----------------------------------------------------------------*/
6929 static void movLeft2Result (operand *left, int offl,
6930                                                         operand *result, int offr)
6931 {
6932         char *l;
6933         FENTRY;
6934         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6935         if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6936                 l = aopGet(AOP(left),offl,FALSE,FALSE);
6937                 
6938                 if (*l == '@' && (IS_AOP_PREG(result))) {
6939                         pic14_emitcode("mov","a,%s",l);
6940                         aopPut(AOP(result),"a",offr);
6941                 } else {
6942                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6943                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6944                 }
6945         }
6946 }
6947
6948 /*-----------------------------------------------------------------*/
6949 /* shiftLeft_Left2ResultLit - shift left by known count            */
6950 /*-----------------------------------------------------------------*/
6951
6952 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6953 {
6954         int size, same, offr, i;
6955
6956         size = AOP_SIZE(left);
6957         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6958         
6959         same = pic14_sameRegs (AOP(left), AOP(result));
6960         
6961         offr = shCount / 8;
6962         shCount = shCount & 0x07;
6963
6964         size -= offr;
6965
6966         switch (shCount)
6967         {
6968         case 0: /* takes 0 or 2N cycles (for offr==0) */
6969                 if (!same || offr) {
6970                         for (i=size-1; i >= 0; i--)
6971                                 movLeft2Result (left, i, result, offr + i);
6972                 } // if
6973                 break;
6974                 
6975         case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6976                 if (same && offr) {
6977                         shiftLeft_Left2ResultLit (left, result, 8 * offr);
6978                         shiftLeft_Left2ResultLit (result, result, shCount);
6979                         return; /* prevent clearing result again */
6980                 } else {
6981                         emitCLRC;
6982                         for (i=0; i < size; i++) {
6983                                 if (same && !offr) {
6984                                         emitpcode (POC_RLF, popGet (AOP(left), i));
6985                                 } else {
6986                                         emitpcode (POC_RLFW, popGet (AOP(left), i));
6987                                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6988                                 } // if
6989                         } // for
6990                 } // if (offr)
6991                 break;
6992                 
6993         case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6994                 /* works in-place/with offr as well */
6995                 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6996                 emitpcode (POC_ANDLW, popGetLit (0xF0));
6997                 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6998
6999                 for (i = size - 2; i >= 0; i--)
7000                 {
7001                         emitpcode (POC_SWAPFW, popGet (AOP(left), i));
7002                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7003                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7004                         emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
7005                         emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
7006                 } // for i
7007                 break;
7008                 
7009         case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7010                 /* works in-place/with offr as well */
7011                 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7012                 for (i = size-2; i >= 0; i--) {
7013                         emitpcode (POC_RRFW, popGet (AOP(left), i));
7014                         emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7015                 } // for i
7016                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7017                 emitpcode (POC_RRF, popGet (AOP(result), offr));
7018                 break;
7019         
7020         default:
7021                 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7022                 shiftLeft_Left2ResultLit (result, result, 1);
7023                 return; /* prevent clearing result again */
7024                 break;
7025         } // switch
7026
7027         while (0 < offr--)
7028         {
7029                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7030         } // while
7031 }
7032
7033 /*-----------------------------------------------------------------*/
7034 /* shiftRight_Left2ResultLit - shift right by known count          */
7035 /*-----------------------------------------------------------------*/
7036
7037 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7038 {
7039         int size, same, offr, i;
7040
7041         size = AOP_SIZE(left);
7042         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7043         
7044         same = pic14_sameRegs (AOP(left), AOP(result));
7045         
7046         offr = shCount / 8;
7047         shCount = shCount & 0x07;
7048
7049         size -= offr;
7050
7051         if (size)
7052         {
7053                 switch (shCount)
7054                 {
7055                 case 0: /* takes 0 or 2N cycles (for offr==0) */
7056                         if (!same || offr) {
7057                                 for (i=0; i < size; i++)
7058                                         movLeft2Result (left, i + offr, result, i);
7059                         } // if
7060                         break;
7061                         
7062                 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7063                         emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7064                         if (same && offr) {
7065                                 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7066                                 shiftRight_Left2ResultLit (result, result, shCount, sign);
7067                                 return; /* prevent sign-extending result again */
7068                         } else {
7069                                 emitCLRC;
7070                                 if (sign) {
7071                                         emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7072                                         emitSETC;
7073                                 }
7074                                 for (i = size-1; i >= 0; i--) {
7075                                         if (same && !offr) {
7076                                                 emitpcode (POC_RRF, popGet (AOP(left), i));
7077                                         } else {
7078                                                 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7079                                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7080                                         }
7081                                 } // for i
7082                         } // if (offr)
7083                         break;
7084                         
7085                 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7086                         /* works in-place/with offr as well */
7087                         emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7088                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7089                         emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7090
7091                         for (i = 1; i < size; i++)
7092                         {
7093                                 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7094                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7095                                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7096                                 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7097                                 emitpcode (POC_XORWF, popGet (AOP(result), i));
7098                         } // for i
7099
7100                         if (sign)
7101                         {
7102                                 emitpcode (POC_MOVLW, popGetLit (0xF0));
7103                                 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7104                                 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7105                         } // if
7106                         break;
7107                         
7108                 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7109                         /* works in-place/with offr as well */
7110                         emitpcode (POC_RLFW, popGet (AOP(left), offr));
7111                         for (i = 0; i < size-1; i++) {
7112                                 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7113                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7114                         } // for i
7115                         emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7116                         if (!sign) {
7117                                 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7118                         } else {
7119                                 emitSKPNC;
7120                                 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7121                         }
7122                         break;
7123                 
7124                 default:
7125                         shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7126                         shiftRight_Left2ResultLit (result, result, 1, sign);
7127                         return; /* prevent sign extending result again */
7128                         break;
7129                 } // switch
7130         } // if
7131
7132         addSign (result, size, sign);
7133 }
7134
7135 #if 0
7136 /*-----------------------------------------------------------------*/
7137 /* shiftL2Left2Result - shift left two bytes from left to result   */
7138 /*-----------------------------------------------------------------*/
7139 static void shiftL2Left2Result (operand *left, int offl,
7140                                                                 operand *result, int offr, int shCount)
7141 {
7142         FENTRY;
7143         
7144         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7145         
7146         if(pic14_sameRegs(AOP(result), AOP(left))) {
7147                 switch(shCount) {
7148                 case 0:
7149                         break;
7150                 case 1:
7151                 case 2:
7152                 case 3:
7153                         
7154                         emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7155                         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7156                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7157                         
7158                         while(--shCount) {
7159                                 emitCLRC;
7160                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7161                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7162                         }
7163                         
7164                         break;
7165                 case 4:
7166                 case 5:
7167                         emitpcode(POC_MOVLW, popGetLit(0x0f));
7168                         emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7169                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7170                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7171                         emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7172                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7173                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7174                         if(shCount >=5) {
7175                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7176                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7177                         }
7178                         break;
7179                 case 6:
7180                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7181                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7182                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7183                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7184                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7185                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7186                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7187                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7188                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7189                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7190                         break;
7191                 case 7:
7192                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7193                         emitpcode(POC_RRFW, popGet(AOP(result),offr));
7194                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7195                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7196                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7197                 }
7198                 
7199         } else {
7200                 switch(shCount) {
7201                 case 0:
7202                         break;
7203                 case 1:
7204                 case 2:
7205                 case 3:
7206                 /* note, use a mov/add for the shift since the mov has a
7207                         chance of getting optimized out */
7208                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7209                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7210                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7211                         emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
7212                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7213                         
7214                         while(--shCount) {
7215                                 emitCLRC;
7216                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7217                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7218                         }
7219                         break;
7220                         
7221                 case 4:
7222                 case 5:
7223                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7224                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7225                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7226                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7227                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7228                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7229                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7230                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7231                         
7232                         
7233                         if(shCount == 5) {
7234                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7235                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7236                         }
7237                         break;
7238                 case 6:
7239                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7240                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7241                         emitpcode(POC_RRFW, popGet(AOP(result),offl));
7242                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
7243                         
7244                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7245                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7246                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7247                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7248                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7249                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7250                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7251                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7252                         break;
7253                 case 7:
7254                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7255                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7256                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7257                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7258                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7259                 }
7260         }
7261         
7262 }
7263
7264 /*-----------------------------------------------------------------*/
7265 /* shiftR2Left2Result - shift right two bytes from left to result  */
7266 /*-----------------------------------------------------------------*/
7267 static void shiftR2Left2Result (operand *left, int offl,
7268                                                                 operand *result, int offr,
7269                                                                 int shCount, int sign)
7270 {
7271         int same=0;
7272         
7273         FENTRY;
7274         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7275         same = pic14_sameRegs(AOP(result), AOP(left));
7276         
7277         if(same && ((offl + MSB16) == offr)){
7278                 same=1;
7279                 /* don't crash result[offr] */
7280                 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7281                 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7282         }
7283         /* else {
7284         movLeft2Result(left,offl, result, offr);
7285         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7286         }
7287         */
7288         /* a:x >> shCount (x = lsb(result))*/
7289         /*
7290         if(sign)
7291         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7292         else {
7293         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7294         */
7295         switch(shCount) {
7296         case 0:
7297                 break;
7298         case 1:
7299         case 2:
7300         case 3:
7301                 if(sign)
7302                         emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7303                 else
7304                         emitCLRC;
7305                 
7306                 if(same) {
7307                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7308                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7309                 } else {
7310                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7311                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7312                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7313                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7314                 }
7315                 
7316                 while(--shCount) {
7317                         if(sign)
7318                                 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7319                         else
7320                                 emitCLRC;
7321                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7322                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7323                 }
7324                 break;
7325         case 4:
7326         case 5:
7327                 if(same) {
7328                         
7329                         emitpcode(POC_MOVLW, popGetLit(0xf0));
7330                         emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7331                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7332                         
7333                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7334                         emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7335                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7336                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7337                 } else {
7338                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7339                         emitpcode(POC_ANDLW, popGetLit(0x0f));
7340                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7341                         
7342                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7343                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7344                         emitpcode(POC_ANDLW, popGetLit(0xf0));
7345                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7346                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7347                 }
7348                 
7349                 if(shCount >=5) {
7350                         emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7351                         emitpcode(POC_RRF, popGet(AOP(result),offr));
7352                 }
7353                 
7354                 if(sign) {
7355                         emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7356                         emitpcode(POC_BTFSC, 
7357                                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7358                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7359                 }
7360                 
7361                 break;
7362                 
7363         case 6:
7364                 if(same) {
7365                         
7366                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7367                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7368                         
7369                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7370                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7371                         emitpcode(POC_RLFW, popGet(AOP(result),offr));
7372                         emitpcode(POC_ANDLW,popGetLit(0x03));
7373                         if(sign) {
7374                                 emitpcode(POC_BTFSC, 
7375                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7376                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7377                         }
7378                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7379                         emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7380                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7381                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7382                 } else {
7383                         emitpcode(POC_RLFW, popGet(AOP(left),offl));
7384                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7385                         emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7386                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7387                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7388                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7389                         emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7390                         emitpcode(POC_ANDLW,popGetLit(0x03));
7391                         if(sign) {
7392                                 emitpcode(POC_BTFSC, 
7393                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7394                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7395                         }
7396                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7397                         //emitpcode(POC_RLF,  popGet(AOP(result),offr));
7398                         
7399                         
7400                 }
7401                 
7402                 break;
7403         case 7:
7404                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7405                 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7406                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7407                 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7408                 if(sign) {
7409                         emitSKPNC;
7410                         emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7411                 } else 
7412                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7413   }
7414 }
7415
7416 /*-----------------------------------------------------------------*/
7417 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7418 /*-----------------------------------------------------------------*/
7419 static void shiftLLeftOrResult (operand *left, int offl,
7420                                                                 operand *result, int offr, int shCount)
7421 {
7422         FENTRY;
7423         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7424         
7425         /* shift left accumulator */
7426         AccLsh(left,offl,shCount);
7427         /* or with result */
7428         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7429         assert ( !"broken (modifies left, fails for left==result))" );
7430 }
7431
7432 /*-----------------------------------------------------------------*/
7433 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7434 /*-----------------------------------------------------------------*/
7435 static void shiftRLeftOrResult (operand *left, int offl,
7436                                                                 operand *result, int offr, int shCount)
7437 {
7438         FENTRY;
7439         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7440         
7441         /* shift right accumulator */
7442         AccRsh(left,offl,shCount);
7443         /* or with result */
7444         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7445         assert ( !"broken (modifies left, fails for left==result))" );
7446 }
7447
7448 /*-----------------------------------------------------------------*/
7449 /* genlshOne - left shift a one byte quantity by known count       */
7450 /*-----------------------------------------------------------------*/
7451 static void genlshOne (operand *result, operand *left, int shCount)
7452 {       
7453         FENTRY;
7454         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7455         shiftL1Left2Result(left, LSB, result, LSB, shCount);
7456 }
7457
7458 /*-----------------------------------------------------------------*/
7459 /* genlshTwo - left shift two bytes by known amount != 0           */
7460 /*-----------------------------------------------------------------*/
7461 static void genlshTwo (operand *result,operand *left, int shCount)
7462 {
7463         int size;
7464         
7465         FENTRY;
7466         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7467         size = pic14_getDataSize(result);
7468         
7469         /* if shCount >= 8 */
7470         if (shCount >= 8) {
7471                 shCount -= 8 ;
7472                 
7473                 if (size > 1){
7474                         if (shCount)
7475                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7476                         else 
7477                                 movLeft2Result(left, LSB, result, MSB16);
7478                 }
7479                 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7480         }
7481         
7482         /*  1 <= shCount <= 7 */
7483         else {  
7484                 if(size == 1)
7485                         shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7486                 else 
7487                         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7488         }
7489 }
7490
7491 /*-----------------------------------------------------------------*/
7492 /* shiftLLong - shift left one long from left to result            */
7493 /* offl = LSB or MSB16                                             */
7494 /*-----------------------------------------------------------------*/
7495 static void shiftLLong (operand *left, operand *result, int offr )
7496 {
7497         char *l;
7498         int size = AOP_SIZE(result);
7499         
7500         FENTRY;
7501         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7502         if(size >= LSB+offr){
7503                 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7504                 MOVA(l);
7505                 pic14_emitcode("add","a,acc");
7506                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7507                         size >= MSB16+offr && offr != LSB )
7508                         pic14_emitcode("xch","a,%s",
7509                         aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7510                 else      
7511                         aopPut(AOP(result),"a",LSB+offr);
7512         }
7513         
7514         if(size >= MSB16+offr){
7515                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7516                         l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7517                         MOVA(l);
7518                 }
7519                 pic14_emitcode("rlc","a");
7520                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7521                         size >= MSB24+offr && offr != LSB)
7522                         pic14_emitcode("xch","a,%s",
7523                         aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7524                 else      
7525                         aopPut(AOP(result),"a",MSB16+offr);
7526         }
7527         
7528         if(size >= MSB24+offr){
7529                 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7530                         l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7531                         MOVA(l);
7532                 }
7533                 pic14_emitcode("rlc","a");
7534                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7535                         size >= MSB32+offr && offr != LSB )
7536                         pic14_emitcode("xch","a,%s",
7537                         aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7538                 else      
7539                         aopPut(AOP(result),"a",MSB24+offr);
7540         }
7541         
7542         if(size > MSB32+offr){
7543                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7544                         l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7545                         MOVA(l);  
7546                 }
7547                 pic14_emitcode("rlc","a");
7548                 aopPut(AOP(result),"a",MSB32+offr);
7549         }
7550         if(offr != LSB)
7551                 aopPut(AOP(result),zero,LSB);       
7552 }
7553
7554 /*-----------------------------------------------------------------*/
7555 /* genlshFour - shift four byte by a known amount != 0             */
7556 /*-----------------------------------------------------------------*/
7557 static void genlshFour (operand *result, operand *left, int shCount)
7558 {
7559         int size;
7560         
7561         FENTRY;
7562         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7563         size = AOP_SIZE(result);
7564         
7565         /* if shifting more that 3 bytes */
7566         if (shCount >= 24 ) {
7567                 shCount -= 24;
7568                 if (shCount)
7569                 /* lowest order of left goes to the highest
7570                 order of the destination */
7571                 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7572                 else
7573                         movLeft2Result(left, LSB, result, MSB32);
7574                 aopPut(AOP(result),zero,LSB);
7575                 aopPut(AOP(result),zero,MSB16);
7576                 aopPut(AOP(result),zero,MSB32);
7577                 return;
7578         }
7579         
7580         /* more than two bytes */
7581         else if ( shCount >= 16 ) {
7582                 /* lower order two bytes goes to higher order two bytes */
7583                 shCount -= 16;
7584                 /* if some more remaining */
7585                 if (shCount)
7586                         shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7587                 else {
7588                         movLeft2Result(left, MSB16, result, MSB32);
7589                         movLeft2Result(left, LSB, result, MSB24);
7590                 }
7591                 aopPut(AOP(result),zero,MSB16);
7592                 aopPut(AOP(result),zero,LSB);
7593                 return;
7594         }    
7595         
7596         /* if more than 1 byte */
7597         else if ( shCount >= 8 ) {
7598                 /* lower order three bytes goes to higher order  three bytes */
7599                 shCount -= 8;
7600                 if(size == 2){
7601                         if(shCount)
7602                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7603                         else
7604                                 movLeft2Result(left, LSB, result, MSB16);
7605                 }
7606                 else{   /* size = 4 */
7607                         if(shCount == 0){
7608                                 movLeft2Result(left, MSB24, result, MSB32);
7609                                 movLeft2Result(left, MSB16, result, MSB24);
7610                                 movLeft2Result(left, LSB, result, MSB16);
7611                                 aopPut(AOP(result),zero,LSB);
7612                         }
7613                         else if(shCount == 1)
7614                                 shiftLLong(left, result, MSB16);
7615                         else{
7616                                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7617                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7618                                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7619                                 aopPut(AOP(result),zero,LSB);
7620                         }
7621                 }
7622         }
7623         
7624         /* 1 <= shCount <= 7 */
7625         else if(shCount <= 2){
7626                 shiftLLong(left, result, LSB);
7627                 if(shCount == 2)
7628                         shiftLLong(result, result, LSB);
7629         }
7630         /* 3 <= shCount <= 7, optimize */
7631         else{
7632                 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7633                 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7634                 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7635         }
7636 }
7637 #endif
7638
7639 #if 0
7640 /*-----------------------------------------------------------------*/
7641 /* genLeftShiftLiteral - left shifting by known count              */
7642 /*-----------------------------------------------------------------*/
7643 static void genLeftShiftLiteral (operand *left,
7644                                                                  operand *right,
7645                                                                  operand *result,
7646                                                                  iCode *ic)
7647 {    
7648         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7649         //int size;
7650         
7651         FENTRY;
7652         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7653         freeAsmop(right,NULL,ic,TRUE);
7654         
7655         aopOp(left,ic,FALSE);
7656         aopOp(result,ic,FALSE);
7657
7658         size = getSize(operandType(result));
7659         
7660 #if VIEW_SIZE
7661         pic14_emitcode("; shift left ","result %d, left %d",size,
7662                 AOP_SIZE(left));
7663 #endif
7664         
7665         /* I suppose that the left size >= result size */
7666         if(shCount == 0){
7667                 while(size--){
7668                         movLeft2Result(left, size, result, size);
7669                 }
7670         }
7671         
7672         else if(shCount >= (size * 8))
7673                 while(size--)
7674                         aopPut(AOP(result),zero,size);
7675                 else{
7676                         switch (size) {
7677                         case 1:
7678                                 genlshOne (result,left,shCount);
7679                                 break;
7680                                 
7681                         case 2:
7682                         case 3:
7683                                 genlshTwo (result,left,shCount);
7684                                 break;
7685                                 
7686                         case 4:
7687                                 genlshFour (result,left,shCount);
7688                                 break;
7689                         }
7690                 }
7691                 freeAsmop(left,NULL,ic,TRUE);
7692                 freeAsmop(result,NULL,ic,TRUE);
7693 }
7694 #endif
7695
7696 /*-----------------------------------------------------------------*
7697 * genMultiAsm - repeat assembly instruction for size of register.
7698 * if endian == 1, then the high byte (i.e base address + size of 
7699 * register) is used first else the low byte is used first;
7700 *-----------------------------------------------------------------*/
7701 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7702 {
7703         
7704         int offset = 0;
7705         
7706         FENTRY;
7707         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7708         
7709         if(!reg)
7710                 return;
7711         
7712         if(!endian) {
7713                 endian = 1;
7714         } else {
7715                 endian = -1;
7716                 offset = size-1;
7717         }
7718         
7719         while(size--) {
7720                 emitpcode(poc,    popGet(AOP(reg),offset));
7721                 offset += endian;
7722         }
7723         
7724 }
7725
7726 #if 0
7727 /*-----------------------------------------------------------------*/
7728 /* genLeftShift - generates code for left shifting                 */
7729 /*-----------------------------------------------------------------*/
7730 static void genLeftShift (iCode *ic)
7731 {
7732         operand *left,*right, *result;
7733         int size, offset;
7734         unsigned long lit = 0L;
7735         char *l;
7736         symbol *tlbl , *tlbl1;
7737         pCodeOp *pctemp;
7738         
7739         FENTRY;
7740         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7741         
7742         right = IC_RIGHT(ic);
7743         left  = IC_LEFT(ic);
7744         result = IC_RESULT(ic);
7745         
7746         aopOp(right,ic,FALSE);
7747         aopOp(left,ic,FALSE);
7748         aopOp(result,ic,FALSE);
7749         
7750         
7751         /* if the shift count is known then do it 
7752         as efficiently as possible */
7753         if (AOP_TYPE(right) == AOP_LIT) {
7754                 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7755                 return ;
7756         }
7757         
7758         /* shift count is unknown then we have to form 
7759         a loop get the loop count in B : Note: we take
7760         only the lower order byte since shifting
7761         more that 32 bits make no sense anyway, ( the
7762         largest size of an object can be only 32 bits ) */  
7763         
7764         /* this code fails for RIGHT == RESULT */
7765         assert (!pic14_sameRegs (AOP(right), AOP(result)));
7766         
7767         /* now move the left to the result if they are not the
7768         same */
7769         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7770                 AOP_SIZE(result) > 1) {
7771                 
7772                 size = AOP_SIZE(result);
7773                 offset=0;
7774                 while (size--) {
7775                         l = aopGet(AOP(left),offset,FALSE,TRUE);
7776                         if (*l == '@' && (IS_AOP_PREG(result))) {
7777                                 
7778                                 pic14_emitcode("mov","a,%s",l);
7779                                 aopPut(AOP(result),"a",offset);
7780                         } else {
7781                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7782                                 emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7783                                 //aopPut(AOP(result),l,offset);
7784                         }
7785                         offset++;
7786                 }
7787         }
7788         
7789         if(AOP_TYPE(left) == AOP_LIT)
7790                 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7791
7792         size = AOP_SIZE(result);
7793         
7794         /* if it is only one byte then */
7795         if (size == 1) {
7796                 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7797                         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7798                         emitpcode(POC_ANDLW,  popGetLit(0xf0));
7799                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7800                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7801                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7802                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7803                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7804                         emitpcode(POC_RLFW,   popGet(AOP(result),0));
7805                         emitpcode(POC_ANDLW,  popGetLit(0xfe));
7806                         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7807                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7808                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7809                 } else {
7810                         
7811                         tlbl = newiTempLabel(NULL);
7812                         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7813                                 mov2w (AOP(left), 0);
7814                                 emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7815                         }
7816                         
7817                         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7818                         emitpcode(POC_RRF,    popGet(AOP(result),0));
7819                         emitpLabel(tlbl->key);
7820                         emitpcode(POC_RLF,    popGet(AOP(result),0));
7821                         emitpcode(POC_ADDLW,  popGetLit(1));
7822                         emitSKPC;
7823                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7824                 }
7825                 goto release ;
7826         }
7827         
7828         if (pic14_sameRegs(AOP(left),AOP(result))) {
7829                 
7830                 tlbl = newiTempLabel(NULL);
7831                 emitpcode(POC_COMFW,  popGet(AOP(right),0));
7832                 genMultiAsm(POC_RRF, result, size,1);
7833                 emitpLabel(tlbl->key);
7834                 genMultiAsm(POC_RLF, result, size,0);
7835                 emitpcode(POC_ADDLW,  popGetLit(1));
7836                 emitSKPC;
7837                 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7838                 goto release;
7839         }
7840         
7841         //tlbl = newiTempLabel(NULL);
7842         //offset = 0 ;   
7843         //tlbl1 = newiTempLabel(NULL);
7844         
7845         //reAdjustPreg(AOP(result));    
7846         
7847         //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7848         //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7849         //l = aopGet(AOP(result),offset,FALSE,FALSE);
7850         //MOVA(l);
7851         //pic14_emitcode("add","a,acc");         
7852         //aopPut(AOP(result),"a",offset++);
7853         //while (--size) {
7854         //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7855         //  MOVA(l);
7856         //  pic14_emitcode("rlc","a");         
7857         //  aopPut(AOP(result),"a",offset++);
7858         //}
7859         //reAdjustPreg(AOP(result));
7860         
7861         //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7862         //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7863         
7864         
7865         tlbl = newiTempLabel(NULL);
7866         tlbl1= newiTempLabel(NULL);
7867         
7868         size = AOP_SIZE(result);
7869         offset = 1;
7870         
7871         pctemp = popGetTempReg();  /* grab a temporary working register. */
7872         
7873         emitpcode(POC_MOVFW, popGet(AOP(right),0));
7874         
7875         /* offset should be 0, 1 or 3 */
7876         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7877         emitSKPNZ;
7878         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7879         
7880         emitpcode(POC_MOVWF, pctemp);
7881         
7882         
7883         emitpLabel(tlbl->key);
7884         
7885         emitCLRC;
7886         emitpcode(POC_RLF,  popGet(AOP(result),0));
7887         while(--size)
7888                 emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7889         
7890         emitpcode(POC_DECFSZ,  pctemp);
7891         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7892         emitpLabel(tlbl1->key);
7893         
7894         popReleaseTempReg(pctemp);
7895         
7896         
7897 release:
7898         freeAsmop (right,NULL,ic,TRUE);
7899         freeAsmop(left,NULL,ic,TRUE);
7900         freeAsmop(result,NULL,ic,TRUE);
7901 }
7902 #endif
7903
7904 #if 0
7905 /*-----------------------------------------------------------------*/
7906 /* genrshOne - right shift a one byte quantity by known count      */
7907 /*-----------------------------------------------------------------*/
7908 static void genrshOne (operand *result, operand *left,
7909                                            int shCount, int sign)
7910 {
7911         FENTRY;
7912         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7913         shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7914 }
7915
7916 /*-----------------------------------------------------------------*/
7917 /* genrshTwo - right shift two bytes by known amount != 0          */
7918 /*-----------------------------------------------------------------*/
7919 static void genrshTwo (operand *result,operand *left,
7920                                            int shCount, int sign)
7921 {
7922         FENTRY;
7923         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7924         /* if shCount >= 8 */
7925         if (shCount >= 8) {
7926                 shCount -= 8 ;
7927                 if (shCount)
7928                         shiftR1Left2Result(left, MSB16, result, LSB,
7929                         shCount, sign);
7930                 else
7931                         movLeft2Result(left, MSB16, result, LSB);
7932                 
7933                 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7934                 
7935                 if(sign) {
7936                         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7937                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7938                 }
7939         }
7940         
7941         /*  1 <= shCount <= 7 */
7942         else
7943                 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7944 }
7945
7946 /*-----------------------------------------------------------------*/
7947 /* shiftRLong - shift right one long from left to result           */
7948 /* offl = LSB or MSB16                                             */
7949 /*-----------------------------------------------------------------*/
7950 static void shiftRLong (operand *left, int offl,
7951                                                 operand *result, int sign)
7952 {
7953         int size, same;
7954         
7955         FENTRY;
7956         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7957         
7958         size = AOP_SIZE(left);
7959         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7960         
7961         if (sign)
7962                 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7963         else
7964                 emitCLRC;
7965
7966         assert (offl >= 0 && offl < size);
7967
7968         same = pic14_sameRegs (AOP(left), AOP(result));
7969
7970         /* perform the shift */
7971         while (size--)
7972         {
7973                 if (same && !offl) {
7974                         emitpcode (POC_RRF, popGet (AOP(result), size));
7975                 } else {
7976                         emitpcode (POC_RRFW, popGet (AOP(left), size));
7977                         emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7978                 }
7979         } // while
7980
7981         addSign (result, AOP_SIZE(left) - offl, sign);
7982 }
7983
7984 /*-----------------------------------------------------------------*/
7985 /* genrshFour - shift four byte by a known amount != 0             */
7986 /*-----------------------------------------------------------------*/
7987 static void genrshFour (operand *result, operand *left,
7988                                                 int shCount, int sign)
7989 {
7990         FENTRY;
7991         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7992         /* if shifting more that 3 bytes */
7993         if(shCount >= 24 ) {
7994                 shCount -= 24;
7995                 if(shCount)
7996                         shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7997                 else
7998                         movLeft2Result(left, MSB32, result, LSB);
7999                 
8000                 addSign(result, MSB16, sign);
8001         }
8002         else if(shCount >= 16){
8003                 shCount -= 16;
8004                 if(shCount)
8005                         shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8006                 else{
8007                         movLeft2Result(left, MSB24, result, LSB);
8008                         movLeft2Result(left, MSB32, result, MSB16);
8009                 }
8010                 addSign(result, MSB24, sign);
8011         }
8012         else if(shCount >= 8){
8013                 shCount -= 8;
8014                 if(shCount == 1)
8015                         shiftRLong(left, MSB16, result, sign);
8016                 else if(shCount == 0){
8017                         movLeft2Result(left, MSB16, result, LSB);
8018                         movLeft2Result(left, MSB24, result, MSB16);
8019                         movLeft2Result(left, MSB32, result, MSB24);
8020                         addSign(result, MSB32, sign);
8021                 }
8022                 else{
8023                         shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8024                         shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8025                         /* the last shift is signed */
8026                         shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8027                         addSign(result, MSB32, sign);
8028                 }
8029         }
8030         else{   /* 1 <= shCount <= 7 */
8031                 if(shCount <= 2){
8032                         shiftRLong(left, LSB, result, sign);
8033                         if(shCount == 2)
8034                                 shiftRLong(result, LSB, result, sign);
8035                 }
8036                 else{
8037                         shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8038                         shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8039                         shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8040                 }
8041         }
8042 }
8043
8044 /*-----------------------------------------------------------------*/
8045 /* genRightShiftLiteral - right shifting by known count            */
8046 /*-----------------------------------------------------------------*/
8047 static void genRightShiftLiteral (operand *left,
8048                                                                   operand *right,
8049                                                                   operand *result,
8050                                                                   iCode *ic,
8051                                                                   int sign)
8052 {    
8053         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8054         int lsize,res_size;
8055         
8056         FENTRY;
8057         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8058         freeAsmop(right,NULL,ic,TRUE);
8059         
8060         aopOp(left,ic,FALSE);
8061         aopOp(result,ic,FALSE);
8062         
8063 #if VIEW_SIZE
8064         pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8065                 AOP_SIZE(left));
8066 #endif
8067         
8068         lsize = pic14_getDataSize(left);
8069         res_size = pic14_getDataSize(result);
8070         /* test the LEFT size !!! */
8071         
8072         /* I suppose that the left size >= result size */
8073         if(shCount == 0){
8074                 while(res_size--)
8075                         movLeft2Result(left, res_size, result, res_size);
8076         }
8077         
8078         else if(shCount >= (lsize * 8)){
8079                 
8080                 if(res_size == 1) {
8081                         emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8082                         if(sign) {
8083                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8084                                 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8085                         }
8086                 } else {
8087                         
8088                         if(sign) {
8089                                 emitpcode(POC_MOVLW, popGetLit(0));
8090                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8091                                 emitpcode(POC_MOVLW, popGetLit(0xff));
8092                                 while(res_size--)
8093                                         emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8094                                 
8095                         } else {
8096                                 
8097                                 while(res_size--)
8098                                         emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8099                         }
8100                 }
8101         } else {
8102                 
8103                 switch (res_size) {
8104                 case 1:
8105                         genrshOne (result,left,shCount,sign);
8106                         break;
8107                         
8108                 case 2:
8109                         genrshTwo (result,left,shCount,sign);
8110                         break;
8111                         
8112                 case 4:
8113                         genrshFour (result,left,shCount,sign);
8114                         break;
8115                 default :
8116                         break;
8117                 }
8118                 
8119         }
8120
8121         freeAsmop(left,NULL,ic,TRUE);
8122         freeAsmop(result,NULL,ic,TRUE);
8123 }
8124 #endif
8125
8126 #if 0
8127 /*-----------------------------------------------------------------*/
8128 /* genSignedRightShift - right shift of signed number              */
8129 /*-----------------------------------------------------------------*/
8130 static void genSignedRightShift (iCode *ic)
8131 {
8132         operand *right, *left, *result;
8133         int size, offset;
8134         //  char *l;
8135         symbol *tlbl, *tlbl1 ;
8136         pCodeOp *pctemp;
8137         
8138         //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8139         
8140         /* we do it the hard way put the shift count in b
8141         and loop thru preserving the sign */
8142         FENTRY;
8143         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8144         
8145         right = IC_RIGHT(ic);
8146         left  = IC_LEFT(ic);
8147         result = IC_RESULT(ic);
8148         
8149         aopOp(right,ic,FALSE);  
8150         aopOp(left,ic,FALSE);
8151         aopOp(result,ic,FALSE);
8152         
8153         
8154         if ( AOP_TYPE(right) == AOP_LIT) {
8155                 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8156                 //genRightShiftLiteral (left,right,result,ic,1);
8157                 return ;
8158         }
8159         /* shift count is unknown then we have to form 
8160         a loop get the loop count in B : Note: we take
8161         only the lower order byte since shifting
8162         more that 32 bits make no sense anyway, ( the
8163         largest size of an object can be only 32 bits ) */  
8164         
8165         //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8166         //pic14_emitcode("inc","b");
8167         //freeAsmop (right,NULL,ic,TRUE);
8168         //aopOp(left,ic,FALSE);
8169         //aopOp(result,ic,FALSE);
8170         
8171         /* now move the left to the result if they are not the
8172         same */
8173         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
8174                 AOP_SIZE(result) > 1) {
8175                 
8176                 size = AOP_SIZE(result);
8177                 offset=0;
8178                 while (size--) { 
8179                         /*
8180                         l = aopGet(AOP(left),offset,FALSE,TRUE);
8181                         if (*l == '@' && IS_AOP_PREG(result)) {
8182                                 pic14_emitcode("mov","a,%s",l);
8183                                 aopPut(AOP(result),"a",offset);
8184                         } else
8185                         aopPut(AOP(result),l,offset);
8186                         */
8187                         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
8188                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
8189                         
8190                         offset++;
8191                 }
8192         }
8193         
8194         /* mov the highest order bit to OVR */    
8195         tlbl = newiTempLabel(NULL);
8196         tlbl1= newiTempLabel(NULL);
8197         
8198         size = AOP_SIZE(result);
8199         offset = size - 1;
8200         
8201         pctemp = popGetTempReg();  /* grab a temporary working register. */
8202         
8203         emitpcode(POC_MOVFW, popGet(AOP(right),0));
8204         
8205         /* offset should be 0, 1 or 3 */
8206         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8207         emitSKPNZ;
8208         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
8209         
8210         emitpcode(POC_MOVWF, pctemp);
8211         
8212         
8213         emitpLabel(tlbl->key);
8214         
8215         emitpcode(POC_RLFW,  popGet(AOP(result),offset));
8216         emitpcode(POC_RRF,   popGet(AOP(result),offset));
8217         
8218         while(--size) {
8219                 emitpcode(POC_RRF,   popGet(AOP(result),--offset));
8220         }
8221         
8222         emitpcode(POC_DECFSZ,  pctemp);
8223         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8224         emitpLabel(tlbl1->key);
8225         
8226         popReleaseTempReg(pctemp);
8227 #if 0
8228         size = AOP_SIZE(result);
8229         offset = size - 1;
8230         pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8231         pic14_emitcode("rlc","a");
8232         pic14_emitcode("mov","ov,c");
8233         /* if it is only one byte then */
8234         if (size == 1) {
8235                 l = aopGet(AOP(left),0,FALSE,FALSE);
8236                 MOVA(l);
8237                 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8238                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8239                 pic14_emitcode("mov","c,ov");
8240                 pic14_emitcode("rrc","a");
8241                 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8242                 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8243                 aopPut(AOP(result),"a",0);
8244                 goto release ;
8245         }
8246         
8247         reAdjustPreg(AOP(result));
8248         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8249         pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
8250         pic14_emitcode("mov","c,ov");
8251         while (size--) {
8252                 l = aopGet(AOP(result),offset,FALSE,FALSE);
8253                 MOVA(l);
8254                 pic14_emitcode("rrc","a");         
8255                 aopPut(AOP(result),"a",offset--);
8256         }
8257         reAdjustPreg(AOP(result));
8258         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8259         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8260         
8261 release:
8262 #endif
8263         
8264         freeAsmop(left,NULL,ic,TRUE);
8265         freeAsmop(result,NULL,ic,TRUE);
8266         freeAsmop(right,NULL,ic,TRUE);
8267 }
8268 #endif
8269
8270 /*-----------------------------------------------------------------*/
8271 /* loadSignToC - load the operand's sign bit into CARRY            */
8272 /*-----------------------------------------------------------------*/
8273
8274 static void loadSignToC (operand *op)
8275 {
8276         FENTRY;
8277         assert (op && AOP(op) && AOP_SIZE(op));
8278
8279         emitCLRC;
8280         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8281         emitSETC;
8282 }
8283
8284 /*-----------------------------------------------------------------*/
8285 /* genRightShift - generate code for right shifting                */
8286 /*-----------------------------------------------------------------*/
8287 static void genGenericShift (iCode *ic, int shiftRight)
8288 {
8289         operand *right, *left, *result;
8290         sym_link *retype ;
8291         int size;
8292         symbol *tlbl, *tlbl1, *inverselbl;
8293         
8294         FENTRY;
8295         /* if signed then we do it the hard way preserve the
8296         sign bit moving it inwards */
8297         retype = getSpec(operandType(IC_RESULT(ic)));
8298         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8299         
8300         /* signed & unsigned types are treated the same : i.e. the
8301         signed is NOT propagated inwards : quoting from the
8302         ANSI - standard : "for E1 >> E2, is equivalent to division
8303         by 2**E2 if unsigned or if it has a non-negative value,
8304         otherwise the result is implementation defined ", MY definition
8305         is that the sign does not get propagated */
8306         
8307         right = IC_RIGHT(ic);
8308         left  = IC_LEFT(ic);
8309         result = IC_RESULT(ic);
8310         
8311         aopOp(right,ic,FALSE);
8312         aopOp(left,ic,FALSE);
8313         aopOp(result,ic,FALSE);
8314         
8315         /* if the shift count is known then do it 
8316         as efficiently as possible */
8317         if (AOP_TYPE(right) == AOP_LIT) {
8318                 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8319                 if (lit < 0)
8320                 {
8321                         lit = -lit;
8322                         shiftRight = !shiftRight;
8323                 }
8324                 
8325                 if (shiftRight)
8326                         shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8327                 else
8328                         shiftLeft_Left2ResultLit (left, result, lit);
8329                 //genRightShiftLiteral (left,right,result,ic, 0);
8330                 return ;
8331         }
8332         
8333         /* shift count is unknown then we have to form 
8334         a loop get the loop count in B : Note: we take
8335         only the lower order byte since shifting
8336         more that 32 bits make no sense anyway, ( the
8337         largest size of an object can be only 32 bits ) */  
8338
8339         /* we must not overwrite the shift counter */
8340         assert (!pic14_sameRegs(AOP(right),AOP(result)));
8341         
8342         /* now move the left to the result if they are not the
8343         same */
8344         if (!pic14_sameRegs(AOP(left),AOP(result)))
8345         {
8346                 size = min(AOP_SIZE(result), AOP_SIZE(left));
8347                 while (size--) {
8348                         mov2w(AOP(left), size);
8349                         movwf(AOP(result), size);
8350                 }
8351                 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8352         }
8353         
8354         tlbl = newiTempLabel(NULL);
8355         tlbl1= newiTempLabel(NULL);
8356         inverselbl = NULL;
8357         size = AOP_SIZE(result);
8358
8359         mov2w(AOP(right),0);
8360         if (!SPEC_USIGN(operandType(right)))
8361         {
8362                 inverselbl = newiTempLabel(NULL);
8363                 /* signed shift count -- invert shift direction for c<0 */
8364                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8365                 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8366         } // if
8367         emitpcode(POC_SUBLW, popGetLit(0));     /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8368         /* check for `a = b >> c' with `-c == 0' */
8369         emitSKPNZ;
8370         emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8371         emitpLabel(tlbl->key);
8372         /* propagate the sign bit inwards for SIGNED result */
8373         if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8374         genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8375         emitpcode(POC_ADDLW,  popGetLit(1));    /* clears CARRY (unless W==0 afterwards) */
8376         emitSKPC;
8377         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8378
8379         if (!SPEC_USIGN(operandType(right)))
8380         {
8381                 symbol *inv_loop = newiTempLabel(NULL);
8382
8383                 shiftRight = !shiftRight;       /* invert shift direction */
8384                 
8385                 /* we came here from the code above -- we are done */
8386                 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8387                 
8388                 /* emit code for shifting N<0 steps, count is already in W */
8389                 emitpLabel(inverselbl->key);
8390                 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8391                 emitpLabel(inv_loop->key);
8392                 /* propagate the sign bit inwards for SIGNED result */
8393                 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8394                 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8395                 emitpcode(POC_ADDLW, popGetLit(1));
8396                 emitSKPC;
8397                 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8398         } // if
8399         
8400         emitpLabel(tlbl1->key);
8401         
8402         freeAsmop(left,NULL,ic,TRUE);
8403         freeAsmop (right,NULL,ic,TRUE);
8404         freeAsmop(result,NULL,ic,TRUE);
8405 }
8406
8407 static void genRightShift (iCode *ic)
8408 {
8409         genGenericShift(ic, 1);
8410 }
8411
8412 static void genLeftShift (iCode *ic)
8413 {
8414         genGenericShift(ic, 0);
8415 }
8416
8417 /*-----------------------------------------------------------------*/
8418 /* SetIrp - Set IRP bit                                            */
8419 /*-----------------------------------------------------------------*/
8420 void SetIrp(operand *result) {
8421         FENTRY;
8422         if (AOP_TYPE(result) == AOP_LIT) {
8423                 unsigned lit = (unsigned)operandLitValue(result);
8424                 if (lit&0x100)
8425                         emitSETIRP;
8426                 else
8427                         emitCLRIRP;
8428         } else {
8429                 if (PCOP(AOP(result))->type == PO_LITERAL) {
8430                         int addrs = PCOL(AOP(result))->lit;
8431                         if (addrs & 0x100)
8432                                 emitSETIRP;
8433                         else
8434                                 emitCLRIRP;
8435                 } else {
8436                         emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8437                         if(AOP_SIZE(result) > 1) {
8438                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8439                                 emitSETIRP;
8440                         }
8441                 }
8442         }
8443 }
8444
8445 static void
8446 setup_fsr (operand *ptr)
8447 {
8448   mov2w_op(ptr, 0);
8449   emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8450
8451   /* also setup-up IRP */
8452   SetIrp (ptr);
8453 }
8454
8455 /*-----------------------------------------------------------------*/
8456 /* emitPtrByteGet - emits code to get a byte into WREG from an     */
8457 /*                  arbitrary pointer (__code, __data, generic)    */
8458 /*-----------------------------------------------------------------*/
8459 static void
8460 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8461 {
8462     FENTRY;
8463     switch (p_type)
8464     {
8465     case POINTER:
8466     case FPOINTER:
8467       if (!alreadyAddressed) setup_fsr (src);
8468       emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8469       break;
8470     
8471     case CPOINTER:
8472       assert( AOP_SIZE(src) == 2 );
8473       mov2w_op(src, 0);
8474       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8475       mov2w_op(src, 1);
8476       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8477       emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE));   /* GPOINTER tag for __code space */
8478       call_libraryfunc ("__gptrget1");
8479       break;
8480     
8481     case GPOINTER:
8482       assert( AOP_SIZE(src) == 3 );
8483       mov2w_op(src, 0);
8484       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8485       mov2w_op(src, 1);
8486       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8487       mov2w_op(src, 2);
8488       call_libraryfunc ("__gptrget1");
8489       break;
8490     
8491     default:
8492       assert( !"unhandled pointer type" );
8493       break;
8494     }
8495 }
8496
8497 /*-----------------------------------------------------------------*/
8498 /* emitPtrByteSet - emits code to set a byte from src through a    */
8499 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR).       */
8500 /*-----------------------------------------------------------------*/
8501 static void
8502 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8503 {
8504     FENTRY;
8505     switch (p_type)
8506     {
8507     case POINTER:
8508     case FPOINTER:
8509       if (!alreadyAddressed) setup_fsr (dst);
8510       emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8511       break;
8512     
8513     case CPOINTER:
8514       assert( !"trying to assign to __code pointer" );
8515       break;
8516     
8517     case GPOINTER:
8518       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8519       mov2w_op(dst, 0);
8520       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8521       mov2w_op(dst, 1);
8522       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8523       mov2w_op(dst, 2);
8524       call_libraryfunc ("__gptrput1");
8525       break;
8526
8527     default:
8528       assert( !"unhandled pointer type" );
8529       break;
8530     }
8531 }
8532
8533 /*-----------------------------------------------------------------*/
8534 /* genUnpackBits - generates code for unpacking bits               */
8535 /*-----------------------------------------------------------------*/
8536 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8537 {    
8538   int rsize;            /* result size */
8539   sym_link *etype;      /* bitfield type information */
8540   int blen;             /* bitfield length */
8541   int bstr;             /* bitfield starting bit within byte */
8542
8543   FENTRY;
8544   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8545   etype = getSpec(operandType(result));
8546   rsize = getSize (operandType (result));
8547   blen = SPEC_BLEN (etype);
8548   bstr = SPEC_BSTR (etype);
8549
8550   /* single bit field case */
8551   if (blen == 1) {
8552     if (ifx) { /* that is for an if statement */
8553       pCodeOp *pcop;
8554       resolvedIfx rIfx;
8555       resolveIfx(&rIfx,ifx);
8556       if (ptype == -1) /* direct */
8557         pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8558       else
8559         pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8560       emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8561       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8562       ifx->generated=1;
8563     } else {
8564       int i;
8565       assert (!pic14_sameRegs (AOP(result), AOP(left)));
8566       for (i=0; i < AOP_SIZE(result); i++)
8567         emitpcode (POC_CLRF, popGet (AOP(result), i));
8568
8569       switch (ptype)
8570       {
8571       case -1:
8572         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8573         /* adjust result below */
8574         break;
8575         
8576       case POINTER:
8577       case FPOINTER:
8578       case GPOINTER:
8579       case CPOINTER:
8580         emitPtrByteGet (left, ptype, FALSE);
8581         emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8582         emitSKPZ;
8583         /* adjust result below */
8584         break;
8585         
8586       default:
8587         assert( !"unhandled pointer type" );
8588       } // switch
8589
8590       /* move sign-/zero extended bit to result */
8591       if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8592         emitpcode (POC_INCF, popGet (AOP(result), 0));
8593       } else {
8594         emitpcode (POC_DECF, popGet (AOP(result), 0));
8595       }
8596       addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8597     }
8598     return;
8599   }
8600   else if (blen <= 8 && ((blen + bstr) <= 8))
8601   {
8602     /* blen > 1 */
8603     int i;
8604
8605     for (i=0; i < AOP_SIZE(result); i++)
8606       emitpcode (POC_CLRF, popGet (AOP(result), i));
8607
8608     switch (ptype)
8609     {
8610     case -1:
8611       mov2w(AOP(left), 0);
8612       break;
8613       
8614     case POINTER:
8615     case FPOINTER:
8616     case GPOINTER:
8617     case CPOINTER:
8618       emitPtrByteGet (left, ptype, FALSE);
8619       break;
8620       
8621     default:
8622       assert( !"unhandled pointer type" );
8623     } // switch
8624
8625     if (blen < 8)
8626       emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8627     movwf(AOP(result), 0);
8628     AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8629
8630     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8631     {
8632       /* signed bitfield */
8633       assert (bstr + blen > 0);
8634       emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8635       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8636       emitpcode(POC_IORWF, popGet(AOP(result),0));
8637     }
8638     addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8639     return;
8640   }
8641
8642   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8643 }
8644
8645 #if 1
8646 /*-----------------------------------------------------------------*/
8647 /* genDataPointerGet - generates code when ptr offset is known     */
8648 /*-----------------------------------------------------------------*/
8649 static void genDataPointerGet (operand *left, 
8650         operand *result, 
8651         iCode *ic)
8652 {
8653         int size , offset = 0;
8654                 
8655         FENTRY;
8656         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8657         
8658         
8659         /* optimization - most of the time, left and result are the same
8660         * address, but different types. for the pic code, we could omit
8661         * the following
8662         */
8663         aopOp(result,ic,TRUE);
8664         
8665         if (pic14_sameRegs (AOP(left), AOP(result)))
8666                 return;
8667         
8668         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8669         
8670         //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8671         
8672         size = AOP_SIZE(result);
8673         if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8674         
8675         offset = 0;
8676         while (size--) {
8677                 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8678                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8679                 offset++;
8680         }
8681         
8682         freeAsmop(left,NULL,ic,TRUE);
8683         freeAsmop(result,NULL,ic,TRUE);
8684 }
8685 #endif
8686
8687 /*-----------------------------------------------------------------*/
8688 /* genNearPointerGet - pic14_emitcode for near pointer fetch       */
8689 /*-----------------------------------------------------------------*/
8690 static void genNearPointerGet (operand *left, 
8691                                                            operand *result, 
8692                                                            iCode *ic)
8693 {
8694         asmop *aop = NULL;
8695         sym_link *ltype = operandType(left);
8696         sym_link *rtype = operandType(result);
8697         sym_link *retype= getSpec(rtype);      /* bitfield type information */
8698         int direct = 0;
8699
8700         FENTRY;
8701         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8702         
8703         
8704         aopOp(left,ic,FALSE);
8705         
8706         /* if left is rematerialisable and
8707         result is not bit variable type and
8708         the left is pointer to data space i.e
8709         lower 128 bytes of space */
8710         if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8711                 !IS_BITVAR(retype)         &&
8712                 PIC_IS_DATA_PTR(ltype)) {
8713                 genDataPointerGet (left,result,ic);
8714                 return ;
8715         }
8716         
8717         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8718         aopOp (result,ic,FALSE);
8719         
8720         /* Check if can access directly instead of via a pointer */
8721         if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8722                 && AOP_SIZE(result) == 1)
8723         {
8724                 direct = 1;
8725         }
8726
8727         if (IS_BITFIELD(getSpec(operandType(result)))) 
8728         {
8729                 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8730                 goto release;
8731         }
8732         
8733         /* If the pointer value is not in a the FSR then need to put it in */
8734         /* Must set/reset IRP bit for use with FSR. */
8735         if (!direct)
8736           setup_fsr (left);
8737         
8738 //      sym_link *etype;
8739         /* if bitfield then unpack the bits */
8740         {
8741                 /* we have can just get the values */
8742                 int size = AOP_SIZE(result);
8743                 int offset = 0 ;  
8744                 
8745                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8746                 
8747                 while(size--) {
8748                         if (direct)
8749                                 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8750                         else
8751                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8752                         if (AOP_TYPE(result) == AOP_LIT) {
8753                                 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8754                         } else {
8755                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8756                         }
8757                         if (size && !direct)
8758                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8759                         offset++;
8760                 }
8761         }
8762         
8763         /* now some housekeeping stuff */
8764         if (aop) {
8765                 /* we had to allocate for this iCode */
8766                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8767                 freeAsmop(NULL,aop,ic,TRUE);
8768         } else { 
8769                 /* we did not allocate which means left
8770                 already in a pointer register, then
8771                 if size > 0 && this could be used again
8772                 we have to point it back to where it 
8773                 belongs */
8774                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8775                 if (AOP_SIZE(result) > 1 &&
8776                         !OP_SYMBOL(left)->remat &&
8777                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8778                         ic->depth )) {
8779                         int size = AOP_SIZE(result) - 1;
8780                         while (size--)
8781                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8782                 }
8783         }
8784         
8785 release:
8786         /* done */
8787         freeAsmop(left,NULL,ic,TRUE);
8788         freeAsmop(result,NULL,ic,TRUE);
8789
8790 }
8791
8792 #if 0
8793 /*-----------------------------------------------------------------*/
8794 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8795 /*-----------------------------------------------------------------*/
8796 static void genPagedPointerGet (operand *left, 
8797                                                                 operand *result, 
8798                                                                 iCode *ic)
8799 {
8800         asmop *aop = NULL;
8801         regs *preg = NULL ;
8802         char *rname ;
8803         sym_link *rtype, *retype;    
8804         
8805         FENTRY;
8806         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8807         
8808         rtype = operandType(result);
8809         retype= getSpec(rtype);
8810         
8811         aopOp(left,ic,FALSE);
8812         
8813         /* if the value is already in a pointer register
8814         then don't need anything more */
8815         if (!AOP_INPREG(AOP(left))) {
8816                 /* otherwise get a free pointer register */
8817                 aop = newAsmop(0);
8818                 preg = getFreePtr(ic,&aop,FALSE);
8819                 pic14_emitcode("mov","%s,%s",
8820                         preg->name,
8821                         aopGet(AOP(left),0,FALSE,TRUE));
8822                 rname = preg->name ;
8823         } else
8824                 rname = aopGet(AOP(left),0,FALSE,FALSE);
8825         
8826         freeAsmop(left,NULL,ic,TRUE);
8827         aopOp (result,ic,FALSE);
8828         
8829         /* if bitfield then unpack the bits */
8830         if (IS_BITFIELD(retype)) 
8831                 genUnpackBits (result,left,rname,PPOINTER,0);
8832         else {
8833                 /* we have can just get the values */
8834                 int size = AOP_SIZE(result);
8835                 int offset = 0 ;  
8836                 
8837                 while (size--) {
8838                         
8839                         pic14_emitcode("movx","a,@%s",rname);
8840                         aopPut(AOP(result),"a",offset);
8841                         
8842                         offset++ ;
8843                         
8844                         if (size)
8845                                 pic14_emitcode("inc","%s",rname);
8846                 }
8847         }
8848         
8849         /* now some housekeeping stuff */
8850         if (aop) {
8851                 /* we had to allocate for this iCode */
8852                 freeAsmop(NULL,aop,ic,TRUE);
8853         } else { 
8854         /* we did not allocate which means left
8855         already in a pointer register, then
8856         if size > 0 && this could be used again
8857         we have to point it back to where it 
8858                 belongs */
8859                 if (AOP_SIZE(result) > 1 &&
8860                         !OP_SYMBOL(left)->remat &&
8861                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8862                         ic->depth )) {
8863                         int size = AOP_SIZE(result) - 1;
8864                         while (size--)
8865                                 pic14_emitcode("dec","%s",rname);
8866                 }
8867         }
8868         
8869         /* done */
8870         freeAsmop(result,NULL,ic,TRUE);
8871         
8872         
8873 }
8874
8875 /*-----------------------------------------------------------------*/
8876 /* genFarPointerGet - gget value from far space                    */
8877 /*-----------------------------------------------------------------*/
8878 static void genFarPointerGet (operand *left,
8879                                                           operand *result, iCode *ic)
8880 {
8881         int size, offset ;
8882         sym_link *retype = getSpec(operandType(result));
8883         
8884         FENTRY;
8885         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8886         
8887         aopOp(left,ic,FALSE);
8888         
8889         /* if the operand is already in dptr 
8890         then we do nothing else we move the value to dptr */
8891         if (AOP_TYPE(left) != AOP_STR) {
8892                 /* if this is remateriazable */
8893                 if (AOP_TYPE(left) == AOP_IMMD)
8894                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8895                 else { /* we need to get it byte by byte */
8896                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8897                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8898                         if (options.model == MODEL_FLAT24)
8899                         {
8900                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8901                         }
8902                 }
8903         }
8904         /* so dptr know contains the address */
8905         freeAsmop(left,NULL,ic,TRUE);
8906         aopOp(result,ic,FALSE);
8907         
8908         /* if bit then unpack */
8909         if (IS_BITFIELD(retype)) 
8910                 genUnpackBits(result,left,"dptr",FPOINTER,0);
8911         else {
8912                 size = AOP_SIZE(result);
8913                 offset = 0 ;
8914                 
8915                 while (size--) {
8916                         pic14_emitcode("movx","a,@dptr");
8917                         aopPut(AOP(result),"a",offset++);
8918                         if (size)
8919                                 pic14_emitcode("inc","dptr");
8920                 }
8921         }
8922         
8923         freeAsmop(result,NULL,ic,TRUE);
8924 }
8925 #endif
8926
8927 #if 0
8928 /*-----------------------------------------------------------------*/
8929 /* genCodePointerGet - get value from code space                  */
8930 /*-----------------------------------------------------------------*/
8931 static void genCodePointerGet (operand *left,
8932                                                            operand *result, iCode *ic)
8933 {
8934         int size, offset ;
8935         sym_link *retype = getSpec(operandType(result));
8936         
8937         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8938         
8939         aopOp(left,ic,FALSE);
8940         
8941         /* if the operand is already in dptr 
8942         then we do nothing else we move the value to dptr */
8943         if (AOP_TYPE(left) != AOP_STR) {
8944                 /* if this is remateriazable */
8945                 if (AOP_TYPE(left) == AOP_IMMD)
8946                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8947                 else { /* we need to get it byte by byte */
8948                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8949                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8950                         if (options.model == MODEL_FLAT24)
8951                         {
8952                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8953                         }
8954                 }
8955         }
8956         /* so dptr know contains the address */
8957         freeAsmop(left,NULL,ic,TRUE);
8958         aopOp(result,ic,FALSE);
8959         
8960         /* if bit then unpack */
8961         if (IS_BITFIELD(retype)) 
8962                 genUnpackBits(result,left,"dptr",CPOINTER,0);
8963         else {
8964                 size = AOP_SIZE(result);
8965                 offset = 0 ;
8966                 
8967                 while (size--) {
8968                         pic14_emitcode("clr","a");
8969                         pic14_emitcode("movc","a,@a+dptr");
8970                         aopPut(AOP(result),"a",offset++);
8971                         if (size)
8972                                 pic14_emitcode("inc","dptr");
8973                 }
8974         }
8975         
8976         freeAsmop(result,NULL,ic,TRUE);
8977 }
8978 #endif
8979 /*-----------------------------------------------------------------*/
8980 /* genGenPointerGet - gget value from generic pointer space        */
8981 /*-----------------------------------------------------------------*/
8982 static void genGenPointerGet (operand *left,
8983                                                           operand *result, iCode *ic)
8984 {
8985         FENTRY;
8986         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8987         aopOp(left,ic,FALSE);
8988         aopOp(result,ic,FALSE);
8989         
8990         
8991         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8992
8993         if (IS_BITFIELD(getSpec(operandType(result))))
8994         {
8995           genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
8996           return;
8997         }
8998
8999         {
9000           /* emit call to __gptrget */
9001           char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
9002           int size = AOP_SIZE(result);
9003           int idx = 0;
9004
9005           assert (size > 0 && size <= 4);
9006
9007           /* pass arguments */
9008           assert (AOP_SIZE(left) == 3);
9009           mov2w(AOP(left), 0);
9010           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9011           mov2w(AOP(left), 1);
9012           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9013           mov2w(AOP(left), 2);
9014           call_libraryfunc (func[size]);
9015           
9016           /* save result */
9017           movwf (AOP(result), --size);
9018           while (size--) {
9019             emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
9020             movwf (AOP(result), size);
9021           } // while
9022         }
9023         
9024         freeAsmop(left,NULL,ic,TRUE);
9025         freeAsmop(result,NULL,ic,TRUE);
9026         
9027 }
9028
9029 /*-----------------------------------------------------------------*/
9030 /* genConstPointerGet - get value from const generic pointer space */
9031 /*-----------------------------------------------------------------*/
9032 static void genConstPointerGet (operand *left,
9033                                                                 operand *result, iCode *ic)
9034 {
9035         //sym_link *retype = getSpec(operandType(result));
9036         #if 0
9037         symbol *albl, *blbl;//, *clbl;
9038         pCodeOp *pcop;
9039         #endif
9040         PIC_OPCODE poc;
9041         int i, size, lit;
9042         
9043         FENTRY;
9044         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9045         aopOp(left,ic,FALSE);
9046         aopOp(result,ic,FALSE);
9047         
9048         size = AOP_SIZE(result);
9049         
9050         DEBUGpic14_AopType(__LINE__,left,NULL,result);
9051         
9052         DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9053
9054         lit = op_isLitLike (left);
9055         poc = lit ? POC_MOVLW : POC_MOVFW;
9056
9057         if (IS_BITFIELD(getSpec(operandType(result))))
9058         {
9059                 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9060                 goto release;
9061         }
9062
9063         {
9064                 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9065                 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9066                 assert (size > 0 && size <= 4);
9067                 
9068                 mov2w_op(left, 0);
9069                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9070                 mov2w_op(left, 1);
9071                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9072                 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9073                 call_libraryfunc (func[size]);
9074
9075                 movwf(AOP(result),size-1);
9076                 for (i = 1; i < size; i++)
9077                 {
9078                         emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9079                         movwf(AOP(result),size - 1 - i);
9080                 } // for
9081         }
9082         
9083 release:
9084         freeAsmop(left,NULL,ic,TRUE);
9085         freeAsmop(result,NULL,ic,TRUE);
9086         
9087 }
9088 /*-----------------------------------------------------------------*/
9089 /* genPointerGet - generate code for pointer get                   */
9090 /*-----------------------------------------------------------------*/
9091 static void genPointerGet (iCode *ic)
9092 {
9093         operand *left, *result ;
9094         sym_link *type, *etype;
9095         int p_type = -1;
9096         
9097         FENTRY;
9098         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9099         
9100         left = IC_LEFT(ic);
9101         result = IC_RESULT(ic) ;
9102         
9103         /* depending on the type of pointer we need to
9104         move it to the correct pointer register */
9105         type = operandType(left);
9106         etype = getSpec(type);
9107         
9108         if (IS_PTR_CONST(type))
9109                 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9110         
9111         /* if left is of type of pointer then it is simple */
9112         if (IS_PTR(type) && !IS_FUNC(type->next)) 
9113                 p_type = DCL_TYPE(type);
9114         else {
9115                 /* we have to go by the storage class */
9116                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9117                 
9118                 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9119                 
9120                 if (SPEC_OCLS(etype)->codesp ) {
9121                         DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9122                         //p_type = CPOINTER ; 
9123                 }
9124                 else
9125                         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9126                                 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9127                         /*p_type = FPOINTER ;*/ 
9128                         else
9129                                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9130                                         DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9131                                 /*        p_type = PPOINTER; */
9132                                 else
9133                                         if (SPEC_OCLS(etype) == idata )
9134                                                 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9135                                         /*      p_type = IPOINTER; */
9136                                         else
9137                                                 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9138                                         /*      p_type = POINTER ; */
9139         }
9140         
9141         /* now that we have the pointer type we assign
9142         the pointer values */
9143         switch (p_type) {
9144                 
9145         case POINTER: 
9146         case FPOINTER:
9147         //case IPOINTER:
9148                 genNearPointerGet (left,result,ic);
9149                 break;
9150 /*
9151         case PPOINTER:
9152                 genPagedPointerGet(left,result,ic);
9153                 break;
9154                 
9155         case FPOINTER:
9156                 genFarPointerGet (left,result,ic);
9157                 break;
9158 */              
9159         case CPOINTER:
9160                 genConstPointerGet (left,result,ic);
9161                 break;
9162                 
9163         case GPOINTER:
9164                 genGenPointerGet (left,result,ic);
9165                 break;
9166         default:
9167                 assert ( !"unhandled pointer type" );
9168                 break;
9169         }
9170         
9171 }
9172
9173 /*-----------------------------------------------------------------*/
9174 /* genPackBits - generates code for packed bit storage             */
9175 /*-----------------------------------------------------------------*/
9176 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9177 {
9178   int blen;             /* bitfield length */
9179   int bstr;             /* bitfield starting bit within byte */
9180   int litval;           /* source literal value (if AOP_LIT) */
9181   unsigned char mask;   /* bitmask within current byte */
9182
9183   FENTRY;
9184   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9185
9186   blen = SPEC_BLEN (etype);
9187   bstr = SPEC_BSTR (etype);
9188
9189   /* If the bitfield length is less than a byte and does not cross byte boundaries */
9190   if ((blen <= 8) && ((bstr + blen) <= 8))
9191   {
9192     mask = ((unsigned char) (0xFF << (blen + bstr)) |
9193             (unsigned char) (0xFF >> (8 - bstr)));
9194
9195     if (AOP_TYPE (right) == AOP_LIT)
9196     {
9197       /* Case with a bitfield length <8 and literal source */
9198       int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9199       if (blen == 1) {
9200         pCodeOp *pcop;
9201         
9202         switch (p_type)
9203         {
9204         case -1:
9205           if (AOP(result)->type == AOP_PCODE)
9206             pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9207           else
9208             pcop = popGet(AOP(result),0);
9209           emitpcode(lit?POC_BSF:POC_BCF,pcop);
9210           break;
9211         
9212         case POINTER:
9213         case FPOINTER:
9214           setup_fsr (result);
9215           emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9216           break;
9217         
9218         case CPOINTER:
9219           assert( !"trying to assign to bitfield via pointer to __code space" );
9220           break;
9221         
9222         case GPOINTER:
9223           emitPtrByteGet(result, p_type, FALSE);
9224           if (lit) {
9225             emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9226           } else {
9227             emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9228           }
9229           emitPtrByteSet(result, p_type, TRUE);
9230           break;
9231         
9232         default:
9233           assert( !"unhandled pointer type" );
9234           break;
9235         } // switch (p_type)
9236       } else {
9237         /* blen > 1 */
9238         litval = lit << bstr;
9239         litval &= (~mask) & 0x00ff;
9240         
9241         switch (p_type)
9242         {
9243         case -1:
9244           mov2w (AOP(result), 0);
9245           if ((litval|mask) != 0x00ff)
9246             emitpcode(POC_ANDLW, popGetLit (mask));
9247           if (litval != 0x00)
9248             emitpcode(POC_IORLW, popGetLit (litval));
9249           movwf (AOP(result), 0);
9250           break;
9251         
9252         case POINTER:
9253         case FPOINTER:
9254         case GPOINTER:
9255           emitPtrByteGet(result, p_type, FALSE);
9256           if ((litval|mask) != 0x00ff)
9257             emitpcode(POC_ANDLW, popGetLit (mask));
9258           if (litval != 0x00)
9259             emitpcode(POC_IORLW, popGetLit (litval));
9260           emitPtrByteSet(result, p_type, TRUE);
9261           break;
9262         
9263         case CPOINTER:
9264           assert( !"trying to assign to bitfield via pointer to __code space" );
9265           break;
9266         
9267         default:
9268           assert( !"unhandled pointer type" );
9269           break;
9270         } // switch
9271       } // if (blen > 1)
9272     }
9273     else
9274     {
9275       /* right is no literal */
9276       if (blen==1) {
9277         switch (p_type)
9278         {
9279         case -1:
9280           /* Note more efficient code, of pre clearing bit then only setting it if required,
9281            * can only be done if it is known that the result is not a SFR */
9282           emitpcode(POC_RRFW,popGet(AOP(right),0));
9283           emitSKPC;
9284           emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9285           emitSKPNC;
9286           emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9287           break;
9288         
9289         case POINTER:
9290         case FPOINTER:
9291         case GPOINTER:
9292           emitPtrByteGet (result, p_type, FALSE);
9293           emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9294           emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9295           emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9296           emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9297           emitPtrByteSet (result, p_type, TRUE);
9298           break;
9299         
9300         case CPOINTER:
9301           assert( !"trying to assign to bitfield via pointer to __code space" );
9302           break;
9303         
9304         default:
9305           assert( !"unhandled pointer type" );
9306           break;
9307         } // switch
9308         return;
9309       } else {
9310         /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9311         pCodeOp *temp = popGetTempReg ();
9312
9313         mov2w (AOP(right), 0);
9314         if (blen < 8) {
9315           emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9316         }
9317         emitpcode(POC_MOVWF, temp);
9318         if (bstr) {
9319           AccLsh (temp, bstr);
9320         }
9321         
9322         switch (p_type)
9323         {
9324         case -1:
9325           mov2w (AOP(result), 0);
9326           emitpcode(POC_ANDLW, popGetLit (mask));
9327           emitpcode(POC_IORFW, temp);
9328           movwf (AOP(result), 0);
9329           break;
9330         
9331         case POINTER:
9332         case FPOINTER:
9333         case GPOINTER:
9334           emitPtrByteGet (result, p_type, FALSE);
9335           emitpcode(POC_ANDLW, popGetLit (mask));
9336           emitpcode(POC_IORFW, temp);
9337           emitPtrByteSet (result, p_type, TRUE);
9338           break;
9339         
9340         case CPOINTER:
9341           assert( !"trying to assign to bitfield via pointer to __code space" );
9342           break;
9343         
9344         default:
9345           assert( !"unhandled pointer type" );
9346           break;
9347         } // switch
9348
9349         popReleaseTempReg (temp);
9350       } // if (blen > 1)
9351     } // if (AOP(right)->type != AOP_LIT)
9352     return;
9353   } // if (blen <= 8 && ((blen + bstr) <= 8))
9354
9355   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9356 }
9357
9358 /*-----------------------------------------------------------------*/
9359 /* genDataPointerSet - remat pointer to data space                 */
9360 /*-----------------------------------------------------------------*/
9361 static void genDataPointerSet(operand *right,
9362         operand *result,
9363         iCode *ic)
9364 {
9365         int size, offset = 0 ;
9366         int ressize;
9367         
9368         FENTRY;
9369         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9370         aopOp(right,ic,FALSE);
9371         aopOp(result,ic,FALSE);
9372         
9373         assert (IS_SYMOP(result));
9374         assert (IS_PTR(OP_SYM_TYPE(result)));
9375         
9376         size = AOP_SIZE(right);
9377         ressize = getSize(OP_SYM_ETYPE(result));
9378         if (size > ressize) size = ressize;
9379         //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9380         
9381         //assert( !"what's going on here?" );
9382
9383         /*
9384         if ( AOP_TYPE(result) == AOP_PCODE) {
9385         fprintf(stderr,"genDataPointerSet   %s, %d\n",
9386         AOP(result)->aopu.pcop->name,
9387         PCOI(AOP(result)->aopu.pcop)->offset);
9388         }
9389         */
9390         
9391         // tsd, was l+1 - the underline `_' prefix was being stripped
9392         while (size--) {
9393                 emitpComment ("%s:%u: size=%d/%d, offset=%i", __FILE__,__LINE__, size, ressize, offset);
9394                 
9395                 if (AOP_TYPE(right) == AOP_LIT) {
9396                         unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
9397                         //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9398                         if(lit&0xff) {
9399                                 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9400                                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9401                         } else {
9402                                 emitpcode(POC_CLRF, popGet(AOP(result), offset));
9403                         }
9404                 } else {
9405                         //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9406                         emitpcode(POC_MOVFW, popGet(AOP(right), offset));
9407                         emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9408                 }
9409                 
9410                 offset++;
9411         }
9412         
9413         freeAsmop(right,NULL,ic,TRUE);
9414         freeAsmop(result,NULL,ic,TRUE);
9415 }
9416
9417 /*-----------------------------------------------------------------*/
9418 /* genNearPointerSet - pic14_emitcode for near pointer put         */
9419 /*-----------------------------------------------------------------*/
9420 static void genNearPointerSet (operand *right,
9421                                                            operand *result, 
9422                                                            iCode *ic)
9423 {
9424         asmop *aop = NULL;
9425         sym_link *ptype = operandType(result);
9426         sym_link *retype = getSpec(operandType(right));
9427         sym_link *letype = getSpec(ptype);
9428         int direct = 0;
9429         
9430         
9431         FENTRY;
9432         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9433         aopOp(result,ic,FALSE);
9434         
9435 #if 1
9436         /* if the result is rematerializable &
9437         in data space & not a bit variable */
9438         //if (AOP_TYPE(result) == AOP_IMMD &&
9439         if (AOP_TYPE(result) == AOP_PCODE &&
9440                 PIC_IS_DATA_PTR(ptype) &&
9441                 !IS_BITVAR (retype) &&
9442                 !IS_BITVAR (letype)) {
9443                 genDataPointerSet (right,result,ic);
9444                 freeAsmop(result,NULL,ic,TRUE);
9445                 return;
9446         }
9447 #endif
9448
9449         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9450         aopOp(right,ic,FALSE);
9451         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9452         
9453         /* Check if can access directly instead of via a pointer */
9454         if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9455                 direct = 1;
9456         }
9457         
9458         if (IS_BITFIELD (letype))
9459         {
9460           genPackBits (letype, result, right, direct?-1:POINTER);
9461           return;
9462         }
9463         
9464         /* If the pointer value is not in a the FSR then need to put it in */
9465         /* Must set/reset IRP bit for use with FSR. */
9466         /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9467         if (!direct)
9468                 setup_fsr (result);
9469
9470         {
9471                 /* we have can just get the values */
9472                 int size = AOP_SIZE(right);
9473                 int offset = 0 ;    
9474                 
9475                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9476                 while (size--) {
9477                         char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9478                         if (*l == '@' ) {
9479                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9480                         } else {
9481                                 if (AOP_TYPE(right) == AOP_LIT) {
9482                                         emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9483                                 } else {
9484                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9485                                 }
9486                                 if (direct)
9487                                         emitpcode(POC_MOVWF,popGet(AOP(result),0));
9488                                 else
9489                                         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9490                         }
9491                         if (size && !direct)
9492                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9493                         offset++;
9494                 }
9495         }
9496         
9497         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9498         /* now some housekeeping stuff */
9499         if (aop) {
9500                 /* we had to allocate for this iCode */
9501                 freeAsmop(NULL,aop,ic,TRUE);
9502         } else { 
9503                 /* we did not allocate which means left
9504                 already in a pointer register, then
9505                 if size > 0 && this could be used again
9506                 we have to point it back to where it 
9507                 belongs */
9508                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9509                 if (AOP_SIZE(right) > 1 &&
9510                         !OP_SYMBOL(result)->remat &&
9511                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9512                         ic->depth )) {
9513                         int size = AOP_SIZE(right) - 1;
9514                         while (size--)
9515                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9516                 }
9517         }
9518         
9519         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9520         /* done */
9521
9522         freeAsmop(right,NULL,ic,TRUE);
9523         freeAsmop(result,NULL,ic,TRUE);
9524 }
9525
9526 #if 0
9527 /*-----------------------------------------------------------------*/
9528 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
9529 /*-----------------------------------------------------------------*/
9530 static void genPagedPointerSet (operand *right,
9531                                                                 operand *result, 
9532                                                                 iCode *ic)
9533 {
9534         asmop *aop = NULL;
9535         regs *preg = NULL ;
9536         char *rname , *l;
9537         sym_link *retype;
9538         
9539         FENTRY;
9540         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9541         
9542         retype= getSpec(operandType(right));
9543         
9544         aopOp(result,ic,FALSE);
9545         
9546         /* if the value is already in a pointer register
9547         then don't need anything more */
9548         if (!AOP_INPREG(AOP(result))) {
9549                 /* otherwise get a free pointer register */
9550                 aop = newAsmop(0);
9551                 preg = getFreePtr(ic,&aop,FALSE);
9552                 pic14_emitcode("mov","%s,%s",
9553                         preg->name,
9554                         aopGet(AOP(result),0,FALSE,TRUE));
9555                 rname = preg->name ;
9556         } else
9557                 rname = aopGet(AOP(result),0,FALSE,FALSE);
9558         
9559         freeAsmop(result,NULL,ic,TRUE);
9560         aopOp (right,ic,FALSE);
9561         
9562         /* if bitfield then unpack the bits */
9563         if (IS_BITFIELD(retype)) 
9564                 genPackBits (retype,result,right,rname,PPOINTER);
9565         else {
9566                 /* we have can just get the values */
9567                 int size = AOP_SIZE(right);
9568                 int offset = 0 ;  
9569                 
9570                 while (size--) {
9571                         l = aopGet(AOP(right),offset,FALSE,TRUE);
9572                         
9573                         MOVA(l);
9574                         pic14_emitcode("movx","@%s,a",rname);
9575                         
9576                         if (size)
9577                                 pic14_emitcode("inc","%s",rname);
9578                         
9579                         offset++;
9580                 }
9581         }
9582         
9583         /* now some housekeeping stuff */
9584         if (aop) {
9585                 /* we had to allocate for this iCode */
9586                 freeAsmop(NULL,aop,ic,TRUE);
9587         } else { 
9588         /* we did not allocate which means left
9589         already in a pointer register, then
9590         if size > 0 && this could be used again
9591         we have to point it back to where it 
9592                 belongs */
9593                 if (AOP_SIZE(right) > 1 &&
9594                         !OP_SYMBOL(result)->remat &&
9595                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9596                         ic->depth )) {
9597                         int size = AOP_SIZE(right) - 1;
9598                         while (size--)
9599                                 pic14_emitcode("dec","%s",rname);
9600                 }
9601         }
9602         
9603         /* done */
9604         freeAsmop(right,NULL,ic,TRUE);
9605         
9606         
9607 }
9608
9609 /*-----------------------------------------------------------------*/
9610 /* genFarPointerSet - set value from far space                     */
9611 /*-----------------------------------------------------------------*/
9612 static void genFarPointerSet (operand *right,
9613                                                           operand *result, iCode *ic)
9614 {
9615         int size, offset ;
9616         sym_link *retype = getSpec(operandType(right));
9617         
9618         FENTRY;
9619         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9620         aopOp(result,ic,FALSE);
9621         
9622         /* if the operand is already in dptr 
9623         then we do nothing else we move the value to dptr */
9624         if (AOP_TYPE(result) != AOP_STR) {
9625                 /* if this is remateriazable */
9626                 if (AOP_TYPE(result) == AOP_IMMD)
9627                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9628                 else { /* we need to get it byte by byte */
9629                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9630                         pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9631                         if (options.model == MODEL_FLAT24)
9632                         {
9633                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9634                         }
9635                 }
9636         }
9637         /* so dptr know contains the address */
9638         freeAsmop(result,NULL,ic,TRUE);
9639         aopOp(right,ic,FALSE);
9640         
9641         /* if bit then unpack */
9642         if (IS_BITFIELD(retype)) 
9643                 genPackBits(retype,result,right,"dptr",FPOINTER);
9644         else {
9645                 size = AOP_SIZE(right);
9646                 offset = 0 ;
9647                 
9648                 while (size--) {
9649                         char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9650                         MOVA(l);
9651                         pic14_emitcode("movx","@dptr,a");
9652                         if (size)
9653                                 pic14_emitcode("inc","dptr");
9654                 }
9655         }
9656         
9657         freeAsmop(right,NULL,ic,TRUE);
9658 }
9659 #endif
9660
9661 /*-----------------------------------------------------------------*/
9662 /* genGenPointerSet - set value from generic pointer space         */
9663 /*-----------------------------------------------------------------*/
9664 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9665 {
9666         sym_link *retype = getSpec(operandType(result));
9667         
9668         FENTRY;
9669         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9670         aopOp(right,ic,FALSE);
9671         aopOp(result,ic,FALSE);
9672
9673         
9674         DEBUGpic14_AopType(__LINE__,right,NULL,result);
9675
9676         if (IS_BITFIELD(retype))
9677         {
9678           genPackBits (retype, result, right, GPOINTER);
9679           return;
9680         }
9681
9682         {
9683           /* emit call to __gptrput */
9684           char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9685           int size = AOP_SIZE(right);
9686           int idx = 0;
9687
9688           assert (size == getSize(OP_SYM_ETYPE(result)));
9689           assert (size > 0 && size <= 4);
9690
9691           /* pass arguments */
9692           /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9693           {
9694             int off = size;
9695             idx = 2;
9696             while (off--)
9697             {
9698               mov2w_op (right, off);
9699               emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9700             }
9701             idx = 0;
9702           }
9703           /* - address */
9704           assert (AOP_SIZE(result) == 3);
9705           mov2w(AOP(result), 0);
9706           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9707           mov2w(AOP(result), 1);
9708           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9709           mov2w(AOP(result), 2);
9710           call_libraryfunc (func[size]);
9711         }
9712         
9713         freeAsmop(right,NULL,ic,TRUE);
9714         freeAsmop(result,NULL,ic,TRUE);
9715 }
9716
9717 /*-----------------------------------------------------------------*/
9718 /* genPointerSet - stores the value into a pointer location        */
9719 /*-----------------------------------------------------------------*/
9720 static void genPointerSet (iCode *ic)
9721 {    
9722         operand *right, *result ;
9723         sym_link *type, *etype;
9724         int p_type;
9725         
9726         FENTRY;
9727         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9728         
9729         right = IC_RIGHT(ic);
9730         result = IC_RESULT(ic) ;
9731         
9732         /* depending on the type of pointer we need to
9733         move it to the correct pointer register */
9734         type = operandType(result);
9735         etype = getSpec(type);
9736         /* if left is of type of pointer then it is simple */
9737         if (IS_PTR(type) && !IS_FUNC(type->next)) {
9738                 p_type = DCL_TYPE(type);
9739         }
9740         else {
9741                 /* we have to go by the storage class */
9742                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9743                 
9744                 /*  if (SPEC_OCLS(etype)->codesp ) { */
9745                 /*      p_type = CPOINTER ;  */
9746                 /*  } */
9747                 /*  else */
9748                 /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9749                 /*    p_type = FPOINTER ; */
9750                 /*      else */
9751                 /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9752                 /*        p_type = PPOINTER ; */
9753                 /*    else */
9754                 /*        if (SPEC_OCLS(etype) == idata ) */
9755                 /*      p_type = IPOINTER ; */
9756                 /*        else */
9757                 /*      p_type = POINTER ; */
9758         }
9759         
9760         /* now that we have the pointer type we assign
9761         the pointer values */
9762         switch (p_type) {
9763                 
9764         case POINTER:
9765         case FPOINTER:
9766         //case IPOINTER:
9767                 genNearPointerSet (right,result,ic);
9768                 break;
9769 /*
9770         case PPOINTER:
9771                 genPagedPointerSet (right,result,ic);
9772                 break;
9773                 
9774         case FPOINTER:
9775                 genFarPointerSet (right,result,ic);
9776                 break;
9777 */
9778         case GPOINTER:
9779                 genGenPointerSet (right,result,ic);
9780                 break;
9781                 
9782         default:
9783                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9784                         "genPointerSet: illegal pointer type");
9785         }
9786 }
9787
9788 /*-----------------------------------------------------------------*/
9789 /* genIfx - generate code for Ifx statement                        */
9790 /*-----------------------------------------------------------------*/
9791 static void genIfx (iCode *ic, iCode *popIc)
9792 {
9793         operand *cond = IC_COND(ic);
9794         int isbit =0;
9795         
9796         FENTRY;
9797         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9798         
9799         aopOp(cond,ic,FALSE);
9800         
9801         /* get the value into acc */
9802         if (AOP_TYPE(cond) != AOP_CRY)
9803                 pic14_toBoolean(cond);
9804         else
9805                 isbit = 1;
9806         
9807         /* if there was something to be popped then do it */
9808         if (popIc)
9809                 genIpop(popIc);
9810         
9811         if (isbit)
9812         {
9813                 /* This assumes that CARRY is set iff cond is true */
9814                 if (IC_TRUE(ic))
9815                 {
9816                         assert (!IC_FALSE(ic));
9817                         emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9818                         //emitSKPNC;
9819                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9820                 } else {
9821                         assert (IC_FALSE(ic));
9822                         emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9823                         //emitSKPC;
9824                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9825                 }
9826                 if (0)
9827                 {
9828                         static int hasWarned = 0;
9829                         if (!hasWarned)
9830                         {
9831                                 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9832                                 hasWarned = 1;
9833                         }
9834                 }
9835         }
9836         else
9837         {
9838                 /* now Z is set iff !cond */
9839                 if (IC_TRUE(ic))
9840                 {
9841                         assert (!IC_FALSE(ic));
9842                         emitSKPZ;
9843                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9844                 } else {
9845                         emitSKPNZ;
9846                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9847                 }
9848         }
9849         
9850         ic->generated = 1;
9851         
9852         /* the result is now in the accumulator */
9853         freeAsmop(cond,NULL,ic,TRUE);
9854 }
9855
9856 /*-----------------------------------------------------------------*/
9857 /* genAddrOf - generates code for address of                       */
9858 /*-----------------------------------------------------------------*/
9859 static void genAddrOf (iCode *ic)
9860 {
9861         operand *right, *result, *left;
9862         int size, offset ;
9863         
9864         FENTRY;
9865         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9866         
9867         
9868         //aopOp(IC_RESULT(ic),ic,FALSE);
9869         
9870         aopOp((left=IC_LEFT(ic)),ic,FALSE);
9871         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9872         aopOp((result=IC_RESULT(ic)),ic,TRUE);
9873         
9874         DEBUGpic14_AopType(__LINE__,left,right,result);
9875         assert (IS_SYMOP (left));
9876         
9877         /* sanity check: generic pointers to code space are not yet supported,
9878          * pionters to codespace must not be assigned addresses of __data values. */
9879  #if 0
9880         fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9881         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)));
9882         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)));
9883         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)));
9884         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)));
9885 #endif
9886
9887         if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9888           fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9889                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9890                 OP_SYMBOL(left)->name);
9891         } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9892           fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9893                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9894                 OP_SYMBOL(left)->name);
9895         }
9896         
9897         size = AOP_SIZE(IC_RESULT(ic));
9898         if (IS_GENPTR(OP_SYM_TYPE(result))) {
9899                 /* strip tag */
9900                 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9901         }
9902         offset = 0;
9903         
9904         while (size--) {
9905                 /* fixing bug #863624, reported from (errolv) */
9906                 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9907                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9908                 
9909 #if 0
9910                 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9911                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9912 #endif
9913                 offset++;
9914         }
9915
9916         if (IS_GENPTR(OP_SYM_TYPE(result)))
9917         {
9918                 /* provide correct tag */
9919                 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9920                 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9921                 movwf (AOP(result), 2);
9922         }
9923         
9924         freeAsmop(left,NULL,ic,FALSE);
9925         freeAsmop(result,NULL,ic,TRUE);
9926         
9927 }
9928
9929 #if 0
9930 /*-----------------------------------------------------------------*/
9931 /* genFarFarAssign - assignment when both are in far space         */
9932 /*-----------------------------------------------------------------*/
9933 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9934 {
9935         int size = AOP_SIZE(right);
9936         int offset = 0;
9937         char *l ;
9938         /* first push the right side on to the stack */
9939         while (size--) {
9940                 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9941                 MOVA(l);
9942                 pic14_emitcode ("push","acc");
9943         }
9944         
9945         freeAsmop(right,NULL,ic,FALSE);
9946         /* now assign DPTR to result */
9947         aopOp(result,ic,FALSE);
9948         size = AOP_SIZE(result);
9949         while (size--) {
9950                 pic14_emitcode ("pop","acc");
9951                 aopPut(AOP(result),"a",--offset);
9952         }
9953         freeAsmop(result,NULL,ic,FALSE);
9954         
9955 }
9956 #endif
9957
9958 /*-----------------------------------------------------------------*/
9959 /* genAssign - generate code for assignment                        */
9960 /*-----------------------------------------------------------------*/
9961 static void genAssign (iCode *ic)
9962 {
9963         operand *result, *right;
9964         int size, offset,know_W;
9965         unsigned long lit = 0L;
9966         
9967         result = IC_RESULT(ic);
9968         right  = IC_RIGHT(ic) ;
9969         
9970         FENTRY;
9971         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9972         
9973         /* if they are the same */
9974         if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9975                 return ;
9976         
9977         aopOp(right,ic,FALSE);
9978         aopOp(result,ic,TRUE);
9979         
9980         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9981         
9982         /* if they are the same registers */
9983         if (pic14_sameRegs(AOP(right),AOP(result)))
9984                 goto release;
9985
9986         /* special case: assign from __code */
9987         if (!IS_ITEMP(right)                            /* --> iTemps never reside in __code */
9988                 && IS_SYMOP (right)                     /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
9989                 && !IS_FUNC(OP_SYM_TYPE(right))         /* --> we would want its address instead of the first instruction */
9990                 && !IS_CODEPTR(OP_SYM_TYPE(right))      /* --> get symbols address instread */
9991                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
9992         {
9993           emitpComment ("genAssign from CODESPACE");
9994           genConstPointerGet (right, result, ic);
9995           goto release;
9996         }
9997         
9998         /* just for symmetry reasons... */
9999         if (!IS_ITEMP(result)
10000                 && IS_SYMOP (result)
10001                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
10002         {
10003           assert ( !"cannot write to CODESPACE" );
10004         }
10005
10006         /* if the result is a bit */
10007         if (AOP_TYPE(result) == AOP_CRY) {
10008                 
10009         /* if the right size is a literal then
10010                 we know what the value is */
10011                 if (AOP_TYPE(right) == AOP_LIT) {
10012                         
10013                         emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10014                                 popGet(AOP(result),0));
10015                         
10016                         if (((int) operandLitValue(right))) 
10017                                 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10018                                 AOP(result)->aopu.aop_dir,
10019                                 AOP(result)->aopu.aop_dir);
10020                         else
10021                                 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10022                                 AOP(result)->aopu.aop_dir,
10023                                 AOP(result)->aopu.aop_dir);
10024                         goto release;
10025                 }
10026                 
10027                 /* the right is also a bit variable */
10028                 if (AOP_TYPE(right) == AOP_CRY) {
10029                         emitpcode(POC_BCF,    popGet(AOP(result),0));
10030                         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10031                         emitpcode(POC_BSF,    popGet(AOP(result),0));
10032                         
10033                         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10034                                 AOP(result)->aopu.aop_dir,
10035                                 AOP(result)->aopu.aop_dir);
10036                         pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10037                                 AOP(right)->aopu.aop_dir,
10038                                 AOP(right)->aopu.aop_dir);
10039                         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10040                                 AOP(result)->aopu.aop_dir,
10041                                 AOP(result)->aopu.aop_dir);
10042                         goto release ;
10043                 }
10044                 
10045                 /* we need to or */
10046                 emitpcode(POC_BCF,    popGet(AOP(result),0));
10047                 pic14_toBoolean(right);
10048                 emitSKPZ;
10049                 emitpcode(POC_BSF,    popGet(AOP(result),0));
10050                 //aopPut(AOP(result),"a",0);
10051                 goto release ;
10052         }
10053         
10054         /* bit variables done */
10055         /* general case */
10056         size = AOP_SIZE(result);
10057         offset = 0 ;
10058         if(AOP_TYPE(right) == AOP_LIT)
10059                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10060         
10061         if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10062                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10063                 if(aopIdx(AOP(result),0) == 4) {
10064                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10065                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10066                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10067                         goto release;
10068                 } else
10069                         DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10070         }
10071         
10072         know_W=-1;
10073         while (size--) {
10074                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10075                 if(AOP_TYPE(right) == AOP_LIT) {
10076                         if(lit&0xff) {
10077                                 if(know_W != (int)(lit&0xff))
10078                                         emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10079                                 know_W = lit&0xff;
10080                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10081                         } else
10082                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10083                         
10084                         lit >>= 8;
10085                         
10086                 } else if (AOP_TYPE(right) == AOP_CRY) {
10087                         emitpcode(POC_CLRF, popGet(AOP(result),offset));
10088                         if(offset == 0) {
10089                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10090                                 emitpcode(POC_INCF, popGet(AOP(result),0));
10091                         }
10092                 } else {
10093                         mov2w_op (right, offset);
10094                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10095                 }
10096                 
10097                 offset++;
10098         }
10099         
10100         
10101 release:
10102         freeAsmop (right,NULL,ic,FALSE);
10103         freeAsmop (result,NULL,ic,TRUE);
10104 }   
10105
10106 /*-----------------------------------------------------------------*/
10107 /* genJumpTab - genrates code for jump table                       */
10108 /*-----------------------------------------------------------------*/
10109 static void genJumpTab (iCode *ic)
10110 {
10111         symbol *jtab;
10112         char *l;
10113         
10114         FENTRY;
10115         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10116         
10117         aopOp(IC_JTCOND(ic),ic,FALSE);
10118         /* get the condition into accumulator */
10119         l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10120         MOVA(l);
10121         /* multiply by three */
10122         pic14_emitcode("add","a,acc");
10123         pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10124         
10125         jtab = newiTempLabel(NULL);
10126         pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10127         pic14_emitcode("jmp","@a+dptr");
10128         pic14_emitcode("","%05d_DS_:",jtab->key+100);
10129         
10130         emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10131         emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10132         emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10133         emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10134         emitSKPNC;
10135         emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10136         emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10137         emitpLabel(jtab->key);
10138         
10139         freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10140         
10141         /* now generate the jump labels */
10142         for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10143         jtab = setNextItem(IC_JTLABELS(ic))) {
10144                 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10145                 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10146                 
10147         }
10148         
10149 }
10150
10151 /*-----------------------------------------------------------------*/
10152 /* genMixedOperation - gen code for operators between mixed types  */
10153 /*-----------------------------------------------------------------*/
10154 /*
10155 TSD - Written for the PIC port - but this unfortunately is buggy.
10156 This routine is good in that it is able to efficiently promote 
10157 types to different (larger) sizes. Unfortunately, the temporary
10158 variables that are optimized out by this routine are sometimes
10159 used in other places. So until I know how to really parse the 
10160 iCode tree, I'm going to not be using this routine :(.
10161 */
10162 static int genMixedOperation (iCode *ic)
10163 {
10164         FENTRY;
10165 #if 0
10166         operand *result = IC_RESULT(ic);
10167         sym_link *ctype = operandType(IC_LEFT(ic));
10168         operand *right = IC_RIGHT(ic);
10169         int ret = 0;
10170         int big,small;
10171         int offset;
10172         
10173         iCode *nextic;
10174         operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10175         
10176         pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10177         
10178         nextic = ic->next;
10179         if(!nextic)
10180                 return 0;
10181         
10182         nextright = IC_RIGHT(nextic);
10183         nextleft  = IC_LEFT(nextic);
10184         nextresult = IC_RESULT(nextic);
10185         
10186         aopOp(right,ic,FALSE);
10187         aopOp(result,ic,FALSE);
10188         aopOp(nextright,  nextic, FALSE);
10189         aopOp(nextleft,   nextic, FALSE);
10190         aopOp(nextresult, nextic, FALSE);
10191         
10192         if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10193                 
10194                 operand *t = right;
10195                 right = nextright;
10196                 nextright = t; 
10197                 
10198                 pic14_emitcode(";remove right +","");
10199                 
10200         } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10201         /*
10202         operand *t = right;
10203         right = nextleft;
10204         nextleft = t; 
10205                 */
10206                 pic14_emitcode(";remove left +","");
10207         } else
10208                 return 0;
10209         
10210         big = AOP_SIZE(nextleft);
10211         small = AOP_SIZE(nextright);
10212         
10213         switch(nextic->op) {
10214                 
10215         case '+':
10216                 pic14_emitcode(";optimize a +","");
10217                 /* if unsigned or not an integral type */
10218                 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10219                         pic14_emitcode(";add a bit to something","");
10220                 } else {
10221                         
10222                         pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10223                         
10224                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10225                                 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10226                                 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10227                         } else
10228                                 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10229                         
10230                         offset = 0;
10231                         while(--big) {
10232                                 
10233                                 offset++;
10234                                 
10235                                 if(--small) {
10236                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10237                                                 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10238                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10239                                         }
10240                                         
10241                                         pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10242                                         emitSKPNC;
10243                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10244                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10245                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10246                                         pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10247                                         pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10248                                         
10249                                 } else {
10250                                         pic14_emitcode("rlf","known_zero,w");
10251                                         
10252                                         /*
10253                                         if right is signed
10254                                         btfsc  right,7
10255                                         addlw ff
10256                                         */
10257                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10258                                                 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10259                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10260                                         } else {
10261                                                 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10262                                         }
10263                                 }
10264                         }
10265                         ret = 1;
10266                 }
10267         }
10268         ret = 1;
10269         
10270 release:
10271         freeAsmop(right,NULL,ic,TRUE);
10272         freeAsmop(result,NULL,ic,TRUE);
10273         freeAsmop(nextright,NULL,ic,TRUE);
10274         freeAsmop(nextleft,NULL,ic,TRUE);
10275         if(ret)
10276                 nextic->generated = 1;
10277         
10278         return ret;
10279 #else
10280         return 0;
10281 #endif
10282 }
10283 /*-----------------------------------------------------------------*/
10284 /* genCast - gen code for casting                                  */
10285 /*-----------------------------------------------------------------*/
10286 static void genCast (iCode *ic)
10287 {
10288         operand *result = IC_RESULT(ic);
10289         sym_link *restype = operandType(result);
10290         sym_link *rtype = operandType(IC_RIGHT(ic));
10291         operand *right = IC_RIGHT(ic);
10292         int size, offset ;
10293         
10294         FENTRY;
10295         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10296         /* if they are equivalent then do nothing */
10297         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10298                 return ;
10299         
10300         aopOp(right,ic,FALSE) ;
10301         aopOp(result,ic,FALSE);
10302         
10303         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10304         
10305         /* if the result is a bit */
10306         if (AOP_TYPE(result) == AOP_CRY) {
10307                 assert(!"assigning to bit variables is not supported");
10308         }
10309         
10310         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10311                 int offset = 1;
10312                 size = AOP_SIZE(result);
10313                 
10314                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10315                 
10316                 emitpcode(POC_CLRF,   popGet(AOP(result),0));
10317                 emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10318                 emitpcode(POC_INCF,   popGet(AOP(result),0));
10319                 
10320                 while (size--)
10321                         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
10322                 
10323                 goto release;
10324         }
10325         
10326         if (IS_PTR(restype))
10327         {
10328           operand *result = IC_RESULT(ic);
10329           //operand *left = IC_LEFT(ic);
10330           operand *right = IC_RIGHT(ic);
10331           int tag = 0xff;
10332           
10333           /* copy common part */
10334           int max, size = AOP_SIZE(result);
10335           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10336           DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10337
10338           /* warn if we discard generic opinter tag */
10339           if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10340           {
10341             //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10342           } // if
10343
10344           max = size;
10345           while (size--)
10346           {
10347             mov2w_op (right, size);
10348             movwf (AOP(result), size);
10349           } // while
10350
10351           /* upcast into generic pointer type? */
10352           if (IS_GENPTR(restype)
10353                 && (size < AOP_SIZE(result))
10354                 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10355           {
10356             //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10357             if (IS_PTR(rtype))
10358             {
10359               switch (DCL_TYPE(rtype))
10360               {
10361               case POINTER:     /* __data */
10362               case FPOINTER:    /* __data */
10363                 assert (AOP_SIZE(right) == 2);
10364                 tag = GPTRTAG_DATA;
10365                 break;
10366
10367               case CPOINTER:    /* __code */
10368                 assert (AOP_SIZE(right) == 2);
10369                 tag = GPTRTAG_CODE;
10370                 break;
10371                 
10372               case GPOINTER:    /* unknown destination, __data or __code */
10373                 /* assume __data space (address of immediate) */
10374                 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10375                 if (AOP(right)->code)
10376                   tag = GPTRTAG_CODE;
10377                 else
10378                   tag = GPTRTAG_DATA;
10379                 break;
10380                 
10381               default:
10382                 assert (!"unhandled pointer type");
10383               } // switch
10384             } else {
10385               /* convert other values into pointers to __data space */
10386               tag = GPTRTAG_DATA;
10387             }
10388
10389             assert (AOP_SIZE(result) == 3);
10390             if (tag == 0) {
10391               emitpcode(POC_CLRF, popGet(AOP(result), 2));
10392             } else {
10393               emitpcode(POC_MOVLW, popGetLit(tag));
10394               movwf(AOP(result), 2);
10395             }
10396           } else {
10397             addSign(result, max, 0);
10398           } // if
10399           goto release;
10400         }
10401         
10402         /* if they are the same size : or less */
10403         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10404                 
10405                 /* if they are in the same place */
10406                 if (pic14_sameRegs(AOP(right),AOP(result)))
10407                         goto release;
10408                 
10409                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10410                 if (IS_PTR_CONST(rtype))
10411                         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10412                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10413                         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10414                 
10415                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10416                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10417                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
10418                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10419                         emitpcode(POC_MOVWF, popGet(AOP(result),1));
10420                         if(AOP_SIZE(result) <2)
10421                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10422                         
10423                 } else {
10424                         
10425                         /* if they in different places then copy */
10426                         size = AOP_SIZE(result);
10427                         offset = 0 ;
10428                         while (size--) {
10429                                 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10430                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10431                                 
10432                                 //aopPut(AOP(result),
10433                                 // aopGet(AOP(right),offset,FALSE,FALSE),
10434                                 // offset);
10435                                 
10436                                 offset++;
10437                         }
10438                 }
10439                 goto release;
10440         }
10441         
10442         /* so we now know that the size of destination is greater
10443         than the size of the source.
10444         Now, if the next iCode is an operator then we might be
10445         able to optimize the operation without performing a cast.
10446         */
10447         if(0 && genMixedOperation(ic)) {
10448                 /* XXX: cannot optimize: must copy regs! */
10449                 goto release;
10450         }
10451         
10452         /* we move to result for the size of source */
10453         size = AOP_SIZE(right);
10454         offset = 0 ;
10455         while (size--) {
10456                 emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
10457                 emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
10458                 offset++;
10459         }
10460
10461         addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10462
10463 release:
10464         freeAsmop(right,NULL,ic,TRUE);
10465         freeAsmop(result,NULL,ic,TRUE);
10466         
10467 }
10468
10469 /*-----------------------------------------------------------------*/
10470 /* genDjnz - generate decrement & jump if not zero instrucion      */
10471 /*-----------------------------------------------------------------*/
10472 static int genDjnz (iCode *ic, iCode *ifx)
10473 {
10474         symbol *lbl, *lbl1;
10475         FENTRY;
10476         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10477         
10478         if (!ifx)
10479                 return 0;
10480         
10481                 /* if the if condition has a false label
10482         then we cannot save */
10483         if (IC_FALSE(ifx))
10484                 return 0;
10485         
10486                 /* if the minus is not of the form 
10487         a = a - 1 */
10488         if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10489                 !IS_OP_LITERAL(IC_RIGHT(ic)))
10490                 return 0;
10491         
10492         if (operandLitValue(IC_RIGHT(ic)) != 1)
10493                 return 0;
10494         
10495                 /* if the size of this greater than one then no
10496         saving */
10497         if (getSize(operandType(IC_RESULT(ic))) > 1)
10498                 return 0;
10499         
10500         /* otherwise we can save BIG */
10501         lbl = newiTempLabel(NULL);
10502         lbl1= newiTempLabel(NULL);
10503         
10504         aopOp(IC_RESULT(ic),ic,FALSE);
10505         
10506         if (IS_AOP_PREG(IC_RESULT(ic))) {
10507                 pic14_emitcode("dec","%s",
10508                         aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10509                 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10510                 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10511         } else {  
10512                 
10513                 
10514                 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10515                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10516                 
10517                 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10518                 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10519                 
10520         }
10521         /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10522         /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10523         /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10524         /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10525         
10526         
10527         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10528         ifx->generated = 1;
10529         return 1;
10530 }
10531
10532 /*-----------------------------------------------------------------*/
10533 /* genReceive - generate code for a receive iCode                  */
10534 /*-----------------------------------------------------------------*/
10535 static void genReceive (iCode *ic)
10536 {
10537         FENTRY;
10538         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10539         
10540         if (isOperandInFarSpace(IC_RESULT(ic)) &&
10541                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10542                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10543                 
10544                 int size = getSize(operandType(IC_RESULT(ic)));
10545                 int offset =  fReturnSizePic - size;
10546                 while (size--) {
10547                         pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10548                                 fReturn[fReturnSizePic - offset - 1] : "acc"));
10549                         offset++;
10550                 }
10551                 aopOp(IC_RESULT(ic),ic,FALSE);
10552                 size = AOP_SIZE(IC_RESULT(ic));
10553                 offset = 0;
10554                 while (size--) {
10555                         pic14_emitcode ("pop","acc");
10556                         aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10557                 }
10558                 
10559         } else {
10560                 _G.accInUse++;
10561                 aopOp(IC_RESULT(ic),ic,FALSE);
10562                 _G.accInUse--;
10563                 assignResultValue(IC_RESULT(ic));
10564         }
10565         
10566         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10567 }
10568
10569 /*-----------------------------------------------------------------*/
10570 /* genDummyRead - generate code for dummy read of volatiles        */
10571 /*-----------------------------------------------------------------*/
10572 static void
10573 genDummyRead (iCode * ic)
10574 {
10575         FENTRY;
10576         pic14_emitcode ("; genDummyRead","");
10577         pic14_emitcode ("; not implemented","");
10578         
10579         ic = ic;
10580 }
10581
10582 /*-----------------------------------------------------------------*/
10583 /* genpic14Code - generate code for pic14 based controllers        */
10584 /*-----------------------------------------------------------------*/
10585 /*
10586 * At this point, ralloc.c has gone through the iCode and attempted
10587 * to optimize in a way suitable for a PIC. Now we've got to generate
10588 * PIC instructions that correspond to the iCode.
10589 *
10590 * Once the instructions are generated, we'll pass through both the
10591 * peep hole optimizer and the pCode optimizer.
10592 *-----------------------------------------------------------------*/
10593
10594 void genpic14Code (iCode *lic)
10595 {
10596         iCode *ic;
10597         int cln = 0;
10598         const char *cline;
10599         
10600         FENTRY;
10601         lineHead = lineCurr = NULL;
10602         
10603         pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10604         addpBlock(pb);
10605         
10606         /* if debug information required */
10607         if (options.debug && currFunc) { 
10608                 if (currFunc) {
10609                         debugFile->writeFunction (currFunc, lic);
10610                 }
10611         }
10612         
10613         
10614         for (ic = lic ; ic ; ic = ic->next ) {
10615                 
10616                 //DEBUGpic14_emitcode(";ic","");
10617                 //fprintf (stderr, "in ic loop\n");
10618                 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10619                 //ic->lineno, printCLine(ic->filename, ic->lineno));
10620                 
10621                 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10622                   cln = ic->lineno;
10623                   //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10624                   cline = printCLine (ic->filename, ic->lineno);
10625                   if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10626                   addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10627                   //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10628                 }
10629                 
10630                 if (options.iCodeInAsm) {
10631                   emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10632                 }
10633                 /* if the result is marked as
10634                 spilt and rematerializable or code for
10635                 this has already been generated then
10636                 do nothing */
10637                 if (resultRemat(ic) || ic->generated ) 
10638                         continue ;
10639                 
10640                 /* depending on the operation */
10641                 switch (ic->op) {
10642                 case '!' :
10643                         genNot(ic);
10644                         break;
10645                         
10646                 case '~' :
10647                         genCpl(ic);
10648                         break;
10649                         
10650                 case UNARYMINUS:
10651                         genUminus (ic);
10652                         break;
10653                         
10654                 case IPUSH:
10655                         genIpush (ic);
10656                         break;
10657                         
10658                 case IPOP:
10659                         /* IPOP happens only when trying to restore a 
10660                         spilt live range, if there is an ifx statement
10661                         following this pop then the if statement might
10662                         be using some of the registers being popped which
10663                         would destory the contents of the register so
10664                         we need to check for this condition and handle it */
10665                         if (ic->next            && 
10666                                 ic->next->op == IFX &&
10667                                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10668                                 genIfx (ic->next,ic);
10669                         else
10670                                 genIpop (ic);
10671                         break; 
10672                         
10673                 case CALL:
10674                         genCall (ic);
10675                         break;
10676                         
10677                 case PCALL:
10678                         genPcall (ic);
10679                         break;
10680                         
10681                 case FUNCTION:
10682                         genFunction (ic);
10683                         break;
10684                         
10685                 case ENDFUNCTION:
10686                         genEndFunction (ic);
10687                         break;
10688                         
10689                 case RETURN:
10690                         genRet (ic);
10691                         break;
10692                         
10693                 case LABEL:
10694                         genLabel (ic);
10695                         break;
10696                         
10697                 case GOTO:
10698                         genGoto (ic);
10699                         break;
10700                         
10701                 case '+' :
10702                         genPlus (ic) ;
10703                         break;
10704                         
10705                 case '-' :
10706                         if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10707                                 genMinus (ic);
10708                         break;
10709                         
10710                 case '*' :
10711                         genMult (ic);
10712                         break;
10713                         
10714                 case '/' :
10715                         genDiv (ic) ;
10716                         break;
10717                         
10718                 case '%' :
10719                         genMod (ic);
10720                         break;
10721                         
10722                 case '>' :
10723                         genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));         
10724                         break;
10725                         
10726                 case '<' :
10727                         genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10728                         break;
10729                         
10730                 case LE_OP:
10731                 case GE_OP:
10732                 case NE_OP:
10733                         
10734                         /* note these two are xlated by algebraic equivalence
10735                         during parsing SDCC.y */
10736                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10737                                 "got '>=' or '<=' shouldn't have come here");
10738                         break;  
10739                         
10740                 case EQ_OP:
10741                         genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10742                         break;      
10743                         
10744                 case AND_OP:
10745                         genAndOp (ic);
10746                         break;
10747                         
10748                 case OR_OP:
10749                         genOrOp (ic);
10750                         break;
10751                         
10752                 case '^' :
10753                         genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10754                         break;
10755                         
10756                 case '|' :
10757                         genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10758                         break;
10759                         
10760                 case BITWISEAND:
10761                         genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10762                         break;
10763                         
10764                 case INLINEASM:
10765                         genInline (ic);
10766                         break;
10767                         
10768                 case RRC:
10769                         genRRC (ic);
10770                         break;
10771                         
10772                 case RLC:
10773                         genRLC (ic);
10774                         break;
10775                         
10776                 case GETHBIT:
10777                         genGetHbit (ic);
10778                         break;
10779                         
10780                 case LEFT_OP:
10781                         genLeftShift (ic);
10782                         break;
10783                         
10784                 case RIGHT_OP:
10785                         genRightShift (ic);
10786                         break;
10787                         
10788                 case GET_VALUE_AT_ADDRESS:
10789                         genPointerGet(ic);
10790                         break;
10791                         
10792                 case '=' :
10793                         if (POINTER_SET(ic))
10794                                 genPointerSet(ic);
10795                         else
10796                                 genAssign(ic);
10797                         break;
10798                         
10799                 case IFX:
10800                         genIfx (ic,NULL);
10801                         break;
10802                         
10803                 case ADDRESS_OF:
10804                         genAddrOf (ic);
10805                         break;
10806                         
10807                 case JUMPTABLE:
10808                         genJumpTab (ic);
10809                         break;
10810                         
10811                 case CAST:
10812                         genCast (ic);
10813                         break;
10814                         
10815                 case RECEIVE:
10816                         genReceive(ic);
10817                         break;
10818                         
10819                 case SEND:
10820                         addSet(&_G.sendSet,ic);
10821                         break;
10822                         
10823                 case DUMMY_READ_VOLATILE:
10824                         genDummyRead (ic);
10825                         break;
10826                         
10827                 default :
10828                         fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10829                         ic = ic;
10830                         break;
10831                 }
10832         }
10833
10834         
10835         /* now we are ready to call the
10836         peep hole optimizer */
10837         if (!options.nopeep) {
10838                 peepHole (&lineHead);
10839         }
10840         /* now do the actual printing */
10841         printLine (lineHead,codeOutFile);
10842         
10843 #ifdef PCODE_DEBUG
10844         DFPRINTF((stderr,"printing pBlock\n\n"));
10845         printpBlock(stdout,pb);
10846 #endif
10847         
10848         return;
10849 }
10850
10851 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10852  * (meaning: representing its own address) or not (referencing its contents).
10853  * This can only be decided based on the operand's type. */
10854 int
10855 aop_isLitLike (asmop *aop)
10856 {
10857   assert (aop);
10858   if (aop->type == AOP_LIT) return 1;
10859 if (aop->type == AOP_IMMD) return 1;
10860   if ((aop->type == AOP_PCODE) &&
10861                 ((aop->aopu.pcop->type == PO_LITERAL)))
10862   {
10863     /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10864      * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10865     return 1;
10866   }
10867   return 0;
10868 }
10869
10870 int
10871 op_isLitLike (operand *op)
10872 {
10873   assert (op);
10874   if (aop_isLitLike (AOP(op))) return 1;
10875   if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10876   if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;
10877   return 0;
10878 }