* src/avr/gen.c (aopop),
[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
46 /* When changing these, you must also update the assembler template
47  * in device/lib/libsdcc/macros.inc */
48 #define GPTRTAG_DATA    0x00
49 #define GPTRTAG_CODE    0x80
50
51 /* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
52 #define PIC_IS_DATA_PTR(x)      (IS_DATA_PTR(x) || IS_FARPTR(x))
53 #define PIC_IS_FARPTR(x)        (PIC_IS_DATA_PTR(x))
54
55 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
56 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
57 void genMult8X8_8 (operand *, operand *,operand *);
58 extern void printpBlock(FILE *of, pBlock *pb);
59
60 static int labelOffset=0;
61 extern int debug_verbose;
62 extern int pic14_hasInterrupt;
63 //static int optimized_for_speed = 0;
64
65 /* max_key keeps track of the largest label number used in 
66 a function. This is then used to adjust the label offset
67 for the next function.
68 */
69 static int max_key=0;
70 static int GpsuedoStkPtr=0;
71
72 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
73 extern char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
74 unsigned int pic14aopLiteral (value *val, int offset);
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_calloc(1,strlen(s)+1);
1214                 strcpy(rs,s);   
1215                 return rs;
1216                 
1217         case AOP_STR:
1218                 aop->coff = offset ;
1219                 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1220                         dname)
1221                         return "acc";
1222                 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1223                 
1224                 return aop->aopu.aop_str[offset];
1225                 
1226         case AOP_PCODE:
1227                 {
1228                         pCodeOp *pcop = aop->aopu.pcop;
1229                         DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1230                         if(pcop->name) {
1231                                 if (offset) {
1232                                         DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1233                                         sprintf(s,"(%s+%d)", pcop->name,offset);
1234                                 } else {
1235                                         DEBUGpic14_emitcode(";","%s",pcop->name);
1236                                         sprintf(s,"%s", pcop->name);
1237                                 }
1238                         } else
1239                                 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1240                         
1241                 }
1242                 rs = Safe_calloc(1,strlen(s)+1);
1243                 strcpy(rs,s);   
1244                 return rs;
1245                 
1246   }
1247   
1248   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1249           "aopget got unsupported aop->type");
1250   exit(0);
1251 }
1252
1253
1254 /*-----------------------------------------------------------------*/
1255 /* popGetTempReg - create a new temporary pCodeOp                                  */
1256 /*-----------------------------------------------------------------*/
1257 pCodeOp *popGetTempReg(void)
1258 {
1259         
1260         pCodeOp *pcop;
1261         
1262         pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1263         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1264                 PCOR(pcop)->r->wasUsed=1;
1265                 PCOR(pcop)->r->isFree=0;
1266         }
1267         
1268         return pcop;
1269 }
1270
1271 /*-----------------------------------------------------------------*/
1272 /* popReleaseTempReg - create a new temporary pCodeOp                              */
1273 /*-----------------------------------------------------------------*/
1274 void popReleaseTempReg(pCodeOp *pcop)
1275 {
1276         
1277         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1278                 PCOR(pcop)->r->isFree = 1;
1279         
1280 }
1281 /*-----------------------------------------------------------------*/
1282 /* popGetLabel - create a new pCodeOp of type PO_LABEL                     */
1283 /*-----------------------------------------------------------------*/
1284 pCodeOp *popGetLabel(unsigned int key)
1285 {
1286         
1287         DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1288         
1289         if(key>(unsigned int)max_key)
1290                 max_key = key;
1291         
1292         return newpCodeOpLabel(NULL,key+100+labelOffset);
1293 }
1294
1295 /*-------------------------------------------------------------------*/
1296 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1297 /*-------------------------------------------------------------------*/
1298 pCodeOp *popGetHighLabel(unsigned int key)
1299 {
1300         pCodeOp *pcop;
1301         pcop = popGetLabel(key);
1302         PCOLAB(pcop)->offset = 1;
1303         return pcop;
1304 }
1305
1306 /*-----------------------------------------------------------------*/
1307 /* popGetLit - asm operator to pcode operator conversion                           */
1308 /*-----------------------------------------------------------------*/
1309 pCodeOp *popGetLit(unsigned int lit)
1310 {
1311         
1312         return newpCodeOpLit((unsigned char)lit);
1313 }
1314
1315 /*-----------------------------------------------------------------*/
1316 /* popGetImmd - asm operator to pcode immediate conversion                 */
1317 /*-----------------------------------------------------------------*/
1318 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1319 {
1320         
1321         return newpCodeOpImmd(name, offset,index, 0, is_func);
1322 }
1323
1324 extern set *externs;
1325
1326 /*-----------------------------------------------------------------*/
1327 /* popGetWithString - asm operator to pcode operator conversion                    */
1328 /*-----------------------------------------------------------------*/
1329 pCodeOp *popGetWithString(char *str, int isExtern)
1330 {
1331         pCodeOp *pcop;
1332         
1333         
1334         if(!str) {
1335                 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1336                 exit (1);
1337         }
1338         
1339         pcop = newpCodeOp(str,PO_STR);
1340         PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1341
1342         return pcop;
1343 }
1344
1345 pCodeOp *popGetExternal (char *str)
1346 {
1347         pCodeOp *pcop = popGetWithString (str, 1);
1348         
1349         if (str) {
1350           symbol *sym;
1351           bool found = 0;
1352
1353           for (sym = setFirstItem (externs); !found && sym; sym = setNextItem (externs))
1354           {
1355             if (!strcmp (str, sym->rname))
1356               found = 1;
1357           }
1358           
1359           if (!found)
1360           {
1361             sym = newSymbol(str, 0);
1362             strncpy(sym->rname, str, SDCC_NAME_MAX);
1363             addSet (&externs, sym);
1364           } // if
1365         }
1366         return pcop;
1367 }
1368
1369 /*-----------------------------------------------------------------*/
1370 /* popRegFromString -                                                                                      */
1371 /*-----------------------------------------------------------------*/
1372 pCodeOp *popRegFromString(char *str, int size, int offset)
1373 {
1374         
1375         pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1376         pcop->type = PO_DIR;
1377         
1378         DEBUGpic14_emitcode(";","%d",__LINE__);
1379         
1380         if(!str)
1381                 str = "BAD_STRING";
1382         
1383         pcop->name = Safe_calloc(1,strlen(str)+1);
1384         strcpy(pcop->name,str);
1385         
1386         //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1387         
1388         PCOR(pcop)->r = dirregWithName(pcop->name);
1389         if(PCOR(pcop)->r == NULL) {
1390                 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1391                 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1392                 DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1393         } else {
1394                 DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1395         }
1396         PCOR(pcop)->instance = offset;
1397         
1398         return pcop;
1399 }
1400
1401 /*-----------------------------------------------------------------*/
1402 /*-----------------------------------------------------------------*/
1403 pCodeOp *popRegFromIdx(int rIdx)
1404 {
1405         pCodeOp *pcop;
1406         
1407         DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1408                 __FUNCTION__,__LINE__,rIdx);
1409         
1410         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1411         
1412         PCOR(pcop)->rIdx = rIdx;
1413         PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1414         PCOR(pcop)->r->isFree = 0;
1415         PCOR(pcop)->r->wasUsed = 1;
1416         
1417         pcop->type = PCOR(pcop)->r->pc_type;
1418         
1419         
1420         return pcop;
1421 }
1422
1423 /*-----------------------------------------------------------------*/
1424 /* popGet - asm operator to pcode operator conversion                      */
1425 /*-----------------------------------------------------------------*/
1426 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1427 {
1428         //char *s = buffer ;
1429         //char *rs;
1430         
1431         pCodeOp *pcop;
1432         
1433         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1434         /* offset is greater than
1435         size then zero */
1436
1437         assert (aop);
1438
1439         /* XXX: still needed for BIT operands (AOP_CRY) */
1440         if (offset > (aop->size - 1) &&
1441                 aop->type != AOP_LIT)
1442                 return NULL;  //zero;
1443         
1444         /* depending on type */
1445         switch (aop->type) {
1446                 
1447         case AOP_R0:
1448         case AOP_R1:
1449         case AOP_DPTR:
1450         case AOP_DPTR2:
1451         case AOP_ACC:
1452                 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1453                 return NULL;
1454                 
1455         case AOP_IMMD:
1456                 DEBUGpic14_emitcode(";","%d",__LINE__);
1457                 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1458                 
1459         case AOP_DIR:
1460                 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1461 #if 0
1462                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1463                 pcop->type = PO_DIR;
1464                 
1465                 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1466                 strcpy(pcop->name,aop->aopu.aop_dir);   
1467                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1468                 if(PCOR(pcop)->r == NULL) {
1469                         //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1470                         PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1471                         DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1472                 } else {
1473                         DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1474                 }
1475                 PCOR(pcop)->instance = offset;
1476                 
1477                 return pcop;
1478 #endif
1479                 
1480         case AOP_REG:
1481                 {
1482                         int rIdx;
1483                         assert (offset < aop->size);
1484                         rIdx = aop->aopu.aop_reg[offset]->rIdx;
1485                         
1486                         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1487                         PCOR(pcop)->rIdx = rIdx;
1488                         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1489                         PCOR(pcop)->r->wasUsed=1;
1490                         PCOR(pcop)->r->isFree=0;
1491                         
1492                         PCOR(pcop)->instance = offset;
1493                         pcop->type = PCOR(pcop)->r->pc_type;
1494                         //rs = aop->aopu.aop_reg[offset]->name;
1495                         DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1496                         return pcop;
1497                 }
1498                 
1499         case AOP_CRY:
1500                 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1501                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1502                 //if(PCOR(pcop)->r == NULL)
1503                 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1504                 return pcop;
1505                 
1506         case AOP_LIT:
1507                 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1508                 
1509         case AOP_STR:
1510                 DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1511                 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1512                 /*
1513                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1514                 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1515                 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1516                 pcop->type = PCOR(pcop)->r->pc_type;
1517                 pcop->name = PCOR(pcop)->r->name;
1518                 
1519                   return pcop;
1520                 */
1521                 
1522         case AOP_PCODE:
1523                 pcop = NULL;
1524                 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1525                         __LINE__, 
1526                         ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1527                 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1528                 switch (aop->aopu.pcop->type)
1529                 {
1530                 case PO_IMMEDIATE:
1531                   pcop = pCodeOpCopy (aop->aopu.pcop);
1532                   /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1533                    * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1534                   PCOI(pcop)->index += offset;
1535                   //PCOI(pcop)->offset = 0;
1536                   break;
1537                 case PO_DIR:
1538                   pcop = pCodeOpCopy (aop->aopu.pcop);
1539                   PCOR(pcop)->instance = offset;
1540                   break;
1541                 default:
1542                   assert ( !"unhandled pCode type" );
1543                   break;
1544                 } // switch
1545                 return pcop;
1546         }
1547         
1548         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1549                 "popGet got unsupported aop->type");
1550         exit(0);
1551 }
1552
1553 /*-----------------------------------------------------------------*/
1554 /* popGetAddr - access the low/high word of a symbol (immediate)   */
1555 /*              (for non-PO_IMMEDIATEs this is the same as popGet) */
1556 /*-----------------------------------------------------------------*/
1557 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1558 {
1559   if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1560   {
1561     pCodeOp *pcop = aop->aopu.pcop;
1562     assert (offset <= GPTRSIZE);
1563
1564     /* special case: index >= 2 should return GPOINTER-style values */
1565     if (offset == 2)
1566     {
1567       pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1568       return pcop;
1569     }
1570     
1571     pcop = pCodeOpCopy (pcop);
1572     /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1573      * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1574     PCOI(pcop)->offset += offset;
1575     PCOI(pcop)->index += index;
1576     //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);
1577     return pcop;
1578   } else {
1579     return popGet (aop, offset + index);
1580   }
1581 }
1582
1583 /*-----------------------------------------------------------------*/
1584 /* aopPut - puts a string for a aop                                                        */
1585 /*-----------------------------------------------------------------*/
1586 void aopPut (asmop *aop, char *s, int offset)
1587 {
1588         char *d = buffer ;
1589         symbol *lbl ;
1590         
1591         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1592         
1593         if (aop->size && offset > ( aop->size - 1)) {
1594                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1595                         "aopPut got offset > aop->size");
1596                 exit(0);
1597         }
1598         
1599         /* will assign value to value */
1600         /* depending on where it is ofcourse */
1601         switch (aop->type) {
1602         case AOP_DIR:
1603                 if (offset) {
1604                         sprintf(d,"(%s + %d)",
1605                                 aop->aopu.aop_dir,offset);
1606                         fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1607                         
1608                 } else
1609                         sprintf(d,"%s",aop->aopu.aop_dir);
1610                 
1611                 if (strcmp(d,s)) {
1612                         DEBUGpic14_emitcode(";","%d",__LINE__);
1613                         if(strcmp(s,"W"))
1614                                 pic14_emitcode("movf","%s,w",s);
1615                         pic14_emitcode("movwf","%s",d);
1616                         
1617                         if(strcmp(s,"W")) {
1618                                 pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1619                                 if(offset >= aop->size) {
1620                                         emitpcode(POC_CLRF,popGet(aop,offset));
1621                                         break;
1622                                 } else {
1623                                         emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1624                                 }
1625                         }
1626                         emitpcode(POC_MOVWF,popGet(aop,offset));
1627                 
1628                 }
1629                 break;
1630                 
1631         case AOP_REG:
1632                 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1633                         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1634                         /*
1635                         if (*s == '@'             ||
1636                         strcmp(s,"r0") == 0 ||
1637                         strcmp(s,"r1") == 0 ||
1638                         strcmp(s,"r2") == 0 ||
1639                         strcmp(s,"r3") == 0 ||
1640                         strcmp(s,"r4") == 0 ||
1641                         strcmp(s,"r5") == 0 ||
1642                         strcmp(s,"r6") == 0 || 
1643                         strcmp(s,"r7") == 0 )
1644                         pic14_emitcode("mov","%s,%s  ; %d",
1645                         aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1646                         else
1647                         */
1648                         
1649                         if(strcmp(s,"W")==0 )
1650                                 pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1651                         
1652                         pic14_emitcode("movwf","%s",
1653                                 aop->aopu.aop_reg[offset]->name);
1654                         
1655                         if(strcmp(s,zero)==0) {
1656                                 emitpcode(POC_CLRF,popGet(aop,offset));
1657                                 
1658                         } else if(strcmp(s,"W")==0) {
1659                                 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1660                                 pcop->type = PO_GPR_REGISTER;
1661                                 
1662                                 PCOR(pcop)->rIdx = -1;
1663                                 PCOR(pcop)->r = NULL;
1664                                 
1665                                 DEBUGpic14_emitcode(";","%d",__LINE__);
1666                                 pcop->name = Safe_strdup(s);
1667                                 emitpcode(POC_MOVFW,pcop);
1668                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1669                         } else if(strcmp(s,one)==0) {
1670                                 emitpcode(POC_CLRF,popGet(aop,offset));
1671                                 emitpcode(POC_INCF,popGet(aop,offset));
1672                         } else {
1673                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1674                         }
1675                 }
1676                 break;
1677                 
1678         case AOP_DPTR:
1679         case AOP_DPTR2:
1680                 
1681                 if (aop->type == AOP_DPTR2)
1682                 {
1683                         genSetDPTR(1);
1684                 }
1685                 
1686                 if (aop->code) {
1687                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1688                                 "aopPut writting to code space");
1689                         exit(0);
1690                 }
1691                 
1692                 while (offset > aop->coff) {
1693                         aop->coff++;
1694                         pic14_emitcode ("inc","dptr");
1695                 }
1696                 
1697                 while (offset < aop->coff) {
1698                         aop->coff-- ;
1699                         pic14_emitcode("lcall","__decdptr");
1700                 }
1701                 
1702                 aop->coff = offset;
1703                 
1704                 /* if not in accumulater */
1705                 MOVA(s);
1706                 
1707                 pic14_emitcode ("movx","@dptr,a");
1708                 
1709                 if (aop->type == AOP_DPTR2)
1710                 {
1711                         genSetDPTR(0);
1712                 }
1713                 break;
1714                 
1715         case AOP_R0:
1716         case AOP_R1:
1717                 while (offset > aop->coff) {
1718                         aop->coff++;
1719                         pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1720                 }
1721                 while (offset < aop->coff) {
1722                         aop->coff-- ;
1723                         pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1724                 }
1725                 aop->coff = offset;
1726                 
1727                 if (aop->paged) {
1728                         MOVA(s);                         
1729                         pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1730                         
1731                 } else
1732                         if (*s == '@') {
1733                                 MOVA(s);
1734                                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1735                         } else
1736                                 if (strcmp(s,"r0") == 0 ||
1737                                         strcmp(s,"r1") == 0 ||
1738                                         strcmp(s,"r2") == 0 ||
1739                                         strcmp(s,"r3") == 0 ||
1740                                         strcmp(s,"r4") == 0 ||
1741                                         strcmp(s,"r5") == 0 ||
1742                                         strcmp(s,"r6") == 0 || 
1743                                         strcmp(s,"r7") == 0 ) {
1744                                         char buffer[10];
1745                                         sprintf(buffer,"a%s",s);
1746                                         pic14_emitcode("mov","@%s,%s",
1747                                                 aop->aopu.aop_ptr->name,buffer);
1748                                 } else
1749                                         pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1750                                 
1751                                 break;
1752                                 
1753         case AOP_STK:
1754                 if (strcmp(s,"a") == 0)
1755                         pic14_emitcode("push","acc");
1756                 else
1757                         pic14_emitcode("push","%s",s);
1758                 
1759                 break;
1760                 
1761         case AOP_CRY:
1762                 /* if bit variable */
1763                 if (!aop->aopu.aop_dir) {
1764                         pic14_emitcode("clr","a");
1765                         pic14_emitcode("rlc","a");
1766                 } else {
1767                         if (s == zero) 
1768                                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1769                         else
1770                                 if (s == one)
1771                                         pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1772                                 else
1773                                         if (!strcmp(s,"c"))
1774                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1775                                         else {
1776                                                 lbl = newiTempLabel(NULL);
1777                                                 
1778                                                 if (strcmp(s,"a")) {
1779                                                         MOVA(s);
1780                                                 }
1781                                                 pic14_emitcode("clr","c");
1782                                                 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1783                                                 pic14_emitcode("cpl","c");
1784                                                 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1785                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1786                                         }
1787                 }
1788                 break;
1789                 
1790         case AOP_STR:
1791                 aop->coff = offset;
1792                 if (strcmp(aop->aopu.aop_str[offset],s))
1793                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1794                 break;
1795                 
1796         case AOP_ACC:
1797                 aop->coff = offset;
1798                 if (!offset && (strcmp(s,"acc") == 0))
1799                         break;
1800                 
1801                 if (strcmp(aop->aopu.aop_str[offset],s))
1802                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1803                 break;
1804                 
1805         default :
1806                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1807                         "aopPut got unsupported aop->type");
1808                 exit(0);
1809         }
1810         
1811 }
1812
1813 /*-----------------------------------------------------------------*/
1814 /* mov2w_op - generate either a MOVLW or MOVFW based operand type  */
1815 /*-----------------------------------------------------------------*/
1816 static void mov2w_op (operand *op, int offset)
1817 {
1818         assert (op);
1819         FENTRY;
1820
1821         /* for PO_IMMEDIATEs: use address or value? */
1822         if (op_isLitLike (op))
1823         {
1824                 /* access address of op */
1825                 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1826                 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1827                 {
1828                         if (offset == GPTRSIZE-1)
1829                                 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1830                         else
1831                                 emitpcode (POC_MOVLW, popGetLit (0));
1832                 }
1833                 else
1834                         emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1835         } else {
1836                 /* access value stored in op */
1837                 mov2w (AOP(op), offset);
1838         }
1839 }
1840
1841
1842 /*-----------------------------------------------------------------*/
1843 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1844 /*-----------------------------------------------------------------*/
1845 void mov2w (asmop *aop, int offset)
1846 {
1847         
1848         if(!aop)
1849                 return;
1850         
1851         DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1852         
1853         if ( aop_isLitLike (aop) )
1854                 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1855         else
1856                 emitpcode(POC_MOVFW,popGet(aop,offset));
1857         
1858 }
1859
1860 static void movwf (asmop *op, int offset)
1861 {
1862         emitpcode (POC_MOVWF, popGet(op, offset));
1863 }
1864
1865 static pCodeOp *get_argument_pcop (int idx)
1866 {
1867         assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1868         return popRegFromIdx (Gstack_base_addr - (idx - 1));
1869 }
1870
1871 static pCodeOp *get_return_val_pcop (int offset)
1872 {
1873         assert (offset > 0 && "the most significant byte is returned via WREG");
1874         return popRegFromIdx (Gstack_base_addr - (offset - 1));
1875 }
1876
1877 static void pass_argument (operand *op, int offset, int idx)
1878 {
1879         if (op)
1880                 mov2w_op (op, offset);
1881         if (idx != 0)
1882                 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1883 }
1884
1885 static void get_returnvalue (operand *op, int offset, int idx)
1886 {
1887         if (idx != 0)
1888                 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1889         movwf(AOP(op), offset);
1890 }
1891
1892 static void call_libraryfunc (char *name)
1893 {
1894   /* library code might reside in different page... */
1895   emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1896   /* call the library function */
1897   emitpcode (POC_CALL, popGetExternal (name));
1898   /* might return from different page... */
1899   emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1900 }
1901 #if 0
1902 /*-----------------------------------------------------------------*/
1903 /* reAdjustPreg - points a register back to where it should        */
1904 /*-----------------------------------------------------------------*/
1905 static void reAdjustPreg (asmop *aop)
1906 {
1907         int size ;
1908         
1909         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1910         aop->coff = 0;
1911         if ((size = aop->size) <= 1)
1912                 return ;
1913         size-- ;
1914         switch (aop->type) {
1915         case AOP_R0 :
1916         case AOP_R1 :
1917                 while (size--)
1918                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1919                 break;                  
1920         case AOP_DPTR :
1921         case AOP_DPTR2:
1922                 if (aop->type == AOP_DPTR2)
1923                 {
1924                         genSetDPTR(1);
1925                 } 
1926                 while (size--)
1927                 {
1928                         pic14_emitcode("lcall","__decdptr");
1929                 }
1930                 
1931                 if (aop->type == AOP_DPTR2)
1932                 {
1933                         genSetDPTR(0);
1934                 }
1935                 break;
1936                 
1937         }
1938         
1939 }
1940 #endif
1941
1942
1943 #if 0
1944 /*-----------------------------------------------------------------*/
1945 /* opIsGptr: returns non-zero if the passed operand is             */
1946 /* a generic pointer type.                                         */
1947 /*-----------------------------------------------------------------*/ 
1948 static int opIsGptr(operand *op)
1949 {
1950         sym_link *type = operandType(op);
1951         
1952         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1953         if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1954         {
1955                 return 1;
1956         }
1957         return 0;          
1958 }
1959 #endif
1960
1961 /*-----------------------------------------------------------------*/
1962 /* pic14_getDataSize - get the operand data size                   */
1963 /*-----------------------------------------------------------------*/
1964 int pic14_getDataSize(operand *op)
1965 {
1966         int size;
1967         
1968         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1969         
1970 #if 0
1971         size = getSize(OP_SYM_ETYPE(op));
1972         return size;
1973         //return AOP_SIZE(op);
1974         
1975         // tsd- in the pic port, the genptr size is 1, so this code here
1976         // fails. ( in the 8051 port, the size was 4).
1977 #else
1978         size = AOP_SIZE(op);
1979         if (IS_GENPTR(OP_SYM_TYPE(op)))
1980         {
1981                 sym_link *type = operandType(op);
1982                 if (IS_GENPTR(type))
1983                 {
1984                         /* generic pointer; arithmetic operations
1985                         * should ignore the high byte (pointer type).
1986                         */
1987                         size--;
1988                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1989                 }
1990         }
1991         return size;
1992 #endif
1993 }
1994
1995 /*-----------------------------------------------------------------*/
1996 /* pic14_outAcc - output Acc                                       */
1997 /*-----------------------------------------------------------------*/
1998 void pic14_outAcc(operand *result)
1999 {
2000         int size,offset;
2001         DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2002         DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
2003         
2004         
2005         size = pic14_getDataSize(result);
2006         if(size){
2007                 emitpcode(POC_MOVWF,popGet(AOP(result),0));
2008                 size--;
2009                 offset = 1;
2010                 /* unsigned or positive */
2011                 while(size--)
2012                         emitpcode(POC_CLRF,popGet(AOP(result),offset++));
2013         }
2014         
2015 }
2016
2017 /*-----------------------------------------------------------------*/
2018 /* pic14_outBitC - output a bit C                                  */
2019 /*-----------------------------------------------------------------*/
2020 void pic14_outBitC(operand *result)
2021 {
2022         
2023         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2024         /* if the result is bit */
2025         if (AOP_TYPE(result) == AOP_CRY) 
2026                 aopPut(AOP(result),"c",0);
2027         else {
2028                 pic14_emitcode("clr","a  ; %d", __LINE__);
2029                 pic14_emitcode("rlc","a");
2030                 pic14_outAcc(result);
2031         }
2032 }
2033
2034 /*-----------------------------------------------------------------*/
2035 /* pic14_toBoolean - emit code for orl a,operator(sizeop)          */
2036 /*-----------------------------------------------------------------*/
2037 void pic14_toBoolean(operand *oper)
2038 {
2039         int size = AOP_SIZE(oper);
2040         int offset = 0;
2041         
2042         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2043
2044         assert (size > 0);
2045
2046         if (size == 1) {
2047                 /* MOVFW does not load the flags... */
2048                 if (AOP_TYPE(oper) == AOP_ACC) {
2049                         emitpcode(POC_IORLW, popGetLit(0));
2050                         offset = 1;
2051                 } else {
2052                         emitpcode(POC_MOVLW, popGetLit(0));
2053                         offset = 0;
2054                 }
2055         } else {
2056                 if ( AOP_TYPE(oper) != AOP_ACC) {
2057                         emitpcode(POC_MOVFW,popGet(AOP(oper),0));
2058                         offset = 1;
2059                 }
2060         }
2061         
2062         while (offset < size) {
2063                 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
2064         }
2065         /* Z is set iff (oper == 0) */
2066 }
2067
2068
2069 /*-----------------------------------------------------------------*/
2070 /* genNot - generate code for ! operation                          */
2071 /*-----------------------------------------------------------------*/
2072 static void genNot (iCode *ic)
2073 {
2074         //symbol *tlbl;
2075         int size;
2076
2077         FENTRY;
2078         
2079         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2080         /* assign asmOps to operand & result */
2081         aopOp (IC_LEFT(ic),ic,FALSE);
2082         aopOp (IC_RESULT(ic),ic,TRUE);
2083         
2084         DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2085         /* if in bit space then a special case */
2086         if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2087                 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2088                         emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2089                         emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2090                 } else {
2091                         emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2092                         emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2093                         emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2094                 }
2095                 goto release;
2096         }
2097         
2098         size = AOP_SIZE(IC_LEFT(ic));
2099         mov2w (AOP(IC_LEFT(ic)),0);
2100         while (--size > 0)
2101         {
2102           if (op_isLitLike (IC_LEFT(ic)))
2103             emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2104           else
2105             emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2106         }
2107         emitpcode(POC_MOVLW, popGetLit (0));
2108         emitSKPNZ;
2109         emitpcode(POC_MOVLW, popGetLit (1));
2110         movwf(AOP(IC_RESULT(ic)), 0);
2111
2112         for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2113         {
2114           emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2115         }
2116         goto release;
2117         
2118 release:        
2119         /* release the aops */
2120         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2121         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2122 }
2123
2124
2125 /*-----------------------------------------------------------------*/
2126 /* genCpl - generate code for complement                                                   */
2127 /*-----------------------------------------------------------------*/
2128 static void genCpl (iCode *ic)
2129 {
2130         operand *left, *result;
2131         int size, offset=0;  
2132         
2133         FENTRY;
2134         
2135         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2136         aopOp((left = IC_LEFT(ic)),ic,FALSE);
2137         aopOp((result=IC_RESULT(ic)),ic,TRUE);
2138         
2139         /* if both are in bit space then 
2140         a special case */
2141         if (AOP_TYPE(result) == AOP_CRY &&
2142                 AOP_TYPE(left) == AOP_CRY ) { 
2143                 
2144                 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir); 
2145                 pic14_emitcode("cpl","c"); 
2146                 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir); 
2147                 goto release; 
2148         } 
2149         
2150         size = AOP_SIZE(result);
2151         if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2152         while (size--) {
2153                 
2154                 if(AOP_TYPE(left) == AOP_ACC) 
2155                         emitpcode(POC_XORLW, popGetLit(0xff));
2156                 else
2157                         emitpcode(POC_COMFW,popGet(AOP(left),offset));
2158                 
2159                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2160                 offset++;
2161         }
2162         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2163         
2164         
2165 release:
2166         /* release the aops */
2167         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2168         freeAsmop(result,NULL,ic,TRUE);
2169 }
2170
2171 /*-----------------------------------------------------------------*/
2172 /* genUminusFloat - unary minus for floating points                        */
2173 /*-----------------------------------------------------------------*/
2174 static void genUminusFloat(operand *op,operand *result)
2175 {
2176         int size ,offset =0 ;
2177         char *l;
2178         
2179         FENTRY;
2180
2181         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2182         /* for this we just need to flip the 
2183         first it then copy the rest in place */
2184         size = AOP_SIZE(op) - 1;
2185         l = aopGet(AOP(op),3,FALSE,FALSE);
2186         
2187         MOVA(l);          
2188         
2189         pic14_emitcode("cpl","acc.7");
2190         aopPut(AOP(result),"a",3);      
2191         
2192         while(size--) {
2193                 aopPut(AOP(result),
2194                         aopGet(AOP(op),offset,FALSE,FALSE),
2195                         offset);
2196                 offset++;
2197         }                
2198 }
2199
2200 /*-----------------------------------------------------------------*/
2201 /* genUminus - unary minus code generation                                                 */
2202 /*-----------------------------------------------------------------*/
2203 static void genUminus (iCode *ic)
2204 {
2205         int size, i;
2206         sym_link *optype, *rtype;
2207         
2208         FENTRY;
2209         
2210         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2211         /* assign asmops */
2212         aopOp(IC_LEFT(ic),ic,FALSE);
2213         aopOp(IC_RESULT(ic),ic,TRUE);
2214         
2215         /* if both in bit space then special
2216         case */
2217         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2218                 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2219                 
2220                 emitpcode(POC_BCF,       popGet(AOP(IC_RESULT(ic)),0));
2221                 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2222                 emitpcode(POC_BSF,       popGet(AOP(IC_RESULT(ic)),0));
2223                 
2224                 goto release; 
2225         } 
2226         
2227         optype = operandType(IC_LEFT(ic));
2228         rtype = operandType(IC_RESULT(ic));
2229         
2230         /* if float then do float stuff */
2231         if (IS_FLOAT(optype)) {
2232                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2233                 goto release;
2234         }
2235         
2236         /* otherwise subtract from zero by taking the 2's complement */
2237         size = AOP_SIZE(IC_LEFT(ic));
2238         
2239         for(i=0; i<size; i++) {
2240                 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2241                         emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
2242                 else {
2243                         emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2244                         emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2245                 }
2246         }
2247         
2248         emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
2249         for(i=1; i<size; i++) {
2250                 emitSKPNZ;
2251                 emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
2252         }
2253         
2254 release:
2255         /* release the aops */
2256         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2257         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);  
2258 }
2259
2260 /*-----------------------------------------------------------------*/
2261 /* saveRegisters - will look for a call and save the registers     */
2262 /*-----------------------------------------------------------------*/
2263 static void saveRegisters(iCode *lic) 
2264 {
2265         int i;
2266         iCode *ic;
2267         bitVect *rsave;
2268         sym_link *dtype;
2269         
2270         FENTRY;
2271
2272         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2273         /* look for call */
2274         for (ic = lic ; ic ; ic = ic->next) 
2275                 if (ic->op == CALL || ic->op == PCALL)
2276                         break;
2277                 
2278                 if (!ic) {
2279                         fprintf(stderr,"found parameter push with no function call\n");
2280                         return ;
2281                 }
2282                 
2283                 /* if the registers have been saved already then
2284                 do nothing */
2285                 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2286                         return ;
2287                 
2288                         /* find the registers in use at this time 
2289                 and push them away to safety */
2290                 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2291                         ic->rUsed);
2292                 
2293                 ic->regsSaved = 1;
2294                 if (options.useXstack) {
2295                         if (bitVectBitValue(rsave,R0_IDX))
2296                                 pic14_emitcode("mov","b,r0");
2297                         pic14_emitcode("mov","r0,%s",spname);
2298                         for (i = 0 ; i < pic14_nRegs ; i++) {
2299                                 if (bitVectBitValue(rsave,i)) {
2300                                         if (i == R0_IDX)
2301                                                 pic14_emitcode("mov","a,b");
2302                                         else
2303                                                 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2304                                         pic14_emitcode("movx","@r0,a");
2305                                         pic14_emitcode("inc","r0");
2306                                 }
2307                         }
2308                         pic14_emitcode("mov","%s,r0",spname);
2309                         if (bitVectBitValue(rsave,R0_IDX))
2310                                 pic14_emitcode("mov","r0,b");     
2311                 }// else
2312                 //for (i = 0 ; i < pic14_nRegs ; i++) {
2313                 //        if (bitVectBitValue(rsave,i))
2314                 //      pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2315                 //}
2316                 
2317                 dtype = operandType(IC_LEFT(ic));
2318                 if (currFunc && dtype && 
2319                         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2320                         IFFUNC_ISISR(currFunc->type) &&
2321                         !ic->bankSaved) 
2322                         
2323                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2324                 
2325 }
2326 /*-----------------------------------------------------------------*/
2327 /* unsaveRegisters - pop the pushed registers                                      */
2328 /*-----------------------------------------------------------------*/
2329 static void unsaveRegisters (iCode *ic)
2330 {
2331         int i;
2332         bitVect *rsave;
2333         
2334         FENTRY;
2335
2336         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2337         /* find the registers in use at this time 
2338         and push them away to safety */
2339         rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2340                 ic->rUsed);
2341         
2342         if (options.useXstack) {
2343                 pic14_emitcode("mov","r0,%s",spname); 
2344                 for (i =  pic14_nRegs ; i >= 0 ; i--) {
2345                         if (bitVectBitValue(rsave,i)) {
2346                                 pic14_emitcode("dec","r0");
2347                                 pic14_emitcode("movx","a,@r0");
2348                                 if (i == R0_IDX)
2349                                         pic14_emitcode("mov","b,a");
2350                                 else
2351                                         pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2352                         }       
2353                         
2354                 }
2355                 pic14_emitcode("mov","%s,r0",spname);
2356                 if (bitVectBitValue(rsave,R0_IDX))
2357                         pic14_emitcode("mov","r0,b");
2358         } //else
2359         //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2360         //      if (bitVectBitValue(rsave,i))
2361         //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2362         //}
2363         
2364 }  
2365
2366
2367 /*-----------------------------------------------------------------*/
2368 /* pushSide -                            */
2369 /*-----------------------------------------------------------------*/
2370 static void pushSide(operand * oper, int size)
2371 {
2372 #if 0
2373         int offset = 0;
2374         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2375         while (size--) {
2376                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2377                 if (AOP_TYPE(oper) != AOP_REG &&
2378                         AOP_TYPE(oper) != AOP_DIR &&
2379                         strcmp(l,"a") ) {
2380                         pic14_emitcode("mov","a,%s",l);
2381                         pic14_emitcode("push","acc");
2382                 } else
2383                         pic14_emitcode("push","%s",l);
2384         }
2385 #endif
2386 }
2387
2388 /*-----------------------------------------------------------------*/
2389 /* assignResultValue -                           */
2390 /*-----------------------------------------------------------------*/
2391 static void assignResultValue(operand * oper)
2392 {
2393         int size = AOP_SIZE(oper);
2394         int offset = 0;
2395         
2396         FENTRY;
2397
2398         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2399         
2400         DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2401         
2402         /* assign MSB first (passed via WREG) */
2403         while (size--) {
2404                 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2405                 GpsuedoStkPtr++;
2406         }
2407 }
2408
2409
2410 /*-----------------------------------------------------------------*/
2411 /* genIpush - genrate code for pushing this gets a little complex  */
2412 /*-----------------------------------------------------------------*/
2413 static void genIpush (iCode *ic)
2414 {
2415         FENTRY;
2416         
2417         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2418 #if 0
2419         int size, offset = 0 ;
2420         char *l;
2421         
2422         
2423         /* if this is not a parm push : ie. it is spill push 
2424         and spill push is always done on the local stack */
2425         if (!ic->parmPush) {
2426                 
2427                 /* and the item is spilt then do nothing */
2428                 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2429                         return ;
2430                 
2431                 aopOp(IC_LEFT(ic),ic,FALSE);
2432                 size = AOP_SIZE(IC_LEFT(ic));
2433                 /* push it on the stack */
2434                 while(size--) {
2435                         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2436                         if (*l == '#') {
2437                                 MOVA(l);
2438                                 l = "acc";
2439                         }
2440                         pic14_emitcode("push","%s",l);
2441                 }
2442                 return ;                
2443         }
2444         
2445         /* this is a paramter push: in this case we call
2446         the routine to find the call and save those
2447         registers that need to be saved */   
2448         saveRegisters(ic);
2449         
2450         /* then do the push */
2451         aopOp(IC_LEFT(ic),ic,FALSE);
2452         
2453         
2454         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2455         size = AOP_SIZE(IC_LEFT(ic));
2456         
2457         while (size--) {
2458                 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2459                 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2460                         AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2461                         strcmp(l,"a") ) {
2462                         pic14_emitcode("mov","a,%s",l);
2463                         pic14_emitcode("push","acc");
2464                 } else
2465                         pic14_emitcode("push","%s",l);
2466         }         
2467         
2468         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2469 #endif
2470 }
2471
2472 /*-----------------------------------------------------------------*/
2473 /* genIpop - recover the registers: can happen only for spilling   */
2474 /*-----------------------------------------------------------------*/
2475 static void genIpop (iCode *ic)
2476 {
2477         FENTRY;
2478
2479         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2480         assert (!"genIpop -- unimplemented");
2481 #if 0
2482         int size,offset ;
2483         
2484         
2485         /* if the temp was not pushed then */
2486         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2487                 return ;
2488         
2489         aopOp(IC_LEFT(ic),ic,FALSE);
2490         size = AOP_SIZE(IC_LEFT(ic));
2491         offset = (size-1);
2492         while (size--) 
2493                 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2494                 FALSE,TRUE));
2495         
2496         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2497 #endif
2498 }
2499
2500 /*-----------------------------------------------------------------*/
2501 /* unsaverbank - restores the resgister bank from stack                    */
2502 /*-----------------------------------------------------------------*/
2503 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2504 {
2505         FENTRY;
2506
2507         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2508 #if 0
2509         int i;
2510         asmop *aop ;
2511         regs *r = NULL;
2512         
2513         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2514         if (popPsw) {
2515                 if (options.useXstack) {
2516                         aop = newAsmop(0);
2517                         r = getFreePtr(ic,&aop,FALSE);
2518                         
2519                         
2520                         pic14_emitcode("mov","%s,_spx",r->name);
2521                         pic14_emitcode("movx","a,@%s",r->name);
2522                         pic14_emitcode("mov","psw,a");
2523                         pic14_emitcode("dec","%s",r->name);
2524                         
2525                 }else
2526                         pic14_emitcode ("pop","psw");
2527         }
2528         
2529         for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2530                 if (options.useXstack) {           
2531                         pic14_emitcode("movx","a,@%s",r->name);
2532                         //pic14_emitcode("mov","(%s+%d),a",
2533                         //         regspic14[i].base,8*bank+regspic14[i].offset);
2534                         pic14_emitcode("dec","%s",r->name);
2535                         
2536                 } else 
2537                         pic14_emitcode("pop",""); //"(%s+%d)",
2538                 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2539         }
2540         
2541         if (options.useXstack) {
2542                 
2543                 pic14_emitcode("mov","_spx,%s",r->name);
2544                 freeAsmop(NULL,aop,ic,TRUE);
2545                 
2546         }
2547 #endif 
2548 }
2549
2550 /*-----------------------------------------------------------------*/
2551 /* saverbank - saves an entire register bank on the stack                  */
2552 /*-----------------------------------------------------------------*/
2553 static void saverbank (int bank, iCode *ic, bool pushPsw)
2554 {
2555         FENTRY;
2556
2557         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2558 #if 0
2559         int i;
2560         asmop *aop ;
2561         regs *r = NULL;
2562         
2563         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2564         if (options.useXstack) {
2565                 
2566                 aop = newAsmop(0);
2567                 r = getFreePtr(ic,&aop,FALSE);  
2568                 pic14_emitcode("mov","%s,_spx",r->name);
2569                 
2570         }
2571         
2572         for (i = 0 ; i < pic14_nRegs ;i++) {
2573                 if (options.useXstack) {
2574                         pic14_emitcode("inc","%s",r->name);
2575                         //pic14_emitcode("mov","a,(%s+%d)",
2576                         //               regspic14[i].base,8*bank+regspic14[i].offset);
2577                         pic14_emitcode("movx","@%s,a",r->name);                 
2578                 } else 
2579                         pic14_emitcode("push","");// "(%s+%d)",
2580                 //regspic14[i].base,8*bank+regspic14[i].offset);
2581         }
2582         
2583         if (pushPsw) {
2584                 if (options.useXstack) {
2585                         pic14_emitcode("mov","a,psw");
2586                         pic14_emitcode("movx","@%s,a",r->name); 
2587                         pic14_emitcode("inc","%s",r->name);
2588                         pic14_emitcode("mov","_spx,%s",r->name);                 
2589                         freeAsmop (NULL,aop,ic,TRUE);
2590                         
2591                 } else
2592                         pic14_emitcode("push","psw");
2593                 
2594                 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2595         }
2596         ic->bankSaved = 1;
2597 #endif
2598 }
2599
2600 /*-----------------------------------------------------------------*/
2601 /* genCall - generates a call statement                                                    */
2602 /*-----------------------------------------------------------------*/
2603 static void genCall (iCode *ic)
2604 {
2605         sym_link *dtype;         
2606         symbol *sym;
2607         char *name;
2608         int isExtern;
2609         
2610         FENTRY;
2611
2612         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2613         
2614         /* if caller saves & we have not saved then */
2615         if (!ic->regsSaved)
2616                 saveRegisters(ic);
2617         
2618                 /* if we are calling a function that is not using
2619                 the same register bank then we need to save the
2620         destination registers on the stack */
2621         dtype = operandType(IC_LEFT(ic));
2622         if (currFunc && dtype && 
2623                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2624                 IFFUNC_ISISR(currFunc->type) &&
2625                 !ic->bankSaved) 
2626                 
2627                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2628         
2629         /* if send set is not empty the assign */
2630         if (_G.sendSet) {
2631                 iCode *sic;
2632                 /* For the Pic port, there is no data stack.
2633                 * So parameters passed to functions are stored
2634                 * in registers. (The pCode optimizer will get
2635                 * rid of most of these :).
2636                 */
2637                 int psuedoStkPtr=-1;
2638                 int firstTimeThruLoop = 1;
2639                 
2640                 _G.sendSet = reverseSet(_G.sendSet);
2641                 
2642                 /* First figure how many parameters are getting passed */
2643                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2644                 sic = setNextItem(_G.sendSet)) {
2645                         
2646                         aopOp(IC_LEFT(sic),sic,FALSE);
2647                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2648                         freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2649                 }
2650                 
2651                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2652                 sic = setNextItem(_G.sendSet)) {
2653                         int size, offset = 0;
2654                         
2655                         aopOp(IC_LEFT(sic),sic,FALSE);
2656                         size = AOP_SIZE(IC_LEFT(sic));
2657                         
2658                         while (size--) {
2659                                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2660                                         AopType(AOP_TYPE(IC_LEFT(sic))));
2661                                 
2662                                 if(!firstTimeThruLoop) {
2663                                         /* If this is not the first time we've been through the loop
2664                                         * then we need to save the parameter in a temporary
2665                                         * register. The last byte of the last parameter is
2666                                         * passed in W. */
2667                                         emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2668                                         
2669                                 }
2670                                 firstTimeThruLoop=0;
2671                                 
2672                                 mov2w_op (IC_LEFT(sic),  offset);
2673                                 offset++;
2674                         }
2675                         freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2676                 }
2677                 _G.sendSet = NULL;
2678         }
2679         /* make the call */
2680         sym = OP_SYMBOL(IC_LEFT(ic));
2681         name = sym->rname[0] ? sym->rname : sym->name;
2682         isExtern = IS_EXTERN(sym->etype);
2683         if (isExtern) {
2684                 emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2685         }
2686         emitpcode(POC_CALL,popGetWithString(name,isExtern));
2687         if (isExtern) {
2688                 emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel to restore PCLATH before next goto or call instruction */
2689         }
2690         GpsuedoStkPtr=0;
2691         /* if we need assign a result value */
2692         if ((IS_ITEMP(IC_RESULT(ic)) && 
2693                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2694                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2695                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2696                 
2697                 _G.accInUse++;
2698                 aopOp(IC_RESULT(ic),ic,FALSE);
2699                 _G.accInUse--;
2700                 
2701                 assignResultValue(IC_RESULT(ic));
2702                 
2703                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2704                         AopType(AOP_TYPE(IC_RESULT(ic))));
2705                 
2706                 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2707         }
2708         
2709         /* if register bank was saved then pop them */
2710         if (ic->bankSaved)
2711                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2712         
2713         /* if we hade saved some registers then unsave them */
2714         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2715                 unsaveRegisters (ic);
2716         
2717         
2718 }
2719
2720 /*-----------------------------------------------------------------*/
2721 /* genPcall - generates a call by pointer statement                        */
2722 /*-----------------------------------------------------------------*/
2723 static void genPcall (iCode *ic)
2724 {
2725         sym_link *dtype;
2726         symbol *albl = newiTempLabel(NULL);
2727         symbol *blbl = newiTempLabel(NULL);
2728         PIC_OPCODE poc;
2729         pCodeOp *pcop;
2730         operand *left;
2731         
2732         FENTRY;
2733
2734         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2735         /* if caller saves & we have not saved then */
2736         if (!ic->regsSaved)
2737                 saveRegisters(ic);
2738         
2739                 /* if we are calling a function that is not using
2740                 the same register bank then we need to save the
2741         destination registers on the stack */
2742         dtype = operandType(IC_LEFT(ic));
2743         if (currFunc && dtype && 
2744                 IFFUNC_ISISR(currFunc->type) &&
2745                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2746                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2747         
2748         left = IC_LEFT(ic);
2749         aopOp(left,ic,FALSE);
2750         DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2751         
2752         poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2753         
2754         pushSide(IC_LEFT(ic), FPTRSIZE);
2755         
2756         /* if send set is not empty, assign parameters */
2757         if (_G.sendSet) {
2758                 
2759                 DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2760                 /* no way to pass args - W always gets used to make the call */
2761         }
2762         /* first idea - factor out a common helper function and call it.
2763         But don't know how to get it generated only once in its own block
2764         
2765         if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2766                 char *rname;
2767                 char *buffer;
2768                 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2769                 DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2770                 buffer = Safe_calloc(1,strlen(rname)+16);
2771                 sprintf(buffer, "%s_goto_helper", rname);
2772                 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2773                 free(buffer);
2774         }
2775         */
2776         emitpcode(POC_CALL,popGetLabel(albl->key));
2777         pcop = popGetLabel(blbl->key);
2778         emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2779         emitpcode(POC_GOTO,pcop);
2780         emitpLabel(albl->key);
2781         
2782         emitpcode(poc,popGetAddr(AOP(left),1,0));
2783         emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2784         emitpcode(poc,popGetAddr(AOP(left),0,0));
2785         emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2786         
2787         emitpLabel(blbl->key);
2788         
2789         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2790         
2791         /* if we need to assign a result value */
2792         if ((IS_ITEMP(IC_RESULT(ic)) &&
2793                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2794                 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2795                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2796                 
2797                 _G.accInUse++;
2798                 aopOp(IC_RESULT(ic),ic,FALSE);
2799                 _G.accInUse--;
2800
2801                 GpsuedoStkPtr = 0;
2802                 
2803                 assignResultValue(IC_RESULT(ic));
2804                 
2805                 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2806         }
2807         
2808         /* if register bank was saved then unsave them */
2809         if (currFunc && dtype && 
2810                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2811                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2812         
2813                 /* if we hade saved some registers then
2814         unsave them */
2815         if (ic->regsSaved)
2816                 unsaveRegisters (ic);
2817         
2818 }
2819
2820 /*-----------------------------------------------------------------*/
2821 /* resultRemat - result  is rematerializable                                       */
2822 /*-----------------------------------------------------------------*/
2823 static int resultRemat (iCode *ic)
2824 {
2825         //      DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2826         FENTRY;
2827
2828         if (SKIP_IC(ic) || ic->op == IFX)
2829                 return 0;
2830         
2831         if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2832                 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2833                 if (sym->remat && !POINTER_SET(ic)) 
2834                         return 1;
2835         }
2836         
2837         return 0;
2838 }
2839
2840 #if defined(__BORLANDC__) || defined(_MSC_VER)
2841 #define STRCASECMP stricmp
2842 #else
2843 #define STRCASECMP strcasecmp
2844 #endif
2845
2846 #if 0
2847 /*-----------------------------------------------------------------*/
2848 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2849 /*-----------------------------------------------------------------*/
2850 static bool inExcludeList(char *s)
2851 {
2852         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2853         int i =0;
2854         
2855         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2856         if (options.excludeRegs[i] &&
2857                 STRCASECMP(options.excludeRegs[i],"none") == 0)
2858                 return FALSE ;
2859         
2860         for ( i = 0 ; options.excludeRegs[i]; i++) {
2861                 if (options.excludeRegs[i] &&
2862                         STRCASECMP(s,options.excludeRegs[i]) == 0)
2863                         return TRUE;
2864         }
2865         return FALSE ;
2866 }
2867 #endif
2868
2869 /*-----------------------------------------------------------------*/
2870 /* genFunction - generated code for function entry                                 */
2871 /*-----------------------------------------------------------------*/
2872 static void genFunction (iCode *ic)
2873 {
2874         symbol *sym;
2875         sym_link *ftype;
2876         
2877         FENTRY;
2878
2879         DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2880         
2881         labelOffset += (max_key+4);
2882         max_key=0;
2883         GpsuedoStkPtr=0;
2884         _G.nRegsSaved = 0;
2885         /* create the function header */
2886         pic14_emitcode(";","-----------------------------------------");
2887         pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2888         pic14_emitcode(";","-----------------------------------------");
2889         
2890         pic14_emitcode("","%s:",sym->rname);
2891         addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2892         
2893         ftype = operandType(IC_LEFT(ic));
2894         
2895         /* if critical function then turn interrupts off */
2896         if (IFFUNC_ISCRITICAL(ftype))
2897                 pic14_emitcode("clr","ea");
2898         
2899                 /* here we need to generate the equates for the
2900         register bank if required */
2901 #if 0
2902         if (FUNC_REGBANK(ftype) != rbank) {
2903                 int i ;
2904                 
2905                 rbank = FUNC_REGBANK(ftype);
2906                 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2907                         if (strcmp(regspic14[i].base,"0") == 0)
2908                                 pic14_emitcode("","%s = 0x%02x",
2909                                 regspic14[i].dname,
2910                                 8*rbank+regspic14[i].offset);
2911                         else
2912                                 pic14_emitcode ("","%s = %s + 0x%02x",
2913                                 regspic14[i].dname,
2914                                 regspic14[i].base,
2915                                 8*rbank+regspic14[i].offset);
2916                 }
2917         }
2918 #endif
2919         
2920         /* if this is an interrupt service routine */
2921         if (IFFUNC_ISISR(sym->type)) {
2922         /*  already done in pic14createInterruptVect() - delete me
2923         addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2924         emitpcodeNULLop(POC_NOP);
2925         emitpcodeNULLop(POC_NOP);
2926         emitpcodeNULLop(POC_NOP);
2927                 */
2928                 emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2929                 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2930                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2931                 emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2932                 emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2933                 emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2934                 emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2935                 
2936                 pBlockConvert2ISR(pb);
2937                 pic14_hasInterrupt = 1;
2938 #if 0  
2939                 if (!inExcludeList("acc"))              
2940                         pic14_emitcode ("push","acc");  
2941                 if (!inExcludeList("b"))
2942                         pic14_emitcode ("push","b");
2943                 if (!inExcludeList("dpl"))
2944                         pic14_emitcode ("push","dpl");
2945                 if (!inExcludeList("dph"))
2946                         pic14_emitcode ("push","dph");
2947                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2948                 {
2949                         pic14_emitcode ("push", "dpx");
2950                         /* Make sure we're using standard DPTR */
2951                         pic14_emitcode ("push", "dps");
2952                         pic14_emitcode ("mov", "dps, #0x00");
2953                         if (options.stack10bit)
2954                         { 
2955                                 /* This ISR could conceivably use DPTR2. Better save it. */
2956                                 pic14_emitcode ("push", "dpl1");
2957                                 pic14_emitcode ("push", "dph1");
2958                                 pic14_emitcode ("push", "dpx1");
2959                         }
2960                 }
2961                 /* if this isr has no bank i.e. is going to
2962                 run with bank 0 , then we need to save more
2963                 registers :-) */
2964                 if (!FUNC_REGBANK(sym->type)) {
2965                         
2966                 /* if this function does not call any other
2967                 function then we can be economical and
2968                         save only those registers that are used */
2969                         if (! IFFUNC_HASFCALL(sym->type)) {
2970                                 int i;
2971                                 
2972                                 /* if any registers used */
2973                                 if (sym->regsUsed) {
2974                                         /* save the registers used */
2975                                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2976                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2977                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2978                                                         pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);               
2979                                         }
2980                                 }
2981                                 
2982                         } else {
2983                         /* this function has    a function call cannot
2984                         determines register usage so we will have the
2985                                 entire bank */
2986                                 saverbank(0,ic,FALSE);
2987                         }       
2988                 }
2989 #endif
2990         } else {
2991         /* if callee-save to be used for this function
2992                 then save the registers being used in this function */
2993                 if (IFFUNC_CALLEESAVES(sym->type)) {
2994                         int i;
2995                         
2996                         /* if any registers used */
2997                         if (sym->regsUsed) {
2998                                 /* save the registers used */
2999                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3000                                         if (bitVectBitValue(sym->regsUsed,i) ||
3001                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
3002                                                 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
3003                                                 _G.nRegsSaved++;
3004                                         }
3005                                 }
3006                         }
3007                 }
3008         }
3009         
3010         /* set the register bank to the desired value */
3011         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
3012                 pic14_emitcode("push","psw");
3013                 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);       
3014         }
3015         
3016         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3017                 
3018                 if (options.useXstack) {
3019                         pic14_emitcode("mov","r0,%s",spname);
3020                         pic14_emitcode("mov","a,_bp");
3021                         pic14_emitcode("movx","@r0,a");
3022                         pic14_emitcode("inc","%s",spname);
3023                 }
3024                 else
3025                 {
3026                         /* set up the stack */
3027                         pic14_emitcode ("push","_bp");   /* save the callers stack      */
3028                 }
3029                 pic14_emitcode ("mov","_bp,%s",spname);
3030         }
3031         
3032         /* adjust the stack for the function */
3033         if (sym->stack) {
3034                 
3035                 int i = sym->stack;
3036                 if (i > 256 ) 
3037                         werror(W_STACK_OVERFLOW,sym->name);
3038                 
3039                 if (i > 3 && sym->recvSize < 4) {                
3040                         
3041                         pic14_emitcode ("mov","a,sp");
3042                         pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3043                         pic14_emitcode ("mov","sp,a");
3044                         
3045                 }
3046                 else
3047                         while(i--)
3048                                 pic14_emitcode("inc","sp");
3049         }
3050         
3051         if (sym->xstack) {
3052                 
3053                 pic14_emitcode ("mov","a,_spx");
3054                 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3055                 pic14_emitcode ("mov","_spx,a");
3056         }
3057         
3058 }
3059
3060 /*-----------------------------------------------------------------*/
3061 /* genEndFunction - generates epilogue for functions                       */
3062 /*-----------------------------------------------------------------*/
3063 static void genEndFunction (iCode *ic)
3064 {
3065         symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3066         
3067         FENTRY;
3068
3069         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3070         
3071         if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3072         {
3073                 pic14_emitcode ("mov","%s,_bp",spname);
3074         }
3075         
3076         /* if use external stack but some variables were
3077         added to the local stack then decrement the
3078         local stack */
3079         if (options.useXstack && sym->stack) {    
3080                 pic14_emitcode("mov","a,sp");
3081                 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3082                 pic14_emitcode("mov","sp,a");
3083         }
3084         
3085         
3086         if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3087                 if (options.useXstack) {
3088                         pic14_emitcode("mov","r0,%s",spname);
3089                         pic14_emitcode("movx","a,@r0");
3090                         pic14_emitcode("mov","_bp,a");
3091                         pic14_emitcode("dec","%s",spname);
3092                 }
3093                 else
3094                 {
3095                         pic14_emitcode ("pop","_bp");
3096                 }
3097         }
3098         
3099         /* restore the register bank    */        
3100         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3101                 pic14_emitcode ("pop","psw");
3102         
3103         if (IFFUNC_ISISR(sym->type)) {
3104                 
3105                 /* now we need to restore the registers */
3106                 /* if this isr has no bank i.e. is going to
3107                 run with bank 0 , then we need to save more
3108 registers :-) */
3109                 if (!FUNC_REGBANK(sym->type)) {
3110                         
3111                 /* if this function does not call any other
3112                 function then we can be economical and
3113                         save only those registers that are used */
3114                         if (! IFFUNC_HASFCALL(sym->type)) {
3115                                 int i;
3116                                 
3117                                 /* if any registers used */
3118                                 if (sym->regsUsed) {
3119                                         /* save the registers used */
3120                                         for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3121                                                 if (bitVectBitValue(sym->regsUsed,i) ||
3122                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3123                                                         pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3124                                         }
3125                                 }
3126                                 
3127                         } else {
3128                         /* this function has    a function call cannot
3129                         determines register usage so we will have the
3130                                 entire bank */
3131                                 unsaverbank(0,ic,FALSE);
3132                         }       
3133                 }
3134 #if 0
3135                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3136                 {
3137                         if (options.stack10bit)
3138                         {
3139                                 pic14_emitcode ("pop", "dpx1");
3140                                 pic14_emitcode ("pop", "dph1");
3141                                 pic14_emitcode ("pop", "dpl1");
3142                         } 
3143                         pic14_emitcode ("pop", "dps");
3144                         pic14_emitcode ("pop", "dpx");
3145                 }
3146                 if (!inExcludeList("dph"))
3147                         pic14_emitcode ("pop","dph");
3148                 if (!inExcludeList("dpl"))
3149                         pic14_emitcode ("pop","dpl");
3150                 if (!inExcludeList("b"))
3151                         pic14_emitcode ("pop","b");
3152                 if (!inExcludeList("acc"))
3153                         pic14_emitcode ("pop","acc");
3154                 
3155                 if (IFFUNC_ISCRITICAL(sym->type))
3156                         pic14_emitcode("setb","ea");
3157 #endif
3158                 
3159                 /* if debug then send end of function */
3160                 /*      if (options.debug && currFunc) { */
3161                 if (currFunc) {
3162                         debugFile->writeEndFunction (currFunc, ic, 1);
3163                 }
3164                 
3165                 pic14_emitcode ("reti","");
3166                 emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
3167                 emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
3168                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
3169                 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3170                 emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
3171                 emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
3172                 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3173                 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3174                 emitpcodeNULLop(POC_RETFIE);
3175         }
3176         else {
3177                 if (IFFUNC_ISCRITICAL(sym->type))
3178                         pic14_emitcode("setb","ea");
3179                 
3180                 if (IFFUNC_CALLEESAVES(sym->type)) {
3181                         int i;
3182                         
3183                         /* if any registers used */
3184                         if (sym->regsUsed) {
3185                                 /* save the registers used */
3186                                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3187                                         if (bitVectBitValue(sym->regsUsed,i) ||
3188                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3189                                                 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3190                                 }
3191                         }
3192                         
3193                 }
3194                 
3195                 /* if debug then send end of function */
3196                 if (currFunc) {
3197                         debugFile->writeEndFunction (currFunc, ic, 1);
3198                 }
3199                 
3200                 pic14_emitcode ("return","");
3201                 emitpcodeNULLop(POC_RETURN);
3202                 
3203                 /* Mark the end of a function */
3204                 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3205         }
3206         
3207 }
3208
3209 /*-----------------------------------------------------------------*/
3210 /* genRet - generate code for return statement                                     */
3211 /*-----------------------------------------------------------------*/
3212 static void genRet (iCode *ic)
3213 {
3214         int size,offset = 0;
3215         
3216         FENTRY;
3217
3218         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3219         /* if we have no return value then
3220         just generate the "ret" */
3221         if (!IC_LEFT(ic)) 
3222                 goto jumpret;           
3223         
3224                 /* we have something to return then
3225         move the return value into place */
3226         aopOp(IC_LEFT(ic),ic,FALSE);
3227         size = AOP_SIZE(IC_LEFT(ic));
3228
3229         for (offset = 0; offset < size; offset++)
3230         {
3231                 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3232         }
3233         
3234         freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3235         
3236 jumpret:
3237         /* generate a jump to the return label
3238         if the next is not the return statement */
3239         if (!(ic->next && ic->next->op == LABEL &&
3240                 IC_LABEL(ic->next) == returnLabel)) {
3241                 
3242                 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3243         }
3244         
3245 }
3246
3247 /*-----------------------------------------------------------------*/
3248 /* genLabel - generates a label                                                                    */
3249 /*-----------------------------------------------------------------*/
3250 static void genLabel (iCode *ic)
3251 {
3252         FENTRY;
3253
3254         /* special case never generate */
3255         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3256         if (IC_LABEL(ic) == entryLabel)
3257                 return ;
3258         
3259         emitpLabel(IC_LABEL(ic)->key);
3260         pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3261 }
3262
3263 /*-----------------------------------------------------------------*/
3264 /* genGoto - generates a goto                                                                      */
3265 /*-----------------------------------------------------------------*/
3266 //tsd
3267 static void genGoto (iCode *ic)
3268 {
3269         FENTRY;
3270
3271         emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3272         pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3273 }
3274
3275
3276 /*-----------------------------------------------------------------*/
3277 /* genMultbits :- multiplication of bits                                                   */
3278 /*-----------------------------------------------------------------*/
3279 static void genMultbits (operand *left, 
3280                                                  operand *right, 
3281                                                  operand *result)
3282 {
3283         FENTRY;
3284         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3285         
3286         if(!pic14_sameRegs(AOP(result),AOP(right)))
3287                 emitpcode(POC_BSF,      popGet(AOP(result),0));
3288         
3289         emitpcode(POC_BTFSC,popGet(AOP(right),0));
3290         emitpcode(POC_BTFSS,popGet(AOP(left),0));
3291         emitpcode(POC_BCF,  popGet(AOP(result),0));
3292         
3293 }
3294
3295
3296 /*-----------------------------------------------------------------*/
3297 /* genMultOneByte : 8 bit multiplication & division                        */
3298 /*-----------------------------------------------------------------*/
3299 static void genMultOneByte (operand *left,
3300                                                         operand *right,
3301                                                         operand *result)
3302 {
3303         char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3304         
3305         // symbol *lbl ;
3306         int size,offset,i;
3307         
3308         
3309         FENTRY;
3310         
3311         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3312         DEBUGpic14_AopType(__LINE__,left,right,result);
3313         DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3314         
3315         /* (if two literals, the value is computed before) */
3316         /* if one literal, literal on the right */
3317         if (AOP_TYPE(left) == AOP_LIT){
3318                 operand *t = right;
3319                 right = left;
3320                 left = t;
3321         }
3322
3323         assert (AOP_SIZE(left) == AOP_SIZE(right));
3324         
3325         size = min(AOP_SIZE(result),AOP_SIZE(left));
3326         offset = Gstack_base_addr - (2*size - 1);
3327
3328         /* pass right operand as argument */
3329         for (i=0; i < size; i++)
3330         {
3331                 mov2w (AOP(right), i);
3332                 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3333         } // for
3334         
3335         /* pass left operand as argument */
3336         for (i=0; i < size; i++)
3337         {
3338                 mov2w (AOP(left), i);
3339                 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3340         } // for
3341         assert (offset == Gstack_base_addr);
3342         
3343         /* call library routine */
3344         assert (size > 0 && size <= 4);
3345         call_libraryfunc (func[size]);
3346         
3347         /* assign result */
3348         movwf (AOP(result), size-1);
3349         for (i=0; i < size - 1; i++)
3350         {
3351                 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3352                 movwf (AOP(result), size - 2 - i);
3353         } // for
3354
3355         /* now (zero-/sign) extend the result to its size */
3356         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3357 }
3358
3359 /*-----------------------------------------------------------------*/
3360 /* genMult - generates code for multiplication                                     */
3361 /*-----------------------------------------------------------------*/
3362 static void genMult (iCode *ic)
3363 {
3364         operand *left = IC_LEFT(ic);
3365         operand *right = IC_RIGHT(ic);
3366         operand *result= IC_RESULT(ic); 
3367         
3368         FENTRY;
3369
3370         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3371         /* assign the amsops */
3372         aopOp (left,ic,FALSE);
3373         aopOp (right,ic,FALSE);
3374         aopOp (result,ic,TRUE);
3375         
3376         DEBUGpic14_AopType(__LINE__,left,right,result);
3377         
3378         /* special cases first */
3379         /* both are bits */
3380         if (AOP_TYPE(left) == AOP_CRY &&
3381                 AOP_TYPE(right)== AOP_CRY) {
3382                 genMultbits(left,right,result);
3383                 goto release ;
3384         }
3385         
3386         /* if both are of size == 1 */
3387         if (AOP_SIZE(left) == 1 &&
3388                 AOP_SIZE(right) == 1 ) {
3389                 genMultOneByte(left,right,result);
3390                 goto release ;
3391         }
3392         
3393         /* should have been converted to function call */
3394         assert(0) ;
3395         
3396 release :
3397         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3398         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3399         freeAsmop(result,NULL,ic,TRUE); 
3400 }
3401
3402 /*-----------------------------------------------------------------*/
3403 /* genDivbits :- division of bits                                                                  */
3404 /*-----------------------------------------------------------------*/
3405 static void genDivbits (operand *left, 
3406                                                 operand *right, 
3407                                                 operand *result)
3408 {
3409         
3410         char *l;
3411         
3412         FENTRY;
3413
3414         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3415         /* the result must be bit */      
3416         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3417         l = aopGet(AOP(left),0,FALSE,FALSE);
3418         
3419         MOVA(l);          
3420         
3421         pic14_emitcode("div","ab");
3422         pic14_emitcode("rrc","a");
3423         aopPut(AOP(result),"c",0);
3424 }
3425
3426 /*-----------------------------------------------------------------*/
3427 /* genDivOneByte : 8 bit division                                                                  */
3428 /*-----------------------------------------------------------------*/
3429 static void genDivOneByte (operand *left,
3430                                                    operand *right,
3431                                                    operand *result)
3432 {
3433         int size;
3434         
3435         FENTRY;
3436         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3437         
3438         assert (AOP_SIZE(result) == 1);
3439         assert (AOP_SIZE(right) == 1);
3440         assert (AOP_SIZE(left) == 1);
3441
3442         size = min(AOP_SIZE(result),AOP_SIZE(left));
3443
3444         if (AOP_TYPE(right) == AOP_LIT)
3445         {
3446                 /* XXX: might add specialized code */
3447         }
3448
3449         if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3450         {
3451                 /* unsigned division */
3452         #if 1
3453                 mov2w(AOP(right),0);
3454                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3455                 mov2w(AOP(left),0);
3456                 call_libraryfunc("__divuchar");
3457                 movwf(AOP(result),0);
3458         #else
3459                 pCodeOp *temp;
3460                 symbol *lbl;
3461
3462                 temp = popGetTempReg();
3463                 lbl = newiTempLabel(NULL);
3464                 
3465                 /* XXX: improve this naive approach:
3466                    [result] = [a] / [b]
3467                         ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3468
3469                    In PIC assembler:
3470                    movf  left,W
3471                    movwf temp           // temp <-- left
3472                    movf  right,W        // W <-- right
3473                    clrf  result
3474                    label1:
3475                    incf  result
3476                    subwf temp,F         // temp <-- temp - W
3477                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if temp < W
3478                    goto  label1
3479                    decf result          // we just subtract once too often
3480                  */
3481
3482                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3483                 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3484                 
3485                 mov2w(AOP(left),0);
3486                 emitpcode(POC_MOVWF, temp);
3487                 mov2w(AOP(right),0);
3488                 emitpcode(POC_CLRF, popGet(AOP(result),0));
3489
3490                 emitpLabel(lbl->key);
3491                 emitpcode(POC_INCF, popGet(AOP(result),0));
3492                 emitpcode(POC_SUBWF, temp);
3493                 emitSKPNC;
3494                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3495                 emitpcode(POC_DECF, popGet(AOP(result),0));
3496         #endif
3497         }
3498         else
3499         {
3500                 /* signed division */
3501                 mov2w(AOP(right),0);
3502                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3503                 mov2w(AOP(left),0);
3504                 call_libraryfunc("__divschar");
3505                 movwf(AOP(result),0);
3506         }
3507
3508         /* now performed the signed/unsigned division -- extend result */
3509         addSign(result, 1, !SPEC_USIGN(operandType(result)));
3510 }
3511
3512 /*-----------------------------------------------------------------*/
3513 /* genDiv - generates code for division                            */
3514 /*-----------------------------------------------------------------*/
3515 static void genDiv (iCode *ic)
3516 {
3517         operand *left = IC_LEFT(ic);
3518         operand *right = IC_RIGHT(ic);
3519         operand *result= IC_RESULT(ic); 
3520         
3521         FENTRY;
3522         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3523         /* assign the amsops */
3524         aopOp (left,ic,FALSE);
3525         aopOp (right,ic,FALSE);
3526         aopOp (result,ic,TRUE);
3527         
3528         /* special cases first */
3529         /* both are bits */
3530         if (AOP_TYPE(left) == AOP_CRY &&
3531                 AOP_TYPE(right)== AOP_CRY) {
3532                 genDivbits(left,right,result);
3533                 goto release ;
3534         }
3535         
3536         /* if both are of size == 1 */
3537         if (AOP_SIZE(left) == 1 &&
3538                 AOP_SIZE(right) == 1 ) {
3539                 genDivOneByte(left,right,result);
3540                 goto release ;
3541         }
3542         
3543         /* should have been converted to function call */
3544         assert(0);
3545 release :
3546         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3547         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3548         freeAsmop(result,NULL,ic,TRUE); 
3549 }
3550
3551 /*-----------------------------------------------------------------*/
3552 /* genModbits :- modulus of bits                                                                   */
3553 /*-----------------------------------------------------------------*/
3554 static void genModbits (operand *left, 
3555                                                 operand *right, 
3556                                                 operand *result)
3557 {
3558         
3559         char *l;
3560         
3561         FENTRY;
3562         /* the result must be bit */      
3563         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3564         l = aopGet(AOP(left),0,FALSE,FALSE);
3565         
3566         MOVA(l);
3567         
3568         pic14_emitcode("div","ab");
3569         pic14_emitcode("mov","a,b");
3570         pic14_emitcode("rrc","a");
3571         aopPut(AOP(result),"c",0);
3572 }
3573
3574 /*-----------------------------------------------------------------*/
3575 /* genModOneByte : 8 bit modulus                                                                   */
3576 /*-----------------------------------------------------------------*/
3577 static void genModOneByte (operand *left,
3578                                                    operand *right,
3579                                                    operand *result)
3580 {
3581         int size;
3582         
3583         FENTRY;
3584         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3585         
3586         assert (AOP_SIZE(result) == 1);
3587         assert (AOP_SIZE(right) == 1);
3588         assert (AOP_SIZE(left) == 1);
3589
3590         size = min(AOP_SIZE(result),AOP_SIZE(left));
3591
3592         if (AOP_TYPE(right) == AOP_LIT)
3593         {
3594                 /* XXX: might add specialized code */
3595         }
3596
3597         if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3598         {
3599                 /* unsigned division */
3600         #if 1
3601                 mov2w(AOP(right),0);
3602                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3603                 mov2w(AOP(left),0);
3604                 call_libraryfunc("__moduchar");
3605                 movwf(AOP(result),0);
3606         #else
3607                 pCodeOp *temp;
3608                 symbol *lbl;
3609
3610                 lbl = newiTempLabel(NULL);
3611                 
3612                 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3613
3614                 /* XXX: improve this naive approach:
3615                    [result] = [a] % [b]
3616                         ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3617
3618                    In PIC assembler:
3619                    movf  left,W
3620                    movwf result         // result <-- left
3621                    movf  right,W        // W <-- right
3622                    label1:
3623                    subwf result,F       // result <-- result - W
3624                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if result < W
3625                    goto  label1
3626                    addwf result, F      // we just subtract once too often
3627                  */
3628
3629                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3630                 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3631                 
3632                 if (!pic14_sameRegs(AOP(left), AOP(result)))
3633                 {
3634                         mov2w(AOP(left),0);
3635                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
3636                 }
3637                 mov2w(AOP(right),0);
3638
3639                 emitpLabel(lbl->key);
3640                 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3641                 emitSKPNC;
3642                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3643                 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3644         #endif
3645         }
3646         else
3647         {
3648                 /* signed division */
3649                 mov2w(AOP(right),0);
3650                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3651                 mov2w(AOP(left),0);
3652                 call_libraryfunc("__modschar");
3653                 movwf(AOP(result),0);
3654         }
3655
3656         /* now we performed the signed/unsigned modulus -- extend result */
3657         addSign(result, 1, !SPEC_USIGN(operandType(result)));
3658 }
3659
3660 /*-----------------------------------------------------------------*/
3661 /* genMod - generates code for division                                                    */
3662 /*-----------------------------------------------------------------*/
3663 static void genMod (iCode *ic)
3664 {
3665         operand *left = IC_LEFT(ic);
3666         operand *right = IC_RIGHT(ic);
3667         operand *result= IC_RESULT(ic);  
3668         
3669         FENTRY;
3670         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3671         /* assign the amsops */
3672         aopOp (left,ic,FALSE);
3673         aopOp (right,ic,FALSE);
3674         aopOp (result,ic,TRUE);
3675         
3676         /* special cases first */
3677         /* both are bits */
3678         if (AOP_TYPE(left) == AOP_CRY &&
3679                 AOP_TYPE(right)== AOP_CRY) {
3680                 genModbits(left,right,result);
3681                 goto release ;
3682         }
3683         
3684         /* if both are of size == 1 */
3685         if (AOP_SIZE(left) == 1 &&
3686                 AOP_SIZE(right) == 1 ) {
3687                 genModOneByte(left,right,result);
3688                 goto release ;
3689         }
3690         
3691         /* should have been converted to function call */
3692         assert(0);
3693         
3694 release :
3695         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3696         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3697         freeAsmop(result,NULL,ic,TRUE); 
3698 }
3699
3700 /*-----------------------------------------------------------------*/
3701 /* genIfxJump :- will create a jump depending on the ifx                   */
3702 /*-----------------------------------------------------------------*/
3703 /*
3704 note: May need to add parameter to indicate when a variable is in bit space.
3705 */
3706 static void genIfxJump (iCode *ic, char *jval)
3707 {
3708         
3709         FENTRY;
3710         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3711         /* if true label then we jump if condition
3712         supplied is true */
3713         if ( IC_TRUE(ic) ) {
3714                 
3715                 if(strcmp(jval,"a") == 0)
3716                         emitSKPZ;
3717                 else if (strcmp(jval,"c") == 0)
3718                         emitSKPC;
3719                 else {
3720                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3721                         emitpcode(POC_BTFSC,    newpCodeOpBit(jval,-1,1));
3722                 }
3723                 
3724                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3725                 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3726                 
3727         }
3728         else {
3729                 /* false label is present */
3730                 if(strcmp(jval,"a") == 0)
3731                         emitSKPNZ;
3732                 else if (strcmp(jval,"c") == 0)
3733                         emitSKPNC;
3734                 else {
3735                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3736                         emitpcode(POC_BTFSS,    newpCodeOpBit(jval,-1,1));
3737                 }
3738                 
3739                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3740                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3741                 
3742         }
3743         
3744         
3745         /* mark the icode as generated */
3746         ic->generated = 1;
3747 }
3748
3749 #if 0
3750 /*-----------------------------------------------------------------*/
3751 /* genSkip                                                                                                                 */
3752 /*-----------------------------------------------------------------*/
3753 static void genSkip(iCode *ifx,int status_bit)
3754 {
3755         FENTRY;
3756         if(!ifx)
3757                 return;
3758         
3759         if ( IC_TRUE(ifx) ) {
3760                 switch(status_bit) {
3761                 case 'z':
3762                         emitSKPNZ;
3763                         break;
3764                         
3765                 case 'c':
3766                         emitSKPNC;
3767                         break;
3768                         
3769                 case 'd':
3770                         emitSKPDC;
3771                         break;
3772                         
3773                 }
3774                 
3775                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3776                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3777                 
3778         } else {
3779                 
3780                 switch(status_bit) {
3781                         
3782                 case 'z':
3783                         emitSKPZ;
3784                         break;
3785                         
3786                 case 'c':
3787                         emitSKPC;
3788                         break;
3789                         
3790                 case 'd':
3791                         emitSKPDC;
3792                         break;
3793                 }
3794                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3795                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3796                 
3797         }
3798         
3799 }
3800 #endif
3801
3802 /*-----------------------------------------------------------------*/
3803 /* genSkipc                                                                                                        */
3804 /*-----------------------------------------------------------------*/
3805 static void genSkipc(resolvedIfx *rifx)
3806 {
3807         FENTRY;
3808         if(!rifx)
3809                 return;
3810         
3811         if(rifx->condition)
3812                 emitSKPNC;
3813         else
3814                 emitSKPC;
3815         
3816         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3817         emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3818         rifx->generated = 1;
3819 }
3820
3821 #if 0
3822 /*-----------------------------------------------------------------*/
3823 /* genSkipz2                                                                                                       */
3824 /*-----------------------------------------------------------------*/
3825 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3826 {
3827         FENTRY;
3828         if(!rifx)
3829                 return;
3830         
3831         if( (rifx->condition ^ invert_condition) & 1)
3832                 emitSKPZ;
3833         else
3834                 emitSKPNZ;
3835         
3836         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3837         rifx->generated = 1;
3838 }
3839 #endif
3840
3841 #if 0
3842 /*-----------------------------------------------------------------*/
3843 /* genSkipz                                                        */
3844 /*-----------------------------------------------------------------*/
3845 static void genSkipz(iCode *ifx, int condition)
3846 {
3847         FENTRY;
3848         assert (ifx != NULL);
3849         
3850         if(condition)
3851                 emitSKPNZ;
3852         else
3853                 emitSKPZ;
3854         
3855         if ( IC_TRUE(ifx) )
3856                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3857         else
3858                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3859         
3860         if ( IC_TRUE(ifx) )
3861                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3862         else
3863                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3864         
3865 }
3866 #endif
3867
3868 #if 0
3869 /*-----------------------------------------------------------------*/
3870 /* genSkipCond                                                     */
3871 /*-----------------------------------------------------------------*/
3872 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3873 {
3874         FENTRY;
3875         if(!rifx)
3876                 return;
3877         
3878         if(rifx->condition)
3879                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3880         else
3881                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3882         
3883         
3884         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3885         rifx->generated = 1;
3886 }
3887 #endif
3888
3889 #if 0
3890 /*-----------------------------------------------------------------*/
3891 /* genChkZeroes :- greater or less than comparison                 */
3892 /*     For each byte in a literal that is zero, inclusive or the   */
3893 /*     the corresponding byte in the operand with W                */
3894 /*     returns true if any of the bytes are zero                   */
3895 /*-----------------------------------------------------------------*/
3896 static int genChkZeroes(operand *op, int lit,  int size)
3897 {
3898         
3899         int i;
3900         int flag =1;
3901         
3902         while(size--) {
3903                 i = (lit >> (size*8)) & 0xff;
3904                 
3905                 if(i==0) {
3906                         if(flag) 
3907                                 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3908                         else
3909                                 emitpcode(POC_IORFW, popGet(AOP(op),size));
3910                         flag = 0;
3911                 }
3912         }
3913         
3914         return (flag==0);
3915 }
3916 #endif
3917
3918
3919 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3920 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
3921 #define DEBUGpc           emitpComment
3922
3923 /*-----------------------------------------------------------------*/
3924 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
3925 /*                  aop (if it's NOT a literal) or from lit (if    */
3926 /*                  aop is a literal)                              */
3927 /*-----------------------------------------------------------------*/
3928 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3929   if (aop->type == AOP_LIT) {
3930     emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3931   } else {
3932     emitpcode (POC_MOVFW, popGet (aop, offset));
3933   }
3934 }
3935
3936 /* genCmp performs a left < right comparison, stores
3937  * the outcome in result (if != NULL) and generates
3938  * control flow code for the ifx (if != NULL).
3939  *
3940  * This version leaves in sequences like
3941  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3942  * which should be optmized by the peephole
3943  * optimizer - RN 2005-01-01 */
3944 static void genCmp (operand *left,operand *right,
3945                     operand *result, iCode *ifx, int sign)
3946 {
3947   resolvedIfx rIfx;
3948   int size;
3949   int offs;
3950   symbol *templbl;
3951   operand *dummy;
3952   unsigned long lit;
3953   unsigned long mask;
3954   int performedLt;
3955   int invert_result = 0;
3956
3957   FENTRY;
3958   
3959   assert (AOP_SIZE(left) == AOP_SIZE(right));
3960   assert (left && right);
3961
3962   size = AOP_SIZE(right) - 1;
3963   mask = (0x100UL << (size*8)) - 1;
3964   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3965   performedLt = 1;
3966   templbl = NULL;
3967   lit = 0;
3968   
3969   resolveIfx (&rIfx, ifx);
3970
3971   /**********************************************************************
3972    * handle bits - bit compares are promoted to int compares seemingly! *
3973    **********************************************************************/
3974 #if 0
3975   // THIS IS COMPLETELY UNTESTED!
3976   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3977     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3978     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3979     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3980
3981     emitSETC;
3982     // 1 < {0,1} is false --> clear C by skipping the next instruction
3983     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3984     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3985     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3986     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3987     emitCLRC; // only skipped for left=0 && right=1
3988
3989     goto correct_result_in_carry;
3990   } // if
3991 #endif
3992
3993   /*************************************************
3994    * make sure that left is register (or the like) *
3995    *************************************************/
3996   if (!isAOP_REGlike(left)) {
3997     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3998     assert (isAOP_LIT(left));
3999     assert (isAOP_REGlike(right));
4000     // swap left and right
4001     // left < right <==> right > left <==> (right >= left + 1)
4002     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4003
4004     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4005       // MAXVALUE < right? always false
4006       if (performedLt) emitCLRC; else emitSETC;
4007       goto correct_result_in_carry;
4008     } // if
4009
4010     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4011     // that's why we handled it above.
4012     lit++;
4013
4014     dummy = left;
4015     left = right;
4016     right = dummy;
4017
4018     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4019   } else if (isAOP_LIT(right)) {
4020     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4021   } // if
4022
4023   assert (isAOP_REGlike(left)); // left must be register or the like
4024   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4025
4026   /*************************************************
4027    * special cases go here                         *
4028    *************************************************/
4029
4030   if (isAOP_LIT(right)) {
4031     if (!sign) {
4032       // unsigned comparison to a literal
4033       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4034       if (lit == 0) {
4035         // unsigned left < 0? always false
4036         if (performedLt) emitCLRC; else emitSETC;
4037         goto correct_result_in_carry;
4038       }
4039     } else {
4040       // signed comparison to a literal
4041       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4042       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4043         // signed left < 0x80000000? always false
4044         if (performedLt) emitCLRC; else emitSETC;
4045         goto correct_result_in_carry;
4046       } else if (lit == 0) {
4047         // compare left < 0; set CARRY if SIGNBIT(left) is set
4048         if (performedLt) emitSETC; else emitCLRC;
4049         emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
4050         if (performedLt) emitCLRC; else emitSETC;
4051         goto correct_result_in_carry;
4052       }
4053     } // if (!sign)
4054   } // right is literal
4055
4056   /*************************************************
4057    * perform a general case comparison             *
4058    * make sure we get CARRY==1 <==> left >= right  *
4059    *************************************************/
4060   // compare most significant bytes
4061   //DEBUGpc ("comparing bytes at offset %d", size);
4062   if (!sign) {
4063     // unsigned comparison
4064     pic14_mov2w_regOrLit (AOP(right), lit, size);
4065     emitpcode (POC_SUBFW, popGet (AOP(left), size));
4066   } else {
4067     // signed comparison
4068     // (add 2^n to both operands then perform an unsigned comparison)
4069     if (isAOP_LIT(right)) {
4070       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4071       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4072
4073       if (litbyte == 0x80) {
4074         // left >= 0x80 -- always true, but more bytes to come
4075         mov2w (AOP(left), size);
4076         emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
4077         emitSETC;
4078       } else {
4079         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4080         mov2w (AOP(left), size);
4081         emitpcode (POC_ADDLW, popGetLit (0x80));
4082         emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4083       } // if
4084     } else {
4085       pCodeOp *pctemp = popGetTempReg();
4086       mov2w (AOP(left), size);
4087       emitpcode (POC_ADDLW, popGetLit (0x80));
4088       emitpcode (POC_MOVWF, pctemp);
4089       mov2w (AOP(right), size);
4090       emitpcode (POC_ADDLW, popGetLit (0x80));
4091       emitpcode (POC_SUBFW, pctemp);
4092       popReleaseTempReg(pctemp);
4093     }
4094   } // if (!sign)
4095
4096   // compare remaining bytes (treat as unsigned case from above)
4097   templbl = newiTempLabel ( NULL );
4098   offs = size;
4099   while (offs--) {
4100     //DEBUGpc ("comparing bytes at offset %d", offs);
4101     emitSKPZ;
4102     emitpcode (POC_GOTO, popGetLabel (templbl->key));
4103     pic14_mov2w_regOrLit (AOP(right), lit, offs);
4104     emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4105   } // while (offs)
4106   emitpLabel (templbl->key);
4107   goto result_in_carry;
4108
4109 result_in_carry:
4110   
4111   /****************************************************
4112    * now CARRY contains the result of the comparison: *
4113    * SUBWF sets CARRY iff                             *
4114    * F-W >= 0 <==> F >= W <==> !(F < W)               *
4115    * (F=left, W=right)                                *
4116    ****************************************************/
4117
4118   if (performedLt) {
4119     invert_result = 1;
4120     // value will be used in the following genSkipc()
4121     rIfx.condition ^= 1;
4122   } // if
4123
4124 correct_result_in_carry:
4125
4126   // assign result to variable (if neccessary)
4127   if (result && AOP_TYPE(result) != AOP_CRY) {
4128     //DEBUGpc ("assign result");
4129     size = AOP_SIZE(result);
4130     while (size--) {
4131       emitpcode (POC_CLRF, popGet (AOP(result), size));
4132     } // while
4133     if (invert_result) {
4134       emitSKPC;
4135       emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4136     } else {
4137       emitpcode (POC_RLF, popGet (AOP(result), 0));
4138     }
4139   } // if (result)
4140
4141   // perform conditional jump
4142   if (ifx) {
4143     //DEBUGpc ("generate control flow");
4144     genSkipc (&rIfx);
4145     ifx->generated = 1;
4146   } // if
4147 }
4148
4149
4150 #if 0
4151 /* OLD VERSION -- BUGGY, DO NOT USE */
4152
4153 /*-----------------------------------------------------------------*/
4154 /* genCmp :- greater or less than comparison                       */
4155 /*-----------------------------------------------------------------*/
4156 static void genCmp (operand *left,operand *right,
4157                                         operand *result, iCode *ifx, int sign)
4158 {
4159         int size; //, offset = 0 ;
4160         unsigned long lit = 0L,i = 0;
4161         resolvedIfx rFalseIfx;
4162         //  resolvedIfx rTrueIfx;
4163         symbol *truelbl;
4164
4165         FENTRY;
4166         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4167         /*
4168         if(ifx) {
4169         DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4170         DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4171         }
4172         */
4173         
4174         resolveIfx(&rFalseIfx,ifx);
4175         truelbl  = newiTempLabel(NULL);
4176         size = max(AOP_SIZE(left),AOP_SIZE(right));
4177         
4178         DEBUGpic14_AopType(__LINE__,left,right,result);
4179         
4180 #define _swapp
4181         
4182         /* if literal is on the right then swap with left */
4183         if ((AOP_TYPE(right) == AOP_LIT)) {
4184                 operand *tmp = right ;
4185                 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4186                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4187 #ifdef _swapp
4188                 
4189                 lit = (lit - 1) & mask;
4190                 right = left;
4191                 left = tmp;
4192                 rFalseIfx.condition ^= 1;
4193 #endif
4194                 
4195         } else if ((AOP_TYPE(left) == AOP_LIT)) {
4196                 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4197         }
4198         
4199         
4200         //if(IC_TRUE(ifx) == NULL)
4201         /* if left & right are bit variables */
4202         if (AOP_TYPE(left) == AOP_CRY &&
4203                 AOP_TYPE(right) == AOP_CRY ) {
4204                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4205                 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4206         } else {
4207         /* subtract right from left if at the
4208         end the carry flag is set then we know that
4209                 left is greater than right */
4210                 
4211                 symbol *lbl  = newiTempLabel(NULL);
4212                 
4213 #ifndef _swapp
4214                 if(AOP_TYPE(right) == AOP_LIT) {
4215                         
4216                         //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4217                         
4218                         DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4219                         
4220                         /* special cases */
4221                         
4222                         if(lit == 0) {
4223                                 
4224                                 if(sign != 0) 
4225                                         genSkipCond(&rFalseIfx,left,size-1,7);
4226                                 else 
4227                                         /* no need to compare to 0...*/
4228                                         /* NOTE: this is a de-generate compare that most certainly 
4229                                         *       creates some dead code. */
4230                                         emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4231                                 
4232                                 if(ifx) ifx->generated = 1;
4233                                 return;
4234                                 
4235                         }
4236                         size--;
4237                         
4238                         if(size == 0) {
4239                                 //i = (lit >> (size*8)) & 0xff;
4240                                 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4241                                 
4242                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4243                                 
4244                                 i = ((0-lit) & 0xff);
4245                                 if(sign) {
4246                                         if( i == 0x81) { 
4247                                         /* lit is 0x7f, all signed chars are less than
4248                                                 * this except for 0x7f itself */
4249                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4250                                                 genSkipz2(&rFalseIfx,0);
4251                                         } else {
4252                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4253                                                 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4254                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4255                                         }
4256                                         
4257                                 } else {
4258                                         if(lit == 1) {
4259                                                 genSkipz2(&rFalseIfx,1);
4260                                         } else {
4261                                                 emitpcode(POC_ADDLW, popGetLit(i));
4262                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4263                                         }
4264                                 }
4265                                 
4266                                 if(ifx) ifx->generated = 1;
4267                                 return;
4268                         }
4269                         
4270                         /* chars are out of the way. now do ints and longs */
4271                         
4272                         
4273                         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4274                         
4275                         /* special cases */
4276                         
4277                         if(sign) {
4278                                 
4279                                 if(lit == 0) {
4280                                         genSkipCond(&rFalseIfx,left,size,7);
4281                                         if(ifx) ifx->generated = 1;
4282                                         return;
4283                                 }
4284                                 
4285                                 if(lit <0x100) {
4286                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4287                                         
4288                                         //rFalseIfx.condition ^= 1;
4289                                         //genSkipCond(&rFalseIfx,left,size,7);
4290                                         //rFalseIfx.condition ^= 1;
4291                                         
4292                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4293                                         if(rFalseIfx.condition)
4294                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4295                                         else
4296                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4297                                         
4298                                         emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4299                                         emitpcode(POC_ADDFW, popGet(AOP(left),0));
4300                                         emitpcode(POC_MOVFW, popGet(AOP(left),1));
4301                                         
4302                                         while(size > 1)
4303                                                 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4304                                         
4305                                         if(rFalseIfx.condition) {
4306                                                 emitSKPZ;
4307                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4308                                                 
4309                                         } else {
4310                                                 emitSKPNZ;
4311                                         }
4312                                         
4313                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4314                                         emitpLabel(truelbl->key);
4315                                         if(ifx) ifx->generated = 1;
4316                                         return;
4317                                         
4318                                 }
4319                                 
4320                                 if(size == 1) {
4321                                         
4322                                         if( (lit & 0xff) == 0) {
4323                                                 /* lower byte is zero */
4324                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4325                                                 i = ((lit >> 8) & 0xff) ^0x80;
4326                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4327                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4328                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4329                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4330                                                 
4331                                                 
4332                                                 if(ifx) ifx->generated = 1;
4333                                                 return;
4334                                                 
4335                                         }
4336                                 } else {
4337                                         /* Special cases for signed longs */
4338                                         if( (lit & 0xffffff) == 0) {
4339                                                 /* lower byte is zero */
4340                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4341                                                 i = ((lit >> 8*3) & 0xff) ^0x80;
4342                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4343                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4344                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4345                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4346                                                 
4347                                                 
4348                                                 if(ifx) ifx->generated = 1;
4349                                                 return;
4350                                                 
4351                                         }
4352                                         
4353                                 }
4354                                 
4355                                 
4356                                 if(lit & (0x80 << (size*8))) {
4357                                         /* lit is negative */
4358                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4359                                         
4360                                         //genSkipCond(&rFalseIfx,left,size,7);
4361                                         
4362                                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4363                                         
4364                                         if(rFalseIfx.condition)
4365                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4366                                         else
4367                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4368                                         
4369                                         
4370                                 } else {
4371                                         /* lit is positive */
4372                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4373                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4374                                         if(rFalseIfx.condition)
4375                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4376                                         else
4377                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4378                                         
4379                                 }
4380                                 
4381                                 /* There are no more special cases, so perform a general compare */
4382                                 
4383                                 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4384                                 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4385                                 
4386                                 while(size--) {
4387                                         
4388                                         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4389                                         emitSKPNZ;
4390                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4391                                 }
4392                                 //rFalseIfx.condition ^= 1;
4393                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4394                                 
4395                                 emitpLabel(truelbl->key);
4396                                 
4397                                 if(ifx) ifx->generated = 1;
4398                                 return;
4399                                 
4400                                 
4401                         }
4402
4403
4404                         /* sign is out of the way. So now do an unsigned compare */
4405                         DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4406
4407
4408                         /* General case - compare to an unsigned literal on the right.*/
4409
4410                         i = (lit >> (size*8)) & 0xff;
4411                         emitpcode(POC_MOVLW, popGetLit(i));
4412                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4413                         while(size--) {
4414                                 i = (lit >> (size*8)) & 0xff;
4415                                 
4416                                 if(i) {
4417                                         emitpcode(POC_MOVLW, popGetLit(i));
4418                                         emitSKPNZ;
4419                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4420                                 } else {
4421                                 /* this byte of the lit is zero, 
4422                                         *if it's not the last then OR in the variable */
4423                                         if(size)
4424                                                 emitpcode(POC_IORFW, popGet(AOP(left),size));
4425                                 }
4426                         }
4427
4428
4429                 emitpLabel(lbl->key);
4430                 //if(emitFinalCheck)
4431                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4432                 if(sign)
4433                         emitpLabel(truelbl->key);
4434
4435                 if(ifx) ifx->generated = 1;
4436                 return;
4437
4438
4439                 }
4440 #endif  // _swapp
4441
4442                 if(AOP_TYPE(left) == AOP_LIT) {
4443                         //symbol *lbl = newiTempLabel(NULL);
4444                         
4445                         //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4446                         
4447                         
4448                         DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4449                         
4450                         /* Special cases */
4451                         if((lit == 0) && (sign == 0)){
4452                                 
4453                                 size--;
4454                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4455                                 while(size) 
4456                                         emitpcode(POC_IORFW, popGet(AOP(right),--size));
4457                                 
4458                                 genSkipz2(&rFalseIfx,0);
4459                                 if(ifx) ifx->generated = 1;
4460                                 return;
4461                         }
4462                         
4463                         if(size==1) {
4464                                 /* Special cases */
4465                                 lit &= 0xff;
4466                                 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4467                                         /* degenerate compare can never be true */
4468                                         if(rFalseIfx.condition == 0)
4469                                                 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4470                                         
4471                                         if(ifx) ifx->generated = 1;
4472                                         return;
4473                                 }
4474                                 
4475                                 if(sign) {
4476                                         /* signed comparisons to a literal byte */
4477                                         
4478                                         int lp1 = (lit+1) & 0xff;
4479                                         
4480                                         DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4481                                         switch (lp1) {
4482                                         case 0:
4483                                                 rFalseIfx.condition ^= 1;
4484                                                 genSkipCond(&rFalseIfx,right,0,7);
4485                                                 break;
4486                                         case 0x7f:
4487                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4488                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4489                                                 genSkipz2(&rFalseIfx,1);
4490                                                 break;
4491                                         default:
4492                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4493                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4494                                                 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4495                                                 rFalseIfx.condition ^= 1;
4496                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4497                                                 break;
4498                                         }
4499                                         if(ifx) ifx->generated = 1;
4500                                 } else {
4501                                         /* unsigned comparisons to a literal byte */
4502                                         
4503                                         switch(lit & 0xff ) {
4504                                         case 0:
4505                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4506                                                 genSkipz2(&rFalseIfx,0);
4507                                                 if(ifx) ifx->generated = 1;
4508                                                 break;
4509                                         case 0x7f:
4510                                                 genSkipCond(&rFalseIfx,right,0,7);
4511                                                 if(ifx) ifx->generated = 1;
4512                                                 break;
4513                                                 
4514                                         default:
4515                                                 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4516                                                 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4517                                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4518                                                 rFalseIfx.condition ^= 1;
4519                                                 if (AOP_TYPE(result) == AOP_CRY) {
4520                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4521                                                         if(ifx) ifx->generated = 1;
4522                                                 } else {
4523                                                         DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4524                                                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4525                                                         emitpcode(POC_RLF, popGet(AOP(result),0));
4526                                                         emitpcode(POC_MOVLW, popGetLit(0x01));
4527                                                         emitpcode(POC_XORWF, popGet(AOP(result),0));
4528                                                 }       
4529                                                 break;
4530                                         }
4531                                 }
4532                                 
4533                                 //goto check_carry;
4534                                 return;
4535                                 
4536                         } else {
4537                                 
4538                                 /* Size is greater than 1 */
4539                                 
4540                                 if(sign) {
4541                                         int lp1 = lit+1;
4542                                         
4543                                         size--;
4544                                         
4545                                         if(lp1 == 0) {
4546                                                 /* this means lit = 0xffffffff, or -1 */
4547                                                 
4548                                                 
4549                                                 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4550                                                 rFalseIfx.condition ^= 1;
4551                                                 genSkipCond(&rFalseIfx,right,size,7);
4552                                                 if(ifx) ifx->generated = 1;
4553                                                 return;
4554                                         }
4555                                         
4556                                         if(lit == 0) {
4557                                                 int s = size;
4558                                                 
4559                                                 if(rFalseIfx.condition) {
4560                                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4561                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4562                                                 }
4563                                                 
4564                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4565                                                 while(size--)
4566                                                         emitpcode(POC_IORFW, popGet(AOP(right),size));
4567                                                 
4568                                                 
4569                                                 emitSKPZ;
4570                                                 if(rFalseIfx.condition) {
4571                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4572                                                         emitpLabel(truelbl->key);
4573                                                 }else {
4574                                                         rFalseIfx.condition ^= 1;
4575                                                         genSkipCond(&rFalseIfx,right,s,7);
4576                                                 }
4577                                                 
4578                                                 if(ifx) ifx->generated = 1;
4579                                                 return;
4580                                         }
4581                                         
4582                                         if((size == 1) &&  (0 == (lp1&0xff))) {
4583                                                 /* lower byte of signed word is zero */
4584                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4585                                                 i = ((lp1 >> 8) & 0xff) ^0x80;
4586                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4587                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4588                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4589                                                 rFalseIfx.condition ^= 1;
4590                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4591                                                 
4592                                                 
4593                                                 if(ifx) ifx->generated = 1;
4594                                                 return;
4595                                         }
4596                                         
4597                                         if(lit & (0x80 << (size*8))) {
4598                                                 /* Lit is less than zero */
4599                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4600                                                 //rFalseIfx.condition ^= 1;
4601                                                 //genSkipCond(&rFalseIfx,left,size,7);
4602                                                 //rFalseIfx.condition ^= 1;
4603                                                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4604                                                 //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4605                                                 
4606                                                 if(rFalseIfx.condition)
4607                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4608                                                 else
4609                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4610                                                 
4611                                                 
4612                                         } else {
4613                                                 /* Lit is greater than or equal to zero */
4614                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4615                                                 //rFalseIfx.condition ^= 1;
4616                                                 //genSkipCond(&rFalseIfx,right,size,7);
4617                                                 //rFalseIfx.condition ^= 1;
4618                                                 
4619                                                 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4620                                                 //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4621                                                 
4622                                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4623                                                 if(rFalseIfx.condition)
4624                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4625                                                 else
4626                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4627                                                 
4628                                         }
4629                                         
4630                                         
4631                                         emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4632                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4633                                         
4634                                         while(size--) {
4635                                                 
4636                                                 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4637                                                 emitSKPNZ;
4638                                                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4639                                         }
4640                                         rFalseIfx.condition ^= 1;
4641                                         //rFalseIfx.condition = 1;
4642                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4643                                         
4644                                         emitpLabel(truelbl->key);
4645                                         
4646                                         if(ifx) ifx->generated = 1;
4647                                         return;
4648                                         // end of if (sign)
4649                                 } else {
4650                                         
4651                                         /* compare word or long to an unsigned literal on the right.*/
4652                                         
4653                                         
4654                                         size--;
4655                                         if(lit < 0xff) {
4656                                                 DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4657                                                 switch (lit) {
4658                                                 case 0:
4659                                                         break; /* handled above */
4660                                                 /*
4661                                                 case 0xff:
4662                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4663                                                         while(size--)
4664                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4665                                                         genSkipz2(&rFalseIfx,0);
4666                                                         break;
4667                                                 */
4668                                                 default:
4669                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4670                                                         while(--size)
4671                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4672                                                         
4673                                                         emitSKPZ;
4674                                                         if(rFalseIfx.condition)
4675                                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4676                                                         else
4677                                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4678                                                         
4679                                                         
4680                                                         emitpcode(POC_MOVLW, popGetLit(lit+1));
4681                                                         emitpcode(POC_SUBFW, popGet(AOP(right),0));
4682                                                         
4683                                                         rFalseIfx.condition ^= 1;
4684                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4685                                                 }
4686                                                 
4687                                                 emitpLabel(truelbl->key);
4688                                                 
4689                                                 if(ifx) ifx->generated = 1;
4690                                                 return;
4691                                         }
4692                                         
4693                                         
4694                                         lit++;
4695                                         DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4696                                         i = (lit >> (size*8)) & 0xff;
4697                                         
4698                                         emitpcode(POC_MOVLW, popGetLit(i));
4699                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4700                                         
4701                                         while(size--) {
4702                                                 i = (lit >> (size*8)) & 0xff;
4703                                                 
4704                                                 if(i) {
4705                                                         emitpcode(POC_MOVLW, popGetLit(i));
4706                                                         emitSKPNZ;
4707                                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4708                                                 } else {
4709                                                 /* this byte of the lit is zero, 
4710                                                         *if it's not the last then OR in the variable */
4711                                                         if(size)
4712                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4713                                                 }
4714                                         }
4715                                         
4716                                         
4717                                         emitpLabel(lbl->key);
4718                                         
4719                                         rFalseIfx.condition ^= 1;
4720                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4721                                 }
4722                                 
4723                                 if(sign)
4724                                         emitpLabel(truelbl->key);
4725                                 if(ifx) ifx->generated = 1;
4726                                 return;
4727                         }
4728                 }
4729                 /* Compare two variables */
4730                 
4731                 DEBUGpic14_emitcode(";sign","%d",sign);
4732                 
4733                 size--;
4734                 if(sign) {
4735                         /* Sigh. thus sucks... */
4736                         if(size) {
4737                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4738                                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4739                                 emitpcode(POC_MOVLW, popGetLit(0x80));
4740                                 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4741                                 emitpcode(POC_XORFW, popGet(AOP(right),size));
4742                                 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4743                         } else {
4744                                 /* Signed char comparison */
4745                                 /* Special thanks to Nikolai Golovchenko for this snippet */
4746                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4747                                 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4748                                 emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4749                                 emitpcode(POC_XORFW, popGet(AOP(left),0));
4750                                 emitpcode(POC_XORFW, popGet(AOP(right),0));
4751                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4752                                 
4753                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4754                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4755                                 
4756                                 if(ifx) ifx->generated = 1;
4757                                 return;
4758                         }
4759                         
4760                 } else {
4761                         
4762                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4763                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4764                 }
4765                 
4766                 
4767                 /* The rest of the bytes of a multi-byte compare */
4768                 while (size) {
4769                         
4770                         emitSKPZ;
4771                         emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4772                         size--;
4773                         
4774                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4775                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4776                         
4777                         
4778                 }
4779                 
4780                 emitpLabel(lbl->key);
4781                 
4782                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4783                 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4784                         (AOP_TYPE(result) == AOP_REG)) {
4785                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4786                         emitpcode(POC_RLF, popGet(AOP(result),0));
4787                 } else {
4788                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4789                 }       
4790                 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4791                 if(ifx) ifx->generated = 1;
4792                 
4793                 return;
4794                 
4795         }
4796         
4797         // check_carry:
4798         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4799                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4800                 pic14_outBitC(result);
4801         } else {
4802                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4803                 /* if the result is used in the next
4804                 ifx conditional branch then generate
4805                 code a little differently */
4806                 if (ifx )
4807                         genIfxJump (ifx,"c");
4808                 else
4809                         pic14_outBitC(result);
4810                 /* leave the result in acc */
4811         }
4812         
4813 }
4814 #endif
4815
4816 /*-----------------------------------------------------------------*/
4817 /* genCmpGt :- greater than comparison                             */
4818 /*-----------------------------------------------------------------*/
4819 static void genCmpGt (iCode *ic, iCode *ifx)
4820 {
4821         operand *left, *right, *result;
4822         sym_link *letype , *retype;
4823         int sign ;
4824         
4825         FENTRY;
4826         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4827         left = IC_LEFT(ic);
4828         right= IC_RIGHT(ic);
4829         result = IC_RESULT(ic);
4830         
4831         letype = getSpec(operandType(left));
4832         retype =getSpec(operandType(right));
4833         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4834         /* assign the amsops */
4835         aopOp (left,ic,FALSE);
4836         aopOp (right,ic,FALSE);
4837         aopOp (result,ic,TRUE);
4838         
4839         genCmp(right, left, result, ifx, sign);
4840         
4841         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4842         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4843         freeAsmop(result,NULL,ic,TRUE); 
4844 }
4845
4846 /*-----------------------------------------------------------------*/
4847 /* genCmpLt - less than comparisons                                */
4848 /*-----------------------------------------------------------------*/
4849 static void genCmpLt (iCode *ic, iCode *ifx)
4850 {
4851         operand *left, *right, *result;
4852         sym_link *letype , *retype;
4853         int sign ;
4854         
4855         FENTRY;
4856         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4857         left = IC_LEFT(ic);
4858         right= IC_RIGHT(ic);
4859         result = IC_RESULT(ic);
4860         
4861         letype = getSpec(operandType(left));
4862         retype =getSpec(operandType(right));
4863         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4864         
4865         /* assign the amsops */
4866         aopOp (left,ic,FALSE);
4867         aopOp (right,ic,FALSE);
4868         aopOp (result,ic,TRUE);
4869         
4870         genCmp(left, right, result, ifx, sign);
4871         
4872         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4873         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4874         freeAsmop(result,NULL,ic,TRUE); 
4875 }
4876
4877 #if 0
4878 /*-----------------------------------------------------------------*/
4879 /* genc16bit2lit - compare a 16 bit value to a literal             */
4880 /*-----------------------------------------------------------------*/
4881 static void genc16bit2lit(operand *op, int lit, int offset)
4882 {
4883         int i;
4884         
4885         FENTRY;
4886         DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4887         if( (lit&0xff) == 0) 
4888                 i=1;
4889         else
4890                 i=0;
4891         
4892         switch( BYTEofLONG(lit,i)) { 
4893         case 0:
4894                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4895                 break;
4896         case 1:
4897                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4898                 break;
4899         case 0xff:
4900                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4901                 break;
4902         default:
4903                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4904                 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4905         }
4906         
4907         i ^= 1;
4908         
4909         switch( BYTEofLONG(lit,i)) { 
4910         case 0:
4911                 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4912                 break;
4913         case 1:
4914                 emitSKPNZ;
4915                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4916                 break;
4917         case 0xff:
4918                 emitSKPNZ;
4919                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4920                 break;
4921         default:
4922                 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4923                 emitSKPNZ;
4924                 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4925                 
4926         }
4927         
4928 }
4929 #endif
4930
4931 #if 0
4932 /*-----------------------------------------------------------------*/
4933 /* gencjneshort - compare and jump if not equal                    */
4934 /*-----------------------------------------------------------------*/
4935 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4936 {
4937         int size = min(AOP_SIZE(left),AOP_SIZE(right));
4938         int offset = 0;
4939         //resolvedIfx rIfx;
4940         symbol *lbl;
4941         
4942         //unsigned long lit = 0L;
4943         FENTRY;
4944         if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4945           emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4946           return;
4947         }
4948         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4949         DEBUGpic14_AopType(__LINE__,left,right,result);
4950         
4951         assert (!pic14_sameRegs (AOP(left), AOP(result)));
4952         assert (!pic14_sameRegs (AOP(right), AOP(result)));
4953         if (AOP_SIZE(result)) {
4954           for (offset = 0; offset < AOP_SIZE(result); offset++)
4955             emitpcode (POC_CLRF, popGet (AOP(result), offset));
4956         }
4957         
4958         assert (AOP_SIZE(left) == AOP_SIZE(right));
4959         //resolveIfx(&rIfx,ifx);
4960         lbl = newiTempLabel (NULL);
4961         while (size--)
4962         {
4963           mov2w (AOP(right),size);
4964           emitpcode (POC_XORFW, popGet (AOP(left), size));
4965           if (size)
4966           {
4967             emitSKPZ;
4968             emitpcode (POC_GOTO, popGetLabel (lbl->key));
4969           }
4970         } // while
4971         emitpLabel (lbl->key);
4972         if (AOP_SIZE(result)) {
4973           emitSKPNZ;
4974           emitpcode (POC_INCF, popGet (AOP(result), 0));
4975         } else {
4976           assert (ifx);
4977           genSkipz (ifx, NULL != IC_TRUE(ifx));
4978           ifx->generated = 1;
4979         }
4980         return;
4981 #if 0   
4982         if(result)
4983         {
4984                 DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4985                 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4986                 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4987                 for (offset=0; offset < AOP_SIZE(result); offset++)
4988                 {
4989                         emitpcode (POC_CLRF, popGet (AOP(result), offset));
4990                 } // for offset
4991         }
4992         
4993         
4994         /* if the left side is a literal or 
4995         if the right is in a pointer register and left 
4996         is not */
4997         if ((AOP_TYPE(left) == AOP_LIT) || 
4998                 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4999                 operand *t = right;
5000                 right = left;
5001                 left = t;
5002         }
5003         if(AOP_TYPE(right) == AOP_LIT)
5004                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5005         
5006         /* if the right side is a literal then anything goes */
5007         if (AOP_TYPE(right) == AOP_LIT &&
5008                 AOP_TYPE(left) != AOP_DIR ) {
5009                 switch(size) {
5010                 case 2:
5011                         genc16bit2lit(left, lit, 0);
5012                         emitSKPNZ;
5013                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
5014                         break;
5015                 default:
5016                         offset = 0;
5017                         while (size--) {
5018                                 if(lit & 0xff) {
5019                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5020                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5021                                 } else {
5022                                         emitpcode(POC_MOVF,popGet(AOP(left),offset));
5023                                 }
5024                                 
5025                                 emitSKPNZ;
5026                                 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5027                                 offset++;
5028                                 lit >>= 8;
5029                         }
5030                         break;
5031                 }
5032         }
5033         
5034         /* if the right side is in a register or in direct space or
5035         if the left is a pointer register & right is not */    
5036         else if (AOP_TYPE(right) == AOP_REG ||
5037                 AOP_TYPE(right) == AOP_DIR || 
5038                 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5039                 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5040                 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5041                 int lbl_key = lbl->key;
5042                 
5043                 if(!result) {
5044                         DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5045                         fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5046                                 __FUNCTION__,__LINE__);
5047                         return;
5048                 }
5049                 
5050                 /*     switch(size) { */
5051                 /*     case 2: */
5052                 /*       genc16bit2lit(left, lit, 0); */
5053                 /*       emitSKPNZ; */
5054                 /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
5055                 /*       break; */
5056                 /*     default: */
5057                 offset = 0;
5058                 while (size--) {
5059                         int emit_skip=1;
5060                         if((AOP_TYPE(left) == AOP_DIR) && 
5061                                 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5062                                 
5063                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5064                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5065                                 
5066                         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5067                                 
5068                                 switch (lit & 0xff) {
5069                                 case 0:
5070                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5071                                         break;
5072                                 case 1:
5073                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5074                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5075                                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
5076                                         emit_skip=0;
5077                                         break;
5078                                 case 0xff:
5079                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5080                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5081                                         //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5082                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5083                                         emit_skip=0;
5084                                         break;
5085                                 default:
5086                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5087                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5088                                 }
5089                                 lit >>= 8;
5090                                 
5091                         } else {
5092                                 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5093                         }
5094                         if(emit_skip) {
5095                                 if(AOP_TYPE(result) == AOP_CRY) {
5096                                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5097                                         if(rIfx.condition)
5098                                                 emitSKPNZ;
5099                                         else
5100                                                 emitSKPZ;
5101                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5102                                 } else {
5103                                         /* fix me. probably need to check result size too */
5104                                         //emitpcode(POC_CLRF,popGet(AOP(result),0));
5105                                         if(rIfx.condition)
5106                                                 emitSKPZ;
5107                                         else
5108                                                 emitSKPNZ;
5109                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5110                                 }
5111                                 if(ifx)
5112                                         ifx->generated=1;
5113                         }
5114                         emit_skip++;
5115                         offset++;
5116                 }
5117                 /*       break; */
5118                 /*     } */
5119         } else if(AOP_TYPE(right) == AOP_REG &&
5120                 AOP_TYPE(left) != AOP_DIR){
5121
5122                 offset = 0;
5123                 while(size--) {
5124                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5125                         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5126                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5127                         if(rIfx.condition)
5128                                 emitSKPNZ;
5129                         else
5130                                 emitSKPZ;
5131                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5132                         offset++;
5133                 }
5134                 
5135         }else{
5136                 /* right is a pointer reg need both a & b */
5137                 offset = 0;
5138                 while(size--) {
5139                         char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5140                         if(strcmp(l,"b"))
5141                                 pic14_emitcode("mov","b,%s",l);
5142                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5143                         pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5144                         offset++;
5145                 }
5146         }
5147         
5148         emitpcode(POC_INCF,popGet(AOP(result),0));
5149         if(!rIfx.condition)
5150                 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5151         
5152         emitpLabel(lbl->key);
5153         
5154         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5155         
5156         if(ifx)
5157                 ifx->generated = 1;
5158 #endif
5159 }
5160 #endif
5161
5162 #if 0
5163 /*-----------------------------------------------------------------*/
5164 /* gencjne - compare and jump if not equal                         */
5165 /*-----------------------------------------------------------------*/
5166 static void gencjne(operand *left, operand *right, iCode *ifx)
5167 {
5168         symbol *tlbl  = newiTempLabel(NULL);
5169         
5170         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5171         gencjneshort(left, right, lbl);
5172         
5173         pic14_emitcode("mov","a,%s",one);
5174         pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5175         pic14_emitcode("","%05d_DS_:",lbl->key+100);
5176         pic14_emitcode("clr","a");
5177         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5178         
5179         emitpLabel(lbl->key);
5180         emitpLabel(tlbl->key);
5181         
5182 }
5183 #endif
5184
5185 /*-----------------------------------------------------------------*/
5186 /* genCmpEq - generates code for equal to                          */
5187 /*-----------------------------------------------------------------*/
5188 static void genCmpEq (iCode *ic, iCode *ifx)
5189 {
5190   operand *left, *right, *result;
5191   int size;
5192   symbol *false_label;
5193
5194   FENTRY;
5195   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5196
5197   if(ifx)
5198     DEBUGpic14_emitcode ("; ifx is non-null","");
5199   else
5200     DEBUGpic14_emitcode ("; ifx is null","");
5201
5202   aopOp((left=IC_LEFT(ic)),ic,FALSE);
5203   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5204   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5205
5206   DEBUGpic14_AopType(__LINE__,left,right,result);
5207
5208   /* if literal, move literal to right */ 
5209   if (op_isLitLike (IC_LEFT(ic))) {
5210     operand *tmp = right ;
5211     right = left;
5212     left = tmp;
5213   }
5214
5215   false_label = NULL;
5216   if (ifx && !IC_TRUE(ifx))
5217   {
5218     assert (IC_FALSE(ifx));
5219     false_label = IC_FALSE(ifx);
5220   }
5221
5222   size = min(AOP_SIZE(left),AOP_SIZE(right));
5223   assert(!pic14_sameRegs(AOP(result),AOP(left)));
5224   assert(!pic14_sameRegs(AOP(result),AOP(right)));
5225
5226   /* assume left != right */
5227   {
5228     int i;
5229     for (i=0; i < AOP_SIZE(result); i++)
5230     {
5231       emitpcode(POC_CLRF, popGet(AOP(result),i));
5232     }
5233   }
5234
5235   if (AOP_TYPE(right) == AOP_LIT)
5236   {
5237     unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5238     int i;
5239     size = AOP_SIZE(left);
5240     assert(!op_isLitLike(left));
5241
5242     switch (lit)
5243     {
5244       case 0:
5245         mov2w(AOP(left), 0);
5246         for (i=1; i < size; i++)
5247           emitpcode(POC_IORFW,popGet(AOP(left),i));
5248         /* now Z is set iff `left == right' */
5249         emitSKPZ;
5250         if (!false_label) false_label = newiTempLabel(NULL);
5251         emitpcode(POC_GOTO, popGetLabel(false_label->key));
5252         break;
5253
5254       default:
5255         for (i=0; i < size; i++)
5256         {
5257           mov2w(AOP(left),i);
5258           emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5259           /* now Z is cleared if `left != right' */
5260           emitSKPZ;
5261           if (!false_label) false_label = newiTempLabel(NULL);
5262           emitpcode(POC_GOTO, popGetLabel(false_label->key));
5263         } // for i
5264         break;
5265     } // switch (lit)
5266   }
5267   else
5268   {
5269     /* right is no literal */
5270     int i;
5271
5272     for (i=0; i < size; i++)
5273     {
5274       mov2w(AOP(right),i);
5275       emitpcode(POC_XORFW,popGet(AOP(left),i));
5276       /* now Z is cleared if `left != right' */
5277       emitSKPZ;
5278       if (!false_label) false_label = newiTempLabel(NULL);
5279       emitpcode(POC_GOTO, popGetLabel(false_label->key));
5280     } // for i
5281   }
5282
5283   /* if we reach here, left == right */
5284
5285   if (AOP_SIZE(result) > 0)
5286   {
5287     emitpcode(POC_INCF, popGet(AOP(result),0));
5288   }
5289
5290   if (ifx && IC_TRUE(ifx))
5291   {
5292     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5293   }
5294
5295   if (false_label && (!ifx || IC_TRUE(ifx)))
5296     emitpLabel(false_label->key);
5297
5298   if (ifx) ifx->generated = 1;
5299
5300   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5301   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5302   freeAsmop(result,NULL,ic,TRUE);
5303 }
5304
5305 /*-----------------------------------------------------------------*/
5306 /* ifxForOp - returns the icode containing the ifx for operand     */
5307 /*-----------------------------------------------------------------*/
5308 static iCode *ifxForOp ( operand *op, iCode *ic )
5309 {
5310         FENTRY;
5311         /* if true symbol then needs to be assigned */
5312         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5313         if (IS_TRUE_SYMOP(op))
5314                 return NULL ;
5315         
5316         /* if this has register type condition and
5317         the next instruction is ifx with the same operand
5318         and live to of the operand is upto the ifx only then */
5319         if (ic->next &&
5320                 ic->next->op == IFX &&
5321                 IC_COND(ic->next)->key == op->key &&
5322                 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5323                 return ic->next;
5324         
5325         if (ic->next &&
5326                 ic->next->op == IFX &&
5327                 IC_COND(ic->next)->key == op->key) {
5328                 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5329                 return ic->next;
5330         }
5331         
5332         DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5333         if (ic->next &&
5334                 ic->next->op == IFX)
5335                 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5336         
5337         if (ic->next &&
5338                 ic->next->op == IFX &&
5339                 IC_COND(ic->next)->key == op->key) {
5340                 DEBUGpic14_emitcode ("; "," key is okay");
5341                 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5342                         OP_SYMBOL(op)->liveTo,
5343                         ic->next->seq);
5344         }
5345         
5346         
5347         return NULL;
5348 }
5349 /*-----------------------------------------------------------------*/
5350 /* genAndOp - for && operation                                     */
5351 /*-----------------------------------------------------------------*/
5352 static void genAndOp (iCode *ic)
5353 {
5354         operand *left,*right, *result;
5355         /*     symbol *tlbl; */
5356         
5357         FENTRY;
5358         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5359         /* note here that && operations that are in an
5360         if statement are taken away by backPatchLabels
5361         only those used in arthmetic operations remain */
5362         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5363         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5364         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5365         
5366         DEBUGpic14_AopType(__LINE__,left,right,result);
5367         
5368         emitpcode(POC_MOVFW,popGet(AOP(left),0));
5369         emitpcode(POC_ANDFW,popGet(AOP(right),0));
5370         emitpcode(POC_MOVWF,popGet(AOP(result),0));
5371         
5372         /* if both are bit variables */
5373         /*     if (AOP_TYPE(left) == AOP_CRY && */
5374         /*         AOP_TYPE(right) == AOP_CRY ) { */
5375         /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5376         /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5377         /*         pic14_outBitC(result); */
5378         /*     } else { */
5379         /*         tlbl = newiTempLabel(NULL); */
5380         /*         pic14_toBoolean(left);     */
5381         /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5382         /*         pic14_toBoolean(right); */
5383         /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5384         /*         pic14_outBitAcc(result); */
5385         /*     } */
5386         
5387         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5388         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5389         freeAsmop(result,NULL,ic,TRUE);
5390 }
5391
5392
5393 /*-----------------------------------------------------------------*/
5394 /* genOrOp - for || operation                                      */
5395 /*-----------------------------------------------------------------*/
5396 /*
5397 tsd pic port -
5398 modified this code, but it doesn't appear to ever get called
5399 */
5400
5401 static void genOrOp (iCode *ic)
5402 {
5403         operand *left,*right, *result;
5404         symbol *tlbl;
5405         int i;
5406         
5407         /* note here that || operations that are in an
5408         if statement are taken away by backPatchLabels
5409         only those used in arthmetic operations remain */
5410         FENTRY;
5411         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5412         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5413         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5414         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5415         
5416         DEBUGpic14_AopType(__LINE__,left,right,result);
5417
5418         for (i=0; i < AOP_SIZE(result); i++)
5419         {
5420                 emitpcode(POC_CLRF, popGet(AOP(result), i));
5421         } // for i
5422
5423         tlbl = newiTempLabel(NULL);
5424         pic14_toBoolean(left);
5425         emitSKPZ;
5426         emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5427         pic14_toBoolean(right);
5428         emitpLabel(tlbl->key);
5429         /* here Z is clear IFF `left || right' */
5430         emitSKPZ;
5431         emitpcode(POC_INCF, popGet(AOP(result), 0));
5432         
5433         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5434         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5435         freeAsmop(result,NULL,ic,TRUE);            
5436 }
5437
5438 /*-----------------------------------------------------------------*/
5439 /* isLiteralBit - test if lit == 2^n                               */
5440 /*-----------------------------------------------------------------*/
5441 static int isLiteralBit(unsigned long lit)
5442 {
5443         unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5444                 0x100L,0x200L,0x400L,0x800L,
5445                 0x1000L,0x2000L,0x4000L,0x8000L,
5446                 0x10000L,0x20000L,0x40000L,0x80000L,
5447                 0x100000L,0x200000L,0x400000L,0x800000L,
5448                 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5449                 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5450         int idx;
5451         
5452         FENTRY;
5453         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5454         for(idx = 0; idx < 32; idx++)
5455                 if(lit == pw[idx])
5456                         return idx+1;
5457                 return 0;
5458 }
5459
5460 /*-----------------------------------------------------------------*/
5461 /* continueIfTrue -                                                */
5462 /*-----------------------------------------------------------------*/
5463 static void continueIfTrue (iCode *ic)
5464 {
5465         FENTRY;
5466         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5467         if(IC_TRUE(ic))
5468                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5469         ic->generated = 1;
5470 }
5471
5472 /*-----------------------------------------------------------------*/
5473 /* jmpIfTrue -                                                     */
5474 /*-----------------------------------------------------------------*/
5475 static void jumpIfTrue (iCode *ic)
5476 {
5477         FENTRY;
5478         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5479         if(!IC_TRUE(ic))
5480                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5481         ic->generated = 1;
5482 }
5483
5484 /*-----------------------------------------------------------------*/
5485 /* jmpTrueOrFalse -                                                */
5486 /*-----------------------------------------------------------------*/
5487 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5488 {
5489         FENTRY;
5490         // ugly but optimized by peephole
5491         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5492         if(IC_TRUE(ic)){
5493                 symbol *nlbl = newiTempLabel(NULL);
5494                 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5495                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5496                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5497                 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5498         }
5499         else{
5500                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5501                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5502         }
5503         ic->generated = 1;
5504 }
5505
5506 /*-----------------------------------------------------------------*/
5507 /* genAnd  - code for and                                          */
5508 /*-----------------------------------------------------------------*/
5509 static void genAnd (iCode *ic, iCode *ifx)
5510 {
5511         operand *left, *right, *result;
5512         int size, offset=0;  
5513         unsigned long lit = 0L;
5514         int bytelit = 0;
5515         resolvedIfx rIfx;
5516         
5517         FENTRY;
5518         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5519         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5520         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5521         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5522         
5523         resolveIfx(&rIfx,ifx);
5524         
5525         /* if left is a literal & right is not then exchange them */
5526         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5527                 AOP_NEEDSACC(left)) {
5528                 operand *tmp = right ;
5529                 right = left;
5530                 left = tmp;
5531         }
5532         
5533         /* if result = right then exchange them */
5534         if(pic14_sameRegs(AOP(result),AOP(right))){
5535                 operand *tmp = right ;
5536                 right = left;
5537                 left = tmp;
5538         }
5539         
5540         /* if right is bit then exchange them */
5541         if (AOP_TYPE(right) == AOP_CRY &&
5542                 AOP_TYPE(left) != AOP_CRY){
5543                 operand *tmp = right ;
5544                 right = left;
5545                 left = tmp;
5546         }
5547         if(AOP_TYPE(right) == AOP_LIT)
5548                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5549         
5550         size = AOP_SIZE(result);
5551         
5552         DEBUGpic14_AopType(__LINE__,left,right,result);
5553         
5554         // if(bit & yy)
5555         // result = bit & yy;
5556         if (AOP_TYPE(left) == AOP_CRY){
5557                 // c = bit & literal;
5558                 if(AOP_TYPE(right) == AOP_LIT){
5559                         if(lit & 1) {
5560                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5561                                         // no change
5562                                         goto release;
5563                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5564                         } else {
5565                                 // bit(result) = 0;
5566                                 if(size && (AOP_TYPE(result) == AOP_CRY)){
5567                                         pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5568                                         goto release;
5569                                 }
5570                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5571                                         jumpIfTrue(ifx);
5572                                         goto release;
5573                                 }
5574                                 pic14_emitcode("clr","c");
5575                         }
5576                 } else {
5577                         if (AOP_TYPE(right) == AOP_CRY){
5578                                 // c = bit & bit;
5579                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5580                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5581                         } else {
5582                                 // c = bit & val;
5583                                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5584                                 // c = lsb
5585                                 pic14_emitcode("rrc","a");
5586                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5587                         }
5588                 }
5589                 // bit = c
5590                 // val = c
5591                 if(size)
5592                         pic14_outBitC(result);
5593                 // if(bit & ...)
5594                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5595                         genIfxJump(ifx, "c");           
5596                 goto release ;
5597         }
5598         
5599         // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5600         // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5601         if((AOP_TYPE(right) == AOP_LIT) &&
5602                 (AOP_TYPE(result) == AOP_CRY) &&
5603                 (AOP_TYPE(left) != AOP_CRY)){
5604                 int posbit = isLiteralBit(lit);
5605                 /* left &  2^n */
5606                 if(posbit){
5607                         posbit--;
5608                         //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5609                         // bit = left & 2^n
5610                         if(size)
5611                                 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5612                         // if(left &  2^n)
5613                         else{
5614                                 if(ifx){
5615                                         int offset = 0;
5616                                         while (posbit > 7) {
5617                                                 posbit -= 8;
5618                                                 offset++;
5619                                         }
5620                                         emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5621                                                 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5622                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5623                                         
5624                                         ifx->generated = 1;
5625                                 }
5626                                 goto release;
5627                         }
5628                 } else {
5629                         symbol *tlbl = newiTempLabel(NULL);
5630                         int sizel = AOP_SIZE(left);
5631                         if(size)
5632                                 pic14_emitcode("setb","c");
5633                         while(sizel--){
5634                                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5635                                         MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5636                                         // byte ==  2^n ?
5637                                         if((posbit = isLiteralBit(bytelit)) != 0)
5638                                                 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5639                                         else{
5640                                                 if(bytelit != 0x0FFL)
5641                                                         pic14_emitcode("anl","a,%s",
5642                                                         aopGet(AOP(right),offset,FALSE,TRUE));
5643                                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5644                                         }
5645                                 }
5646                                 offset++;
5647                         }
5648                         // bit = left & literal
5649                         if(size){
5650                                 pic14_emitcode("clr","c");
5651                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5652                         }
5653                         // if(left & literal)
5654                         else{
5655                                 if(ifx)
5656                                         jmpTrueOrFalse(ifx, tlbl);
5657                                 goto release ;
5658                         }
5659                 }
5660                 pic14_outBitC(result);
5661                 goto release ;
5662         }
5663         
5664         /* if left is same as result */
5665         if(pic14_sameRegs(AOP(result),AOP(left))){
5666                 int know_W = -1;
5667                 for(;size--; offset++,lit>>=8) {
5668                         if(AOP_TYPE(right) == AOP_LIT){
5669                                 switch(lit & 0xff) {
5670                                 case 0x00:
5671                                         /*  and'ing with 0 has clears the result */
5672                                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
5673                                         break;
5674                                 case 0xff:
5675                                         /* and'ing with 0xff is a nop when the result and left are the same */
5676                                         break;
5677                                         
5678                                 default:
5679                                         {
5680                                                 int p = my_powof2( (~lit) & 0xff );
5681                                                 if(p>=0) {
5682                                                         /* only one bit is set in the literal, so use a bcf instruction */
5683                                                         emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5684                                                         
5685                                                 } else {
5686                                                         if(know_W != (int)(lit&0xff))
5687                                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5688                                                         know_W = lit &0xff;
5689                                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5690                                                 }
5691                                         }    
5692                                 }
5693                         } else {
5694                                 if (AOP_TYPE(left) == AOP_ACC) {
5695                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5696                                 } else {        
5697                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5698                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5699                                         
5700                                 }
5701                         }
5702                 }
5703                 
5704         } else {
5705                 // left & result in different registers
5706                 if(AOP_TYPE(result) == AOP_CRY){
5707                         // result = bit
5708                         // if(size), result in bit
5709                         // if(!size && ifx), conditional oper: if(left & right)
5710                         symbol *tlbl = newiTempLabel(NULL);
5711                         int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5712                         if(size)
5713                                 pic14_emitcode("setb","c");
5714                         while(sizer--){
5715                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5716                                 pic14_emitcode("anl","a,%s",
5717                                         aopGet(AOP(left),offset,FALSE,FALSE));
5718                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5719                                 offset++;
5720                         }
5721                         if(size){
5722                                 CLRC;
5723                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5724                                 pic14_outBitC(result);
5725                         } else if(ifx)
5726                                 jmpTrueOrFalse(ifx, tlbl);
5727                 } else {
5728                         for(;(size--);offset++) {
5729                                 // normal case
5730                                 // result = left & right
5731                                 if(AOP_TYPE(right) == AOP_LIT){
5732                                         int t = (lit >> (offset*8)) & 0x0FFL;
5733                                         switch(t) { 
5734                                         case 0x00:
5735                                                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5736                                                 break;
5737                                         case 0xff:
5738                                                 if(AOP_TYPE(left) != AOP_ACC) {
5739                                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5740                                                 }
5741                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5742                                                 break;
5743                                         default:
5744                                                 if(AOP_TYPE(left) == AOP_ACC) {
5745                                                         emitpcode(POC_ANDLW, popGetLit(t));
5746                                                 } else {
5747                                                         emitpcode(POC_MOVLW, popGetLit(t));
5748                                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5749                                                 }
5750                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5751                                         }
5752                                         continue;
5753                                 }
5754                                 
5755                                 if (AOP_TYPE(left) == AOP_ACC) {
5756                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5757                                 } else {
5758                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5759                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5760                                 }
5761                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5762                         }
5763                 }
5764         }
5765         
5766 release :
5767         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5768         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5769         freeAsmop(result,NULL,ic,TRUE);     
5770 }
5771
5772 /*-----------------------------------------------------------------*/
5773 /* genOr  - code for or                                            */
5774 /*-----------------------------------------------------------------*/
5775 static void genOr (iCode *ic, iCode *ifx)
5776 {
5777         operand *left, *right, *result;
5778         int size, offset=0;
5779         unsigned long lit = 0L;
5780         
5781         FENTRY;
5782         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5783         
5784         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5785         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5786         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5787         
5788         DEBUGpic14_AopType(__LINE__,left,right,result);
5789         
5790         /* if left is a literal & right is not then exchange them */
5791         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5792                 AOP_NEEDSACC(left)) {
5793                 operand *tmp = right ;
5794                 right = left;
5795                 left = tmp;
5796         }
5797         
5798         /* if result = right then exchange them */
5799         if(pic14_sameRegs(AOP(result),AOP(right))){
5800                 operand *tmp = right ;
5801                 right = left;
5802                 left = tmp;
5803         }
5804         
5805         /* if right is bit then exchange them */
5806         if (AOP_TYPE(right) == AOP_CRY &&
5807                 AOP_TYPE(left) != AOP_CRY){
5808                 operand *tmp = right ;
5809                 right = left;
5810                 left = tmp;
5811         }
5812         
5813         DEBUGpic14_AopType(__LINE__,left,right,result);
5814         
5815         if(AOP_TYPE(right) == AOP_LIT)
5816                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5817         
5818         size = AOP_SIZE(result);
5819         
5820         // if(bit | yy)
5821         // xx = bit | yy;
5822         if (AOP_TYPE(left) == AOP_CRY){
5823                 if(AOP_TYPE(right) == AOP_LIT){
5824                         // c = bit & literal;
5825                         if(lit){
5826                                 // lit != 0 => result = 1
5827                                 if(AOP_TYPE(result) == AOP_CRY){
5828                                         if(size)
5829                                                 emitpcode(POC_BSF, popGet(AOP(result),0));
5830                                         //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5831                                         //   AOP(result)->aopu.aop_dir,
5832                                         //   AOP(result)->aopu.aop_dir);
5833                                         else if(ifx)
5834                                                 continueIfTrue(ifx);
5835                                         goto release;
5836                                 }
5837                         } else {
5838                                 // lit == 0 => result = left
5839                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5840                                         goto release;
5841                                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5842                         }
5843                 } else {
5844                         if (AOP_TYPE(right) == AOP_CRY){
5845                                 if(pic14_sameRegs(AOP(result),AOP(left))){
5846                                         // c = bit | bit;
5847                                         emitpcode(POC_BCF,   popGet(AOP(result),0));
5848                                         emitpcode(POC_BTFSC, popGet(AOP(right),0));
5849                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5850                                         
5851                                         pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5852                                                 AOP(result)->aopu.aop_dir,
5853                                                 AOP(result)->aopu.aop_dir);
5854                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5855                                                 AOP(right)->aopu.aop_dir,
5856                                                 AOP(right)->aopu.aop_dir);
5857                                         pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5858                                                 AOP(result)->aopu.aop_dir,
5859                                                 AOP(result)->aopu.aop_dir);
5860                                 } else {
5861                                         if( AOP_TYPE(result) == AOP_ACC) {
5862                                                 emitpcode(POC_MOVLW, popGetLit(0));
5863                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5864                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5865                                                 emitpcode(POC_MOVLW, popGetLit(1));
5866                                                 
5867                                         } else {
5868                                                 
5869                                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5870                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5871                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5872                                                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5873                                                 
5874                                                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5875                                                         AOP(result)->aopu.aop_dir,
5876                                                         AOP(result)->aopu.aop_dir);
5877                                                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5878                                                         AOP(right)->aopu.aop_dir,
5879                                                         AOP(right)->aopu.aop_dir);
5880                                                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5881                                                         AOP(left)->aopu.aop_dir,
5882                                                         AOP(left)->aopu.aop_dir);
5883                                                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5884                                                         AOP(result)->aopu.aop_dir,
5885                                                         AOP(result)->aopu.aop_dir);
5886                                         }
5887                                 }
5888                         } else {
5889                                 // c = bit | val;
5890                                 symbol *tlbl = newiTempLabel(NULL);
5891                                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5892                                 
5893                                 
5894                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5895                                 if( AOP_TYPE(right) == AOP_ACC) {
5896                                         emitpcode(POC_IORLW, popGetLit(0));
5897                                         emitSKPNZ;
5898                                         emitpcode(POC_BTFSC, popGet(AOP(left),0));
5899                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5900                                 }
5901                                 
5902                                 
5903                                 
5904                                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5905                                         pic14_emitcode(";XXX setb","c");
5906                                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5907                                         AOP(left)->aopu.aop_dir,tlbl->key+100);
5908                                 pic14_toBoolean(right);
5909                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5910                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5911                                         jmpTrueOrFalse(ifx, tlbl);
5912                                         goto release;
5913                                 } else {
5914                                         CLRC;
5915                                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5916                                 }
5917                         }
5918                 }
5919                 // bit = c
5920                 // val = c
5921                 if(size)
5922                         pic14_outBitC(result);
5923                 // if(bit | ...)
5924                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5925                         genIfxJump(ifx, "c");           
5926                 goto release ;
5927         }
5928
5929         // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5930         // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5931         if((AOP_TYPE(right) == AOP_LIT) &&
5932           (AOP_TYPE(result) == AOP_CRY) &&
5933           (AOP_TYPE(left) != AOP_CRY)){
5934                 if(lit){
5935                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5936                         // result = 1
5937                         if(size)
5938                                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5939                         else 
5940                                 continueIfTrue(ifx);
5941                         goto release;
5942                 } else {
5943                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5944                         // lit = 0, result = boolean(left)
5945                         if(size)
5946                                 pic14_emitcode(";XXX setb","c");
5947                         pic14_toBoolean(right);
5948                         if(size){
5949                                 symbol *tlbl = newiTempLabel(NULL);
5950                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5951                                 CLRC;
5952                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5953                         } else {
5954                                 genIfxJump (ifx,"a");
5955                                 goto release;
5956                         }
5957                 }
5958                 pic14_outBitC(result);
5959                 goto release ;
5960         }
5961
5962         /* if left is same as result */
5963         if(pic14_sameRegs(AOP(result),AOP(left))){
5964                 int know_W = -1;
5965                 for(;size--; offset++,lit>>=8) {
5966                         if(AOP_TYPE(right) == AOP_LIT){
5967                                 if((lit & 0xff) == 0)
5968                                         /*  or'ing with 0 has no effect */
5969                                         continue;
5970                                 else {
5971                                         int p = my_powof2(lit & 0xff);
5972                                         if(p>=0) {
5973                                                 /* only one bit is set in the literal, so use a bsf instruction */
5974                                                 emitpcode(POC_BSF,
5975                                                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5976                                         } else {
5977                                                 if(know_W != (int)(lit & 0xff))
5978                                                         emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5979                                                 know_W = lit & 0xff;
5980                                                 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5981                                         }
5982                                         
5983                                 }
5984                         } else {
5985                                 if (AOP_TYPE(left) == AOP_ACC) {
5986                                         emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5987                                         pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5988                                 } else {        
5989                                         emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5990                                         emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5991                                         
5992                                         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5993                                         pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5994                                         
5995                                 }
5996                         }
5997                 }
5998         } else {
5999                 // left & result in different registers
6000                 if(AOP_TYPE(result) == AOP_CRY){
6001                         // result = bit
6002                         // if(size), result in bit
6003                         // if(!size && ifx), conditional oper: if(left | right)
6004                         symbol *tlbl = newiTempLabel(NULL);
6005                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6006                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6007                         
6008                         
6009                         if(size)
6010                                 pic14_emitcode(";XXX setb","c");
6011                         while(sizer--){
6012                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6013                                 pic14_emitcode(";XXX orl","a,%s",
6014                                         aopGet(AOP(left),offset,FALSE,FALSE));
6015                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6016                                 offset++;
6017                         }
6018                         if(size){
6019                                 CLRC;
6020                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6021                                 pic14_outBitC(result);
6022                         } else if(ifx)
6023                                 jmpTrueOrFalse(ifx, tlbl);
6024                 } else for(;(size--);offset++){
6025                         // normal case
6026                         // result = left | right
6027                         if(AOP_TYPE(right) == AOP_LIT){
6028                                 int t = (lit >> (offset*8)) & 0x0FFL;
6029                                 switch(t) { 
6030                                 case 0x00:
6031                                         if (AOP_TYPE(left) != AOP_ACC) {
6032                                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
6033                                         }
6034                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6035                                         
6036                                         break;
6037                                 default:
6038                                         if (AOP_TYPE(left) == AOP_ACC) {
6039                                                 emitpcode(POC_IORLW,  popGetLit(t));
6040                                         } else {
6041                                                 emitpcode(POC_MOVLW,  popGetLit(t));
6042                                                 emitpcode(POC_IORFW,  popGet(AOP(left),offset));
6043                                         }
6044                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));        
6045                                 }
6046                                 continue;
6047                         }
6048                         
6049                         // faster than result <- left, anl result,right
6050                         // and better if result is SFR
6051                         if (AOP_TYPE(left) == AOP_ACC) {
6052                                 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6053                         } else {
6054                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6055                                 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6056                         }
6057                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6058                 }
6059         }
6060
6061 release :
6062         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6063         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6064         freeAsmop(result,NULL,ic,TRUE);     
6065 }
6066
6067 /*-----------------------------------------------------------------*/
6068 /* genXor - code for xclusive or                                   */
6069 /*-----------------------------------------------------------------*/
6070 static void genXor (iCode *ic, iCode *ifx)
6071 {
6072         operand *left, *right, *result;
6073         int size, offset=0;
6074         unsigned long lit = 0L;
6075         
6076         FENTRY;
6077         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6078         
6079         aopOp((left = IC_LEFT(ic)),ic,FALSE);
6080         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6081         aopOp((result=IC_RESULT(ic)),ic,TRUE);
6082         
6083         /* if left is a literal & right is not ||
6084         if left needs acc & right does not */
6085         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6086                 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6087                 operand *tmp = right ;
6088                 right = left;
6089                 left = tmp;
6090         }
6091         
6092         /* if result = right then exchange them */
6093         if(pic14_sameRegs(AOP(result),AOP(right))){
6094                 operand *tmp = right ;
6095                 right = left;
6096                 left = tmp;
6097         }
6098         
6099         /* if right is bit then exchange them */
6100         if (AOP_TYPE(right) == AOP_CRY &&
6101                 AOP_TYPE(left) != AOP_CRY){
6102                 operand *tmp = right ;
6103                 right = left;
6104                 left = tmp;
6105         }
6106         if(AOP_TYPE(right) == AOP_LIT)
6107                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6108         
6109         size = AOP_SIZE(result);
6110         
6111         // if(bit ^ yy)
6112         // xx = bit ^ yy;
6113         if (AOP_TYPE(left) == AOP_CRY){
6114                 if(AOP_TYPE(right) == AOP_LIT){
6115                         // c = bit & literal;
6116                         if(lit>>1){
6117                                 // lit>>1  != 0 => result = 1
6118                                 if(AOP_TYPE(result) == AOP_CRY){
6119                                         if(size)
6120                                         {emitpcode(POC_BSF,  popGet(AOP(result),offset));
6121                                         pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6122                                         else if(ifx)
6123                                                 continueIfTrue(ifx);
6124                                         goto release;
6125                                 }
6126                                 pic14_emitcode("setb","c");
6127                         } else{
6128                                 // lit == (0 or 1)
6129                                 if(lit == 0){
6130                                         // lit == 0, result = left
6131                                         if(size && pic14_sameRegs(AOP(result),AOP(left)))
6132                                                 goto release;
6133                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6134                                 } else{
6135                                         // lit == 1, result = not(left)
6136                                         if(size && pic14_sameRegs(AOP(result),AOP(left))){
6137                                                 emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
6138                                                 emitpcode(POC_XORWF,  popGet(AOP(result),offset));
6139                                                 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6140                                                 goto release;
6141                                         } else {
6142                                                 assert ( !"incomplete genXor" );
6143                                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6144                                                 pic14_emitcode("cpl","c");
6145                                         }
6146                                 }
6147                         }
6148                         
6149                 } else {
6150                         // right != literal
6151                         symbol *tlbl = newiTempLabel(NULL);
6152                         if (AOP_TYPE(right) == AOP_CRY){
6153                                 // c = bit ^ bit;
6154                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6155                         }
6156                         else{
6157                                 int sizer = AOP_SIZE(right);
6158                                 // c = bit ^ val
6159                                 // if val>>1 != 0, result = 1
6160                                 pic14_emitcode("setb","c");
6161                                 while(sizer){
6162                                         MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6163                                         if(sizer == 1)
6164                                                 // test the msb of the lsb
6165                                                 pic14_emitcode("anl","a,#0xfe");
6166                                         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6167                                         sizer--;
6168                                 }
6169                                 // val = (0,1)
6170                                 pic14_emitcode("rrc","a");
6171                         }
6172                         pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6173                         pic14_emitcode("cpl","c");
6174                         pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6175                 }
6176                 // bit = c
6177                 // val = c
6178                 if(size)
6179                         pic14_outBitC(result);
6180                 // if(bit | ...)
6181                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6182                         genIfxJump(ifx, "c");           
6183                 goto release ;
6184         }
6185         
6186         if(pic14_sameRegs(AOP(result),AOP(left))){
6187                 /* if left is same as result */
6188                 for(;size--; offset++) {
6189                         if(AOP_TYPE(right) == AOP_LIT){
6190                                 int t  = (lit >> (offset*8)) & 0x0FFL;
6191                                 if(t == 0x00L)
6192                                         continue;
6193                                 else
6194                                         if (IS_AOP_PREG(left)) {
6195                                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6196                                                 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6197                                                 aopPut(AOP(result),"a",offset);
6198                                         } else {
6199                                                 emitpcode(POC_MOVLW, popGetLit(t));
6200                                                 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6201                                                 pic14_emitcode("xrl","%s,%s",
6202                                                         aopGet(AOP(left),offset,FALSE,TRUE),
6203                                                         aopGet(AOP(right),offset,FALSE,FALSE));
6204                                         }
6205                         } else {
6206                                 if (AOP_TYPE(left) == AOP_ACC)
6207                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6208                                 else {
6209                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6210                                         emitpcode(POC_XORWF,popGet(AOP(left),offset));
6211                                         /*
6212                                         if (IS_AOP_PREG(left)) {
6213                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6214                                         aopPut(AOP(result),"a",offset);
6215                                         } else
6216                                         pic14_emitcode("xrl","%s,a",
6217                                         aopGet(AOP(left),offset,FALSE,TRUE));
6218                                         */
6219                                 }
6220                         }
6221                 }
6222         } else {
6223                 // left & result in different registers
6224                 if(AOP_TYPE(result) == AOP_CRY){
6225                         // result = bit
6226                         // if(size), result in bit
6227                         // if(!size && ifx), conditional oper: if(left ^ right)
6228                         symbol *tlbl = newiTempLabel(NULL);
6229                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6230                         if(size)
6231                                 pic14_emitcode("setb","c");
6232                         while(sizer--){
6233                                 if((AOP_TYPE(right) == AOP_LIT) &&
6234                                         (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6235                                         MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6236                                 } else {
6237                                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6238                                         pic14_emitcode("xrl","a,%s",
6239                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6240                                 }
6241                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6242                                 offset++;
6243                         }
6244                         if(size){
6245                                 CLRC;
6246                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6247                                 pic14_outBitC(result);
6248                         } else if(ifx)
6249                                 jmpTrueOrFalse(ifx, tlbl);
6250                 } else for(;(size--);offset++){
6251                         // normal case
6252                         // result = left & right
6253                         if(AOP_TYPE(right) == AOP_LIT){
6254                                 int t = (lit >> (offset*8)) & 0x0FFL;
6255                                 switch(t) { 
6256                                 case 0x00:
6257                                         if (AOP_TYPE(left) != AOP_ACC) {
6258                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6259                                         }
6260                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6261                                         pic14_emitcode("movf","%s,w",
6262                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6263                                         pic14_emitcode("movwf","%s",
6264                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6265                                         break;
6266                                 case 0xff:
6267                                         if (AOP_TYPE(left) == AOP_ACC) {
6268                                                 emitpcode(POC_XORLW, popGetLit(t));
6269                                         } else {
6270                                                 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6271                                         }
6272                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6273                                         break;
6274                                 default:
6275                                         if (AOP_TYPE(left) == AOP_ACC) {
6276                                                 emitpcode(POC_XORLW, popGetLit(t));
6277                                         } else {
6278                                                 emitpcode(POC_MOVLW, popGetLit(t));
6279                                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6280                                         }
6281                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6282                                         pic14_emitcode("movlw","0x%x",t);
6283                                         pic14_emitcode("xorwf","%s,w",
6284                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6285                                         pic14_emitcode("movwf","%s",
6286                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6287                                         
6288                                 }
6289                                 continue;
6290                         }
6291                         
6292                         // faster than result <- left, anl result,right
6293                         // and better if result is SFR
6294                         if (AOP_TYPE(left) == AOP_ACC) {
6295                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6296                         } else {
6297                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6298                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6299                         }
6300                         if ( AOP_TYPE(result) != AOP_ACC){
6301                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6302                         }
6303                 }
6304         }
6305         
6306 release :
6307         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6308         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6309         freeAsmop(result,NULL,ic,TRUE);     
6310 }
6311
6312 /*-----------------------------------------------------------------*/
6313 /* genInline - write the inline code out                           */
6314 /*-----------------------------------------------------------------*/
6315 static void genInline (iCode *ic)
6316 {
6317   char *buffer, *bp, *bp1;
6318
6319   FENTRY;
6320   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6321
6322   _G.inLine += (!options.asmpeep);
6323
6324   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6325   strcpy(buffer,IC_INLINE(ic));
6326
6327   /* emit each line as a code */
6328   while (*bp) {
6329     if (*bp == '\n') {
6330       *bp++ = '\0';
6331       
6332       if(*bp1)
6333         addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6334       bp1 = bp;
6335     } else {
6336       if (*bp == ':') {
6337         bp++;
6338         *bp = '\0';
6339         bp++;
6340
6341         /* print label, use this special format with NULL directive
6342          * to denote that the argument should not be indented with tab */
6343         addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6344
6345         bp1 = bp;
6346       } else
6347         bp++;
6348     }
6349   }
6350   if ((bp1 != bp) && *bp1)
6351     addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6352
6353   Safe_free(buffer);
6354
6355   _G.inLine -= (!options.asmpeep);
6356 }
6357
6358 /*-----------------------------------------------------------------*/
6359 /* genRRC - rotate right with carry                                */
6360 /*-----------------------------------------------------------------*/
6361 static void genRRC (iCode *ic)
6362 {
6363         operand *left , *result ;
6364         int size, offset = 0, same;
6365         
6366         FENTRY;
6367         /* rotate right with carry */
6368         left = IC_LEFT(ic);
6369         result=IC_RESULT(ic);
6370         aopOp (left,ic,FALSE);
6371         aopOp (result,ic,FALSE);
6372         
6373         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6374         
6375         same = pic14_sameRegs(AOP(result),AOP(left));
6376         
6377         size = AOP_SIZE(result);    
6378         
6379         /* get the lsb and put it into the carry */
6380         emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6381         
6382         offset = 0 ;
6383         
6384         while(size--) {
6385                 
6386                 if(same) {
6387                         emitpcode(POC_RRF, popGet(AOP(left),offset));
6388                 } else {
6389                         emitpcode(POC_RRFW, popGet(AOP(left),offset));
6390                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6391                 }
6392                 
6393                 offset++;
6394         }
6395         
6396         freeAsmop(left,NULL,ic,TRUE);
6397         freeAsmop(result,NULL,ic,TRUE);
6398 }
6399
6400 /*-----------------------------------------------------------------*/
6401 /* genRLC - generate code for rotate left with carry               */
6402 /*-----------------------------------------------------------------*/
6403 static void genRLC (iCode *ic)
6404 {    
6405         operand *left , *result ;
6406         int size, offset = 0;
6407         int same;
6408         
6409         FENTRY;
6410         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6411         /* rotate right with carry */
6412         left = IC_LEFT(ic);
6413         result=IC_RESULT(ic);
6414         aopOp (left,ic,FALSE);
6415         aopOp (result,ic,FALSE);
6416         
6417         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6418         
6419         same = pic14_sameRegs(AOP(result),AOP(left));
6420         
6421         /* move it to the result */
6422         size = AOP_SIZE(result);    
6423         
6424         /* get the msb and put it into the carry */
6425         emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6426         
6427         offset = 0 ;
6428         
6429         while(size--) {
6430                 
6431                 if(same) {
6432                         emitpcode(POC_RLF, popGet(AOP(left),offset));
6433                 } else {
6434                         emitpcode(POC_RLFW, popGet(AOP(left),offset));
6435                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6436                 }
6437                 
6438                 offset++;
6439         }
6440         
6441         
6442         freeAsmop(left,NULL,ic,TRUE);
6443         freeAsmop(result,NULL,ic,TRUE);
6444 }
6445
6446 /*-----------------------------------------------------------------*/
6447 /* genGetHbit - generates code get highest order bit               */
6448 /*-----------------------------------------------------------------*/
6449 static void genGetHbit (iCode *ic)
6450 {
6451         operand *left, *result;
6452         left = IC_LEFT(ic);
6453         result=IC_RESULT(ic);
6454         aopOp (left,ic,FALSE);
6455         aopOp (result,ic,FALSE);
6456         
6457         FENTRY;
6458         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6459         /* get the highest order byte into a */
6460         MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6461         if(AOP_TYPE(result) == AOP_CRY){
6462                 pic14_emitcode("rlc","a");
6463                 pic14_outBitC(result);
6464         }
6465         else{
6466                 pic14_emitcode("rl","a");
6467                 pic14_emitcode("anl","a,#0x01");
6468                 pic14_outAcc(result);
6469         }
6470         
6471         
6472         freeAsmop(left,NULL,ic,TRUE);
6473         freeAsmop(result,NULL,ic,TRUE);
6474 }
6475
6476 /*-----------------------------------------------------------------*/
6477 /* AccLsh - shift left accumulator by known count                  */
6478 /* MARK: pic14 always rotates through CARRY!                       */
6479 /*-----------------------------------------------------------------*/
6480 static void AccLsh (pCodeOp *pcop,int shCount)
6481 {
6482         FENTRY;
6483         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6484         shCount &= 0x0007;              // shCount : 0..7
6485         switch(shCount){
6486         case 0 :
6487                 return;
6488                 break;
6489         case 1 :
6490                 emitCLRC;
6491                 emitpcode(POC_RLF,pcop);
6492                 return;
6493                 break;
6494         case 2 :
6495                 emitpcode(POC_RLF,pcop);
6496                 emitpcode(POC_RLF,pcop);
6497                 break;
6498         case 3 :
6499                 emitpcode(POC_RLF,pcop);
6500                 emitpcode(POC_RLF,pcop);
6501                 emitpcode(POC_RLF,pcop);
6502                 break;
6503         case 4 :
6504                 emitpcode(POC_SWAPF,pcop);
6505                 break;
6506         case 5 :
6507                 emitpcode(POC_SWAPF,pcop);
6508                 emitpcode(POC_RLF,pcop);
6509                 break;
6510         case 6 :
6511                 emitpcode(POC_SWAPF,pcop);
6512                 emitpcode(POC_RLF,pcop);
6513                 emitpcode(POC_RLF,pcop);
6514                 break;
6515         case 7 :
6516                 emitpcode(POC_RRFW,pcop);
6517                 emitpcode(POC_RRF,pcop);
6518                 break;
6519         }
6520         /* clear invalid bits */
6521         emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6522         emitpcode(POC_ANDWF, pcop);
6523 }
6524
6525 /*-----------------------------------------------------------------*/
6526 /* AccRsh - shift right accumulator by known count                 */
6527 /* MARK: pic14 always rotates through CARRY!                       */
6528 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6529 /*            1: mask out invalid bits (zero-extend)               */
6530 /*            2: sign-extend result (pretty slow)                  */
6531 /*-----------------------------------------------------------------*/
6532 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6533 {
6534         FENTRY;
6535         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6536         shCount &= 0x0007;              // shCount : 0..7
6537         switch(shCount){
6538         case 0 :
6539                 return;
6540                 break;
6541         case 1 :
6542                 /* load sign if needed */
6543                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6544                 else if (mask_mode == 1) emitCLRC;
6545                 emitpcode(POC_RRF,pcop);
6546                 return;
6547                 break;
6548         case 2 :
6549                 /* load sign if needed */
6550                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6551                 emitpcode(POC_RRF,pcop);
6552                 /* load sign if needed */
6553                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6554                 emitpcode(POC_RRF,pcop);
6555                 if (mask_mode == 2) return;
6556                 break;
6557         case 3 :
6558                 /* load sign if needed */
6559                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6560                 emitpcode(POC_RRF,pcop);
6561                 /* load sign if needed */
6562                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6563                 emitpcode(POC_RRF,pcop);
6564                 /* load sign if needed */
6565                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6566                 emitpcode(POC_RRF,pcop);
6567                 if (mask_mode == 2) return;
6568                 break;
6569         case 4 :
6570                 emitpcode(POC_SWAPF,pcop);
6571                 break;
6572         case 5 :
6573                 emitpcode(POC_SWAPF,pcop);
6574                 emitpcode(POC_RRF,pcop);
6575                 break;
6576         case 6 :
6577                 emitpcode(POC_SWAPF,pcop);
6578                 emitpcode(POC_RRF,pcop);
6579                 emitpcode(POC_RRF,pcop);
6580                 break;
6581         case 7 :
6582                 if (mask_mode == 2)
6583                 {
6584                         /* load sign */
6585                         emitpcode(POC_RLFW,pcop);
6586                         emitpcode(POC_CLRF,pcop);
6587                         emitSKPNC;
6588                         emitpcode(POC_COMF,pcop);
6589                         return;
6590                 } else {
6591                         emitpcode(POC_RLFW,pcop);
6592                         emitpcode(POC_RLF,pcop);
6593                 }
6594                 break;
6595         }
6596
6597         if (mask_mode == 0)
6598         {
6599                 /* leave invalid bits undefined */
6600                 return;
6601         }
6602         
6603         /* clear invalid bits -- zero-extend */
6604         emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6605         emitpcode(POC_ANDWF, pcop);
6606
6607         if (mask_mode == 2) {
6608           /* sign-extend */
6609           emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6610           emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6611           emitpcode(POC_IORWF, pcop);
6612         }
6613 }
6614
6615 #if 0
6616 /*-----------------------------------------------------------------*/
6617 /* AccSRsh - signed right shift accumulator by known count                 */
6618 /*-----------------------------------------------------------------*/
6619 static void AccSRsh (int shCount)
6620 {
6621         symbol *tlbl ;
6622         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6623         if(shCount != 0){
6624                 if(shCount == 1){
6625                         pic14_emitcode("mov","c,acc.7");
6626                         pic14_emitcode("rrc","a");
6627                 } else if(shCount == 2){
6628                         pic14_emitcode("mov","c,acc.7");
6629                         pic14_emitcode("rrc","a");
6630                         pic14_emitcode("mov","c,acc.7");
6631                         pic14_emitcode("rrc","a");
6632                 } else {
6633                         tlbl = newiTempLabel(NULL);
6634                         /* rotate right accumulator */
6635                         AccRol(8 - shCount);
6636                         /* and kill the higher order bits */
6637                         pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6638                         pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6639                         pic14_emitcode("orl","a,#0x%02x",
6640                                 (unsigned char)~SRMask[shCount]);
6641                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6642                 }
6643         }
6644 }
6645
6646 /*-----------------------------------------------------------------*/
6647 /* shiftR1Left2Result - shift right one byte from left to result   */
6648 /*-----------------------------------------------------------------*/
6649 static void shiftR1Left2ResultSigned (operand *left, int offl,
6650                                                                           operand *result, int offr,
6651                                                                           int shCount)
6652 {
6653         int same;
6654         
6655         FENTRY;
6656         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6657         
6658         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6659         
6660         switch(shCount) {
6661         case 1:
6662                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6663                 if(same) 
6664                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6665                 else {
6666                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6667                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6668                 }
6669                 
6670                 break;
6671         case 2:
6672                 
6673                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6674                 if(same) 
6675                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6676                 else {
6677                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6678                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6679                 }
6680                 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6681                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6682                 
6683                 break;
6684                 
6685         case 3:
6686                 if(same)
6687                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6688                 else {
6689                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6690                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6691                 }
6692                 
6693                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6694                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6695                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6696                 
6697                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6698                 emitpcode(POC_IORLW, popGetLit(0xe0));
6699                 
6700                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6701                 break;
6702                 
6703         case 4:
6704                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6705                 emitpcode(POC_ANDLW,  popGetLit(0x0f));
6706                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6707                 emitpcode(POC_IORLW,  popGetLit(0xf0));
6708                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6709                 break;
6710         case 5:
6711                 if(same) {
6712                         emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6713                 } else {
6714                         emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6715                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6716                 }
6717                 emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6718                 emitpcode(POC_ANDLW,  popGetLit(0x07));
6719                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6720                 emitpcode(POC_IORLW,  popGetLit(0xf8));
6721                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6722                 break;
6723                 
6724         case 6:
6725                 if(same) {
6726                         emitpcode(POC_MOVLW, popGetLit(0x00));
6727                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6728                         emitpcode(POC_MOVLW, popGetLit(0xfe));
6729                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6730                         emitpcode(POC_IORLW, popGetLit(0x01));
6731                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6732                 } else {
6733                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6734                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6735                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6736                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6737                         emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6738                 }
6739                 break;
6740                 
6741         case 7:
6742                 if(same) {
6743                         emitpcode(POC_MOVLW, popGetLit(0x00));
6744                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6745                         emitpcode(POC_MOVLW, popGetLit(0xff));
6746                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6747                 } else {
6748                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6749                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6750                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6751                 }
6752                 
6753         default:
6754                 break;
6755         }
6756 }
6757
6758 /*-----------------------------------------------------------------*/
6759 /* shiftR1Left2Result - shift right one byte from left to result   */
6760 /*-----------------------------------------------------------------*/
6761 static void shiftR1Left2Result (operand *left, int offl,
6762                                                                 operand *result, int offr,
6763                                                                 int shCount, int sign)
6764 {
6765         int same;
6766         
6767         FENTRY;
6768         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6769         
6770         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6771         
6772         /* Copy the msb into the carry if signed. */
6773         if(sign) {
6774                 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6775                 return;
6776         }
6777         
6778         
6779         
6780         switch(shCount) {
6781         case 1:
6782                 emitCLRC;
6783                 if(same) 
6784                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6785                 else {
6786                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6787                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6788                 }
6789                 break;
6790         case 2:
6791                 emitCLRC;
6792                 if(same) {
6793                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6794                 } else {
6795                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6796                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6797                 }
6798                 emitCLRC;
6799                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6800                 
6801                 break;
6802         case 3:
6803                 if(same)
6804                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6805                 else {
6806                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6807                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6808                 }
6809                 
6810                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6811                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6812                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6813                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6814                 break;
6815                 
6816         case 4:
6817                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6818                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6819                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6820                 break;
6821                 
6822         case 5:
6823                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6824                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6825                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6826                 emitCLRC;
6827                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6828                 
6829                 break;
6830         case 6:
6831                 
6832                 emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6833                 emitpcode(POC_ANDLW, popGetLit(0x80));
6834                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6835                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6836                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6837                 break;
6838                 
6839         case 7:
6840                 
6841                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6842                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6843                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6844                 
6845                 break;
6846                 
6847         default:
6848                 break;
6849         }
6850 }
6851
6852 /*-----------------------------------------------------------------*/
6853 /* shiftL1Left2Result - shift left one byte from left to result    */
6854 /*-----------------------------------------------------------------*/
6855 static void shiftL1Left2Result (operand *left, int offl,
6856                                                                 operand *result, int offr, int shCount)
6857 {
6858         int same;
6859         
6860         //    char *l;
6861         FENTRY;
6862         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6863         
6864         same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6865         DEBUGpic14_emitcode ("; ***","same =  %d",same);
6866         //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6867         //    MOVA(l);
6868         /* shift left accumulator */
6869         //AccLsh(shCount); // don't comment out just yet...
6870         //    aopPut(AOP(result),"a",offr);
6871         
6872         switch(shCount) {
6873         case 1:
6874                 /* Shift left 1 bit position */
6875                 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6876                 if(same) {
6877                         emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6878                 } else {
6879                         emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6880                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6881                 }
6882                 break;
6883         case 2:
6884                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6885                 emitpcode(POC_ANDLW,popGetLit(0x7e));
6886                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6887                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6888                 break;
6889         case 3:
6890                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6891                 emitpcode(POC_ANDLW,popGetLit(0x3e));
6892                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6893                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6894                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6895                 break;
6896         case 4:
6897                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6898                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6899                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6900                 break;
6901         case 5:
6902                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6903                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6904                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6905                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6906                 break;
6907         case 6:
6908                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6909                 emitpcode(POC_ANDLW, popGetLit(0x30));
6910                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6911                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6912                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6913                 break;
6914         case 7:
6915                 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6916                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6917                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6918                 break;
6919                 
6920         default:
6921                 DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6922         }
6923         
6924 }
6925 #endif
6926
6927 /*-----------------------------------------------------------------*/
6928 /* movLeft2Result - move byte from left to result                  */
6929 /*-----------------------------------------------------------------*/
6930 static void movLeft2Result (operand *left, int offl,
6931                                                         operand *result, int offr)
6932 {
6933         char *l;
6934         FENTRY;
6935         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6936         if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6937                 l = aopGet(AOP(left),offl,FALSE,FALSE);
6938                 
6939                 if (*l == '@' && (IS_AOP_PREG(result))) {
6940                         pic14_emitcode("mov","a,%s",l);
6941                         aopPut(AOP(result),"a",offr);
6942                 } else {
6943                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6944                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6945                 }
6946         }
6947 }
6948
6949 /*-----------------------------------------------------------------*/
6950 /* shiftLeft_Left2ResultLit - shift left by known count            */
6951 /*-----------------------------------------------------------------*/
6952
6953 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6954 {
6955         int size, same, offr, i;
6956
6957         size = AOP_SIZE(left);
6958         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6959         
6960         same = pic14_sameRegs (AOP(left), AOP(result));
6961         
6962         offr = shCount / 8;
6963         shCount = shCount & 0x07;
6964
6965         size -= offr;
6966
6967         switch (shCount)
6968         {
6969         case 0: /* takes 0 or 2N cycles (for offr==0) */
6970                 if (!same || offr) {
6971                         for (i=size-1; i >= 0; i--)
6972                                 movLeft2Result (left, i, result, offr + i);
6973                 } // if
6974                 break;
6975                 
6976         case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6977                 if (same && offr) {
6978                         shiftLeft_Left2ResultLit (left, result, 8 * offr);
6979                         shiftLeft_Left2ResultLit (result, result, shCount);
6980                         return; /* prevent clearing result again */
6981                 } else {
6982                         emitCLRC;
6983                         for (i=0; i < size; i++) {
6984                                 if (same && !offr) {
6985                                         emitpcode (POC_RLF, popGet (AOP(left), i));
6986                                 } else {
6987                                         emitpcode (POC_RLFW, popGet (AOP(left), i));
6988                                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6989                                 } // if
6990                         } // for
6991                 } // if (offr)
6992                 break;
6993                 
6994         case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6995                 /* works in-place/with offr as well */
6996                 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6997                 emitpcode (POC_ANDLW, popGetLit (0xF0));
6998                 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6999
7000                 for (i = size - 2; i >= 0; i--)
7001                 {
7002                         emitpcode (POC_SWAPFW, popGet (AOP(left), i));
7003                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7004                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7005                         emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
7006                         emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
7007                 } // for i
7008                 break;
7009                 
7010         case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7011                 /* works in-place/with offr as well */
7012                 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7013                 for (i = size-2; i >= 0; i--) {
7014                         emitpcode (POC_RRFW, popGet (AOP(left), i));
7015                         emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7016                 } // for i
7017                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7018                 emitpcode (POC_RRF, popGet (AOP(result), offr));
7019                 break;
7020         
7021         default:
7022                 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7023                 shiftLeft_Left2ResultLit (result, result, 1);
7024                 return; /* prevent clearing result again */
7025                 break;
7026         } // switch
7027
7028         while (0 < offr--)
7029         {
7030                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7031         } // while
7032 }
7033
7034 /*-----------------------------------------------------------------*/
7035 /* shiftRight_Left2ResultLit - shift right by known count          */
7036 /*-----------------------------------------------------------------*/
7037
7038 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7039 {
7040         int size, same, offr, i;
7041
7042         size = AOP_SIZE(left);
7043         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7044         
7045         same = pic14_sameRegs (AOP(left), AOP(result));
7046         
7047         offr = shCount / 8;
7048         shCount = shCount & 0x07;
7049
7050         size -= offr;
7051
7052         if (size)
7053         {
7054                 switch (shCount)
7055                 {
7056                 case 0: /* takes 0 or 2N cycles (for offr==0) */
7057                         if (!same || offr) {
7058                                 for (i=0; i < size; i++)
7059                                         movLeft2Result (left, i + offr, result, i);
7060                         } // if
7061                         break;
7062                         
7063                 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7064                         emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7065                         if (same && offr) {
7066                                 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7067                                 shiftRight_Left2ResultLit (result, result, shCount, sign);
7068                                 return; /* prevent sign-extending result again */
7069                         } else {
7070                                 emitCLRC;
7071                                 if (sign) {
7072                                         emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7073                                         emitSETC;
7074                                 }
7075                                 for (i = size-1; i >= 0; i--) {
7076                                         if (same && !offr) {
7077                                                 emitpcode (POC_RRF, popGet (AOP(left), i));
7078                                         } else {
7079                                                 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7080                                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7081                                         }
7082                                 } // for i
7083                         } // if (offr)
7084                         break;
7085                         
7086                 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7087                         /* works in-place/with offr as well */
7088                         emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7089                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7090                         emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7091
7092                         for (i = 1; i < size; i++)
7093                         {
7094                                 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7095                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7096                                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7097                                 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7098                                 emitpcode (POC_XORWF, popGet (AOP(result), i));
7099                         } // for i
7100
7101                         if (sign)
7102                         {
7103                                 emitpcode (POC_MOVLW, popGetLit (0xF0));
7104                                 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7105                                 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7106                         } // if
7107                         break;
7108                         
7109                 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7110                         /* works in-place/with offr as well */
7111                         emitpcode (POC_RLFW, popGet (AOP(left), offr));
7112                         for (i = 0; i < size-1; i++) {
7113                                 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7114                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7115                         } // for i
7116                         emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7117                         if (!sign) {
7118                                 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7119                         } else {
7120                                 emitSKPNC;
7121                                 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7122                         }
7123                         break;
7124                 
7125                 default:
7126                         shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7127                         shiftRight_Left2ResultLit (result, result, 1, sign);
7128                         return; /* prevent sign extending result again */
7129                         break;
7130                 } // switch
7131         } // if
7132
7133         addSign (result, size, sign);
7134 }
7135
7136 #if 0
7137 /*-----------------------------------------------------------------*/
7138 /* shiftL2Left2Result - shift left two bytes from left to result   */
7139 /*-----------------------------------------------------------------*/
7140 static void shiftL2Left2Result (operand *left, int offl,
7141                                                                 operand *result, int offr, int shCount)
7142 {
7143         FENTRY;
7144         
7145         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7146         
7147         if(pic14_sameRegs(AOP(result), AOP(left))) {
7148                 switch(shCount) {
7149                 case 0:
7150                         break;
7151                 case 1:
7152                 case 2:
7153                 case 3:
7154                         
7155                         emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7156                         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7157                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7158                         
7159                         while(--shCount) {
7160                                 emitCLRC;
7161                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7162                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7163                         }
7164                         
7165                         break;
7166                 case 4:
7167                 case 5:
7168                         emitpcode(POC_MOVLW, popGetLit(0x0f));
7169                         emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7170                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7171                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7172                         emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7173                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7174                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7175                         if(shCount >=5) {
7176                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7177                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7178                         }
7179                         break;
7180                 case 6:
7181                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7182                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7183                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7184                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7185                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7186                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7187                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7188                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7189                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7190                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7191                         break;
7192                 case 7:
7193                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7194                         emitpcode(POC_RRFW, popGet(AOP(result),offr));
7195                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7196                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7197                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7198                 }
7199                 
7200         } else {
7201                 switch(shCount) {
7202                 case 0:
7203                         break;
7204                 case 1:
7205                 case 2:
7206                 case 3:
7207                 /* note, use a mov/add for the shift since the mov has a
7208                         chance of getting optimized out */
7209                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7210                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7211                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7212                         emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
7213                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7214                         
7215                         while(--shCount) {
7216                                 emitCLRC;
7217                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7218                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7219                         }
7220                         break;
7221                         
7222                 case 4:
7223                 case 5:
7224                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7225                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7226                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7227                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7228                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7229                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7230                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7231                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7232                         
7233                         
7234                         if(shCount == 5) {
7235                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7236                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7237                         }
7238                         break;
7239                 case 6:
7240                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7241                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7242                         emitpcode(POC_RRFW, popGet(AOP(result),offl));
7243                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
7244                         
7245                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7246                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7247                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7248                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7249                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7250                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7251                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7252                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7253                         break;
7254                 case 7:
7255                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7256                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7257                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7258                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7259                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7260                 }
7261         }
7262         
7263 }
7264
7265 /*-----------------------------------------------------------------*/
7266 /* shiftR2Left2Result - shift right two bytes from left to result  */
7267 /*-----------------------------------------------------------------*/
7268 static void shiftR2Left2Result (operand *left, int offl,
7269                                                                 operand *result, int offr,
7270                                                                 int shCount, int sign)
7271 {
7272         int same=0;
7273         
7274         FENTRY;
7275         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7276         same = pic14_sameRegs(AOP(result), AOP(left));
7277         
7278         if(same && ((offl + MSB16) == offr)){
7279                 same=1;
7280                 /* don't crash result[offr] */
7281                 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7282                 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7283         }
7284         /* else {
7285         movLeft2Result(left,offl, result, offr);
7286         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7287         }
7288         */
7289         /* a:x >> shCount (x = lsb(result))*/
7290         /*
7291         if(sign)
7292         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7293         else {
7294         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7295         */
7296         switch(shCount) {
7297         case 0:
7298                 break;
7299         case 1:
7300         case 2:
7301         case 3:
7302                 if(sign)
7303                         emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7304                 else
7305                         emitCLRC;
7306                 
7307                 if(same) {
7308                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7309                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7310                 } else {
7311                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7312                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7313                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7314                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7315                 }
7316                 
7317                 while(--shCount) {
7318                         if(sign)
7319                                 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7320                         else
7321                                 emitCLRC;
7322                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7323                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7324                 }
7325                 break;
7326         case 4:
7327         case 5:
7328                 if(same) {
7329                         
7330                         emitpcode(POC_MOVLW, popGetLit(0xf0));
7331                         emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7332                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7333                         
7334                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7335                         emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7336                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7337                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7338                 } else {
7339                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7340                         emitpcode(POC_ANDLW, popGetLit(0x0f));
7341                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7342                         
7343                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7344                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7345                         emitpcode(POC_ANDLW, popGetLit(0xf0));
7346                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7347                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7348                 }
7349                 
7350                 if(shCount >=5) {
7351                         emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7352                         emitpcode(POC_RRF, popGet(AOP(result),offr));
7353                 }
7354                 
7355                 if(sign) {
7356                         emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7357                         emitpcode(POC_BTFSC, 
7358                                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7359                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7360                 }
7361                 
7362                 break;
7363                 
7364         case 6:
7365                 if(same) {
7366                         
7367                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7368                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7369                         
7370                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7371                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7372                         emitpcode(POC_RLFW, popGet(AOP(result),offr));
7373                         emitpcode(POC_ANDLW,popGetLit(0x03));
7374                         if(sign) {
7375                                 emitpcode(POC_BTFSC, 
7376                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7377                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7378                         }
7379                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7380                         emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7381                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7382                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7383                 } else {
7384                         emitpcode(POC_RLFW, popGet(AOP(left),offl));
7385                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7386                         emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7387                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7388                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7389                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7390                         emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7391                         emitpcode(POC_ANDLW,popGetLit(0x03));
7392                         if(sign) {
7393                                 emitpcode(POC_BTFSC, 
7394                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7395                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7396                         }
7397                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7398                         //emitpcode(POC_RLF,  popGet(AOP(result),offr));
7399                         
7400                         
7401                 }
7402                 
7403                 break;
7404         case 7:
7405                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7406                 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7407                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7408                 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7409                 if(sign) {
7410                         emitSKPNC;
7411                         emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7412                 } else 
7413                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7414   }
7415 }
7416
7417 /*-----------------------------------------------------------------*/
7418 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7419 /*-----------------------------------------------------------------*/
7420 static void shiftLLeftOrResult (operand *left, int offl,
7421                                                                 operand *result, int offr, int shCount)
7422 {
7423         FENTRY;
7424         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7425         
7426         /* shift left accumulator */
7427         AccLsh(left,offl,shCount);
7428         /* or with result */
7429         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7430         assert ( !"broken (modifies left, fails for left==result))" );
7431 }
7432
7433 /*-----------------------------------------------------------------*/
7434 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7435 /*-----------------------------------------------------------------*/
7436 static void shiftRLeftOrResult (operand *left, int offl,
7437                                                                 operand *result, int offr, int shCount)
7438 {
7439         FENTRY;
7440         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7441         
7442         /* shift right accumulator */
7443         AccRsh(left,offl,shCount);
7444         /* or with result */
7445         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7446         assert ( !"broken (modifies left, fails for left==result))" );
7447 }
7448
7449 /*-----------------------------------------------------------------*/
7450 /* genlshOne - left shift a one byte quantity by known count       */
7451 /*-----------------------------------------------------------------*/
7452 static void genlshOne (operand *result, operand *left, int shCount)
7453 {       
7454         FENTRY;
7455         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7456         shiftL1Left2Result(left, LSB, result, LSB, shCount);
7457 }
7458
7459 /*-----------------------------------------------------------------*/
7460 /* genlshTwo - left shift two bytes by known amount != 0           */
7461 /*-----------------------------------------------------------------*/
7462 static void genlshTwo (operand *result,operand *left, int shCount)
7463 {
7464         int size;
7465         
7466         FENTRY;
7467         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7468         size = pic14_getDataSize(result);
7469         
7470         /* if shCount >= 8 */
7471         if (shCount >= 8) {
7472                 shCount -= 8 ;
7473                 
7474                 if (size > 1){
7475                         if (shCount)
7476                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7477                         else 
7478                                 movLeft2Result(left, LSB, result, MSB16);
7479                 }
7480                 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7481         }
7482         
7483         /*  1 <= shCount <= 7 */
7484         else {  
7485                 if(size == 1)
7486                         shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7487                 else 
7488                         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7489         }
7490 }
7491
7492 /*-----------------------------------------------------------------*/
7493 /* shiftLLong - shift left one long from left to result            */
7494 /* offl = LSB or MSB16                                             */
7495 /*-----------------------------------------------------------------*/
7496 static void shiftLLong (operand *left, operand *result, int offr )
7497 {
7498         char *l;
7499         int size = AOP_SIZE(result);
7500         
7501         FENTRY;
7502         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7503         if(size >= LSB+offr){
7504                 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7505                 MOVA(l);
7506                 pic14_emitcode("add","a,acc");
7507                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7508                         size >= MSB16+offr && offr != LSB )
7509                         pic14_emitcode("xch","a,%s",
7510                         aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7511                 else      
7512                         aopPut(AOP(result),"a",LSB+offr);
7513         }
7514         
7515         if(size >= MSB16+offr){
7516                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7517                         l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7518                         MOVA(l);
7519                 }
7520                 pic14_emitcode("rlc","a");
7521                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7522                         size >= MSB24+offr && offr != LSB)
7523                         pic14_emitcode("xch","a,%s",
7524                         aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7525                 else      
7526                         aopPut(AOP(result),"a",MSB16+offr);
7527         }
7528         
7529         if(size >= MSB24+offr){
7530                 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7531                         l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7532                         MOVA(l);
7533                 }
7534                 pic14_emitcode("rlc","a");
7535                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7536                         size >= MSB32+offr && offr != LSB )
7537                         pic14_emitcode("xch","a,%s",
7538                         aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7539                 else      
7540                         aopPut(AOP(result),"a",MSB24+offr);
7541         }
7542         
7543         if(size > MSB32+offr){
7544                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7545                         l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7546                         MOVA(l);  
7547                 }
7548                 pic14_emitcode("rlc","a");
7549                 aopPut(AOP(result),"a",MSB32+offr);
7550         }
7551         if(offr != LSB)
7552                 aopPut(AOP(result),zero,LSB);       
7553 }
7554
7555 /*-----------------------------------------------------------------*/
7556 /* genlshFour - shift four byte by a known amount != 0             */
7557 /*-----------------------------------------------------------------*/
7558 static void genlshFour (operand *result, operand *left, int shCount)
7559 {
7560         int size;
7561         
7562         FENTRY;
7563         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7564         size = AOP_SIZE(result);
7565         
7566         /* if shifting more that 3 bytes */
7567         if (shCount >= 24 ) {
7568                 shCount -= 24;
7569                 if (shCount)
7570                 /* lowest order of left goes to the highest
7571                 order of the destination */
7572                 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7573                 else
7574                         movLeft2Result(left, LSB, result, MSB32);
7575                 aopPut(AOP(result),zero,LSB);
7576                 aopPut(AOP(result),zero,MSB16);
7577                 aopPut(AOP(result),zero,MSB32);
7578                 return;
7579         }
7580         
7581         /* more than two bytes */
7582         else if ( shCount >= 16 ) {
7583                 /* lower order two bytes goes to higher order two bytes */
7584                 shCount -= 16;
7585                 /* if some more remaining */
7586                 if (shCount)
7587                         shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7588                 else {
7589                         movLeft2Result(left, MSB16, result, MSB32);
7590                         movLeft2Result(left, LSB, result, MSB24);
7591                 }
7592                 aopPut(AOP(result),zero,MSB16);
7593                 aopPut(AOP(result),zero,LSB);
7594                 return;
7595         }    
7596         
7597         /* if more than 1 byte */
7598         else if ( shCount >= 8 ) {
7599                 /* lower order three bytes goes to higher order  three bytes */
7600                 shCount -= 8;
7601                 if(size == 2){
7602                         if(shCount)
7603                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7604                         else
7605                                 movLeft2Result(left, LSB, result, MSB16);
7606                 }
7607                 else{   /* size = 4 */
7608                         if(shCount == 0){
7609                                 movLeft2Result(left, MSB24, result, MSB32);
7610                                 movLeft2Result(left, MSB16, result, MSB24);
7611                                 movLeft2Result(left, LSB, result, MSB16);
7612                                 aopPut(AOP(result),zero,LSB);
7613                         }
7614                         else if(shCount == 1)
7615                                 shiftLLong(left, result, MSB16);
7616                         else{
7617                                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7618                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7619                                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7620                                 aopPut(AOP(result),zero,LSB);
7621                         }
7622                 }
7623         }
7624         
7625         /* 1 <= shCount <= 7 */
7626         else if(shCount <= 2){
7627                 shiftLLong(left, result, LSB);
7628                 if(shCount == 2)
7629                         shiftLLong(result, result, LSB);
7630         }
7631         /* 3 <= shCount <= 7, optimize */
7632         else{
7633                 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7634                 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7635                 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7636         }
7637 }
7638 #endif
7639
7640 #if 0
7641 /*-----------------------------------------------------------------*/
7642 /* genLeftShiftLiteral - left shifting by known count              */
7643 /*-----------------------------------------------------------------*/
7644 static void genLeftShiftLiteral (operand *left,
7645                                                                  operand *right,
7646                                                                  operand *result,
7647                                                                  iCode *ic)
7648 {    
7649         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7650         //int size;
7651         
7652         FENTRY;
7653         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7654         freeAsmop(right,NULL,ic,TRUE);
7655         
7656         aopOp(left,ic,FALSE);
7657         aopOp(result,ic,FALSE);
7658
7659         size = getSize(operandType(result));
7660         
7661 #if VIEW_SIZE
7662         pic14_emitcode("; shift left ","result %d, left %d",size,
7663                 AOP_SIZE(left));
7664 #endif
7665         
7666         /* I suppose that the left size >= result size */
7667         if(shCount == 0){
7668                 while(size--){
7669                         movLeft2Result(left, size, result, size);
7670                 }
7671         }
7672         
7673         else if(shCount >= (size * 8))
7674                 while(size--)
7675                         aopPut(AOP(result),zero,size);
7676                 else{
7677                         switch (size) {
7678                         case 1:
7679                                 genlshOne (result,left,shCount);
7680                                 break;
7681                                 
7682                         case 2:
7683                         case 3:
7684                                 genlshTwo (result,left,shCount);
7685                                 break;
7686                                 
7687                         case 4:
7688                                 genlshFour (result,left,shCount);
7689                                 break;
7690                         }
7691                 }
7692                 freeAsmop(left,NULL,ic,TRUE);
7693                 freeAsmop(result,NULL,ic,TRUE);
7694 }
7695 #endif
7696
7697 /*-----------------------------------------------------------------*
7698 * genMultiAsm - repeat assembly instruction for size of register.
7699 * if endian == 1, then the high byte (i.e base address + size of 
7700 * register) is used first else the low byte is used first;
7701 *-----------------------------------------------------------------*/
7702 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7703 {
7704         
7705         int offset = 0;
7706         
7707         FENTRY;
7708         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7709         
7710         if(!reg)
7711                 return;
7712         
7713         if(!endian) {
7714                 endian = 1;
7715         } else {
7716                 endian = -1;
7717                 offset = size-1;
7718         }
7719         
7720         while(size--) {
7721                 emitpcode(poc,    popGet(AOP(reg),offset));
7722                 offset += endian;
7723         }
7724         
7725 }
7726
7727 #if 0
7728 /*-----------------------------------------------------------------*/
7729 /* genLeftShift - generates code for left shifting                 */
7730 /*-----------------------------------------------------------------*/
7731 static void genLeftShift (iCode *ic)
7732 {
7733         operand *left,*right, *result;
7734         int size, offset;
7735         unsigned long lit = 0L;
7736         char *l;
7737         symbol *tlbl , *tlbl1;
7738         pCodeOp *pctemp;
7739         
7740         FENTRY;
7741         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7742         
7743         right = IC_RIGHT(ic);
7744         left  = IC_LEFT(ic);
7745         result = IC_RESULT(ic);
7746         
7747         aopOp(right,ic,FALSE);
7748         aopOp(left,ic,FALSE);
7749         aopOp(result,ic,FALSE);
7750         
7751         
7752         /* if the shift count is known then do it 
7753         as efficiently as possible */
7754         if (AOP_TYPE(right) == AOP_LIT) {
7755                 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7756                 return ;
7757         }
7758         
7759         /* shift count is unknown then we have to form 
7760         a loop get the loop count in B : Note: we take
7761         only the lower order byte since shifting
7762         more that 32 bits make no sense anyway, ( the
7763         largest size of an object can be only 32 bits ) */  
7764         
7765         /* this code fails for RIGHT == RESULT */
7766         assert (!pic14_sameRegs (AOP(right), AOP(result)));
7767         
7768         /* now move the left to the result if they are not the
7769         same */
7770         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7771                 AOP_SIZE(result) > 1) {
7772                 
7773                 size = AOP_SIZE(result);
7774                 offset=0;
7775                 while (size--) {
7776                         l = aopGet(AOP(left),offset,FALSE,TRUE);
7777                         if (*l == '@' && (IS_AOP_PREG(result))) {
7778                                 
7779                                 pic14_emitcode("mov","a,%s",l);
7780                                 aopPut(AOP(result),"a",offset);
7781                         } else {
7782                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7783                                 emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7784                                 //aopPut(AOP(result),l,offset);
7785                         }
7786                         offset++;
7787                 }
7788         }
7789         
7790         if(AOP_TYPE(left) == AOP_LIT)
7791                 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7792
7793         size = AOP_SIZE(result);
7794         
7795         /* if it is only one byte then */
7796         if (size == 1) {
7797                 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7798                         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7799                         emitpcode(POC_ANDLW,  popGetLit(0xf0));
7800                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7801                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7802                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7803                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7804                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7805                         emitpcode(POC_RLFW,   popGet(AOP(result),0));
7806                         emitpcode(POC_ANDLW,  popGetLit(0xfe));
7807                         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7808                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7809                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7810                 } else {
7811                         
7812                         tlbl = newiTempLabel(NULL);
7813                         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7814                                 mov2w (AOP(left), 0);
7815                                 emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7816                         }
7817                         
7818                         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7819                         emitpcode(POC_RRF,    popGet(AOP(result),0));
7820                         emitpLabel(tlbl->key);
7821                         emitpcode(POC_RLF,    popGet(AOP(result),0));
7822                         emitpcode(POC_ADDLW,  popGetLit(1));
7823                         emitSKPC;
7824                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7825                 }
7826                 goto release ;
7827         }
7828         
7829         if (pic14_sameRegs(AOP(left),AOP(result))) {
7830                 
7831                 tlbl = newiTempLabel(NULL);
7832                 emitpcode(POC_COMFW,  popGet(AOP(right),0));
7833                 genMultiAsm(POC_RRF, result, size,1);
7834                 emitpLabel(tlbl->key);
7835                 genMultiAsm(POC_RLF, result, size,0);
7836                 emitpcode(POC_ADDLW,  popGetLit(1));
7837                 emitSKPC;
7838                 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7839                 goto release;
7840         }
7841         
7842         //tlbl = newiTempLabel(NULL);
7843         //offset = 0 ;   
7844         //tlbl1 = newiTempLabel(NULL);
7845         
7846         //reAdjustPreg(AOP(result));    
7847         
7848         //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7849         //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7850         //l = aopGet(AOP(result),offset,FALSE,FALSE);
7851         //MOVA(l);
7852         //pic14_emitcode("add","a,acc");         
7853         //aopPut(AOP(result),"a",offset++);
7854         //while (--size) {
7855         //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7856         //  MOVA(l);
7857         //  pic14_emitcode("rlc","a");         
7858         //  aopPut(AOP(result),"a",offset++);
7859         //}
7860         //reAdjustPreg(AOP(result));
7861         
7862         //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7863         //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7864         
7865         
7866         tlbl = newiTempLabel(NULL);
7867         tlbl1= newiTempLabel(NULL);
7868         
7869         size = AOP_SIZE(result);
7870         offset = 1;
7871         
7872         pctemp = popGetTempReg();  /* grab a temporary working register. */
7873         
7874         emitpcode(POC_MOVFW, popGet(AOP(right),0));
7875         
7876         /* offset should be 0, 1 or 3 */
7877         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7878         emitSKPNZ;
7879         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7880         
7881         emitpcode(POC_MOVWF, pctemp);
7882         
7883         
7884         emitpLabel(tlbl->key);
7885         
7886         emitCLRC;
7887         emitpcode(POC_RLF,  popGet(AOP(result),0));
7888         while(--size)
7889                 emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7890         
7891         emitpcode(POC_DECFSZ,  pctemp);
7892         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7893         emitpLabel(tlbl1->key);
7894         
7895         popReleaseTempReg(pctemp);
7896         
7897         
7898 release:
7899         freeAsmop (right,NULL,ic,TRUE);
7900         freeAsmop(left,NULL,ic,TRUE);
7901         freeAsmop(result,NULL,ic,TRUE);
7902 }
7903 #endif
7904
7905 #if 0
7906 /*-----------------------------------------------------------------*/
7907 /* genrshOne - right shift a one byte quantity by known count      */
7908 /*-----------------------------------------------------------------*/
7909 static void genrshOne (operand *result, operand *left,
7910                                            int shCount, int sign)
7911 {
7912         FENTRY;
7913         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7914         shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7915 }
7916
7917 /*-----------------------------------------------------------------*/
7918 /* genrshTwo - right shift two bytes by known amount != 0          */
7919 /*-----------------------------------------------------------------*/
7920 static void genrshTwo (operand *result,operand *left,
7921                                            int shCount, int sign)
7922 {
7923         FENTRY;
7924         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7925         /* if shCount >= 8 */
7926         if (shCount >= 8) {
7927                 shCount -= 8 ;
7928                 if (shCount)
7929                         shiftR1Left2Result(left, MSB16, result, LSB,
7930                         shCount, sign);
7931                 else
7932                         movLeft2Result(left, MSB16, result, LSB);
7933                 
7934                 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7935                 
7936                 if(sign) {
7937                         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7938                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7939                 }
7940         }
7941         
7942         /*  1 <= shCount <= 7 */
7943         else
7944                 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7945 }
7946
7947 /*-----------------------------------------------------------------*/
7948 /* shiftRLong - shift right one long from left to result           */
7949 /* offl = LSB or MSB16                                             */
7950 /*-----------------------------------------------------------------*/
7951 static void shiftRLong (operand *left, int offl,
7952                                                 operand *result, int sign)
7953 {
7954         int size, same;
7955         
7956         FENTRY;
7957         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7958         
7959         size = AOP_SIZE(left);
7960         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7961         
7962         if (sign)
7963                 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7964         else
7965                 emitCLRC;
7966
7967         assert (offl >= 0 && offl < size);
7968
7969         same = pic14_sameRegs (AOP(left), AOP(result));
7970
7971         /* perform the shift */
7972         while (size--)
7973         {
7974                 if (same && !offl) {
7975                         emitpcode (POC_RRF, popGet (AOP(result), size));
7976                 } else {
7977                         emitpcode (POC_RRFW, popGet (AOP(left), size));
7978                         emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7979                 }
7980         } // while
7981
7982         addSign (result, AOP_SIZE(left) - offl, sign);
7983 }
7984
7985 /*-----------------------------------------------------------------*/
7986 /* genrshFour - shift four byte by a known amount != 0             */
7987 /*-----------------------------------------------------------------*/
7988 static void genrshFour (operand *result, operand *left,
7989                                                 int shCount, int sign)
7990 {
7991         FENTRY;
7992         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7993         /* if shifting more that 3 bytes */
7994         if(shCount >= 24 ) {
7995                 shCount -= 24;
7996                 if(shCount)
7997                         shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7998                 else
7999                         movLeft2Result(left, MSB32, result, LSB);
8000                 
8001                 addSign(result, MSB16, sign);
8002         }
8003         else if(shCount >= 16){
8004                 shCount -= 16;
8005                 if(shCount)
8006                         shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8007                 else{
8008                         movLeft2Result(left, MSB24, result, LSB);
8009                         movLeft2Result(left, MSB32, result, MSB16);
8010                 }
8011                 addSign(result, MSB24, sign);
8012         }
8013         else if(shCount >= 8){
8014                 shCount -= 8;
8015                 if(shCount == 1)
8016                         shiftRLong(left, MSB16, result, sign);
8017                 else if(shCount == 0){
8018                         movLeft2Result(left, MSB16, result, LSB);
8019                         movLeft2Result(left, MSB24, result, MSB16);
8020                         movLeft2Result(left, MSB32, result, MSB24);
8021                         addSign(result, MSB32, sign);
8022                 }
8023                 else{
8024                         shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8025                         shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8026                         /* the last shift is signed */
8027                         shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8028                         addSign(result, MSB32, sign);
8029                 }
8030         }
8031         else{   /* 1 <= shCount <= 7 */
8032                 if(shCount <= 2){
8033                         shiftRLong(left, LSB, result, sign);
8034                         if(shCount == 2)
8035                                 shiftRLong(result, LSB, result, sign);
8036                 }
8037                 else{
8038                         shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8039                         shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8040                         shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8041                 }
8042         }
8043 }
8044
8045 /*-----------------------------------------------------------------*/
8046 /* genRightShiftLiteral - right shifting by known count            */
8047 /*-----------------------------------------------------------------*/
8048 static void genRightShiftLiteral (operand *left,
8049                                                                   operand *right,
8050                                                                   operand *result,
8051                                                                   iCode *ic,
8052                                                                   int sign)
8053 {    
8054         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8055         int lsize,res_size;
8056         
8057         FENTRY;
8058         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8059         freeAsmop(right,NULL,ic,TRUE);
8060         
8061         aopOp(left,ic,FALSE);
8062         aopOp(result,ic,FALSE);
8063         
8064 #if VIEW_SIZE
8065         pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8066                 AOP_SIZE(left));
8067 #endif
8068         
8069         lsize = pic14_getDataSize(left);
8070         res_size = pic14_getDataSize(result);
8071         /* test the LEFT size !!! */
8072         
8073         /* I suppose that the left size >= result size */
8074         if(shCount == 0){
8075                 while(res_size--)
8076                         movLeft2Result(left, res_size, result, res_size);
8077         }
8078         
8079         else if(shCount >= (lsize * 8)){
8080                 
8081                 if(res_size == 1) {
8082                         emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8083                         if(sign) {
8084                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8085                                 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8086                         }
8087                 } else {
8088                         
8089                         if(sign) {
8090                                 emitpcode(POC_MOVLW, popGetLit(0));
8091                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8092                                 emitpcode(POC_MOVLW, popGetLit(0xff));
8093                                 while(res_size--)
8094                                         emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8095                                 
8096                         } else {
8097                                 
8098                                 while(res_size--)
8099                                         emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8100                         }
8101                 }
8102         } else {
8103                 
8104                 switch (res_size) {
8105                 case 1:
8106                         genrshOne (result,left,shCount,sign);
8107                         break;
8108                         
8109                 case 2:
8110                         genrshTwo (result,left,shCount,sign);
8111                         break;
8112                         
8113                 case 4:
8114                         genrshFour (result,left,shCount,sign);
8115                         break;
8116                 default :
8117                         break;
8118                 }
8119                 
8120         }
8121
8122         freeAsmop(left,NULL,ic,TRUE);
8123         freeAsmop(result,NULL,ic,TRUE);
8124 }
8125 #endif
8126
8127 #if 0
8128 /*-----------------------------------------------------------------*/
8129 /* genSignedRightShift - right shift of signed number              */
8130 /*-----------------------------------------------------------------*/
8131 static void genSignedRightShift (iCode *ic)
8132 {
8133         operand *right, *left, *result;
8134         int size, offset;
8135         //  char *l;
8136         symbol *tlbl, *tlbl1 ;
8137         pCodeOp *pctemp;
8138         
8139         //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8140         
8141         /* we do it the hard way put the shift count in b
8142         and loop thru preserving the sign */
8143         FENTRY;
8144         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8145         
8146         right = IC_RIGHT(ic);
8147         left  = IC_LEFT(ic);
8148         result = IC_RESULT(ic);
8149         
8150         aopOp(right,ic,FALSE);  
8151         aopOp(left,ic,FALSE);
8152         aopOp(result,ic,FALSE);
8153         
8154         
8155         if ( AOP_TYPE(right) == AOP_LIT) {
8156                 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8157                 //genRightShiftLiteral (left,right,result,ic,1);
8158                 return ;
8159         }
8160         /* shift count is unknown then we have to form 
8161         a loop get the loop count in B : Note: we take
8162         only the lower order byte since shifting
8163         more that 32 bits make no sense anyway, ( the
8164         largest size of an object can be only 32 bits ) */  
8165         
8166         //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8167         //pic14_emitcode("inc","b");
8168         //freeAsmop (right,NULL,ic,TRUE);
8169         //aopOp(left,ic,FALSE);
8170         //aopOp(result,ic,FALSE);
8171         
8172         /* now move the left to the result if they are not the
8173         same */
8174         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
8175                 AOP_SIZE(result) > 1) {
8176                 
8177                 size = AOP_SIZE(result);
8178                 offset=0;
8179                 while (size--) { 
8180                         /*
8181                         l = aopGet(AOP(left),offset,FALSE,TRUE);
8182                         if (*l == '@' && IS_AOP_PREG(result)) {
8183                                 pic14_emitcode("mov","a,%s",l);
8184                                 aopPut(AOP(result),"a",offset);
8185                         } else
8186                         aopPut(AOP(result),l,offset);
8187                         */
8188                         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
8189                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
8190                         
8191                         offset++;
8192                 }
8193         }
8194         
8195         /* mov the highest order bit to OVR */    
8196         tlbl = newiTempLabel(NULL);
8197         tlbl1= newiTempLabel(NULL);
8198         
8199         size = AOP_SIZE(result);
8200         offset = size - 1;
8201         
8202         pctemp = popGetTempReg();  /* grab a temporary working register. */
8203         
8204         emitpcode(POC_MOVFW, popGet(AOP(right),0));
8205         
8206         /* offset should be 0, 1 or 3 */
8207         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8208         emitSKPNZ;
8209         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
8210         
8211         emitpcode(POC_MOVWF, pctemp);
8212         
8213         
8214         emitpLabel(tlbl->key);
8215         
8216         emitpcode(POC_RLFW,  popGet(AOP(result),offset));
8217         emitpcode(POC_RRF,   popGet(AOP(result),offset));
8218         
8219         while(--size) {
8220                 emitpcode(POC_RRF,   popGet(AOP(result),--offset));
8221         }
8222         
8223         emitpcode(POC_DECFSZ,  pctemp);
8224         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8225         emitpLabel(tlbl1->key);
8226         
8227         popReleaseTempReg(pctemp);
8228 #if 0
8229         size = AOP_SIZE(result);
8230         offset = size - 1;
8231         pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8232         pic14_emitcode("rlc","a");
8233         pic14_emitcode("mov","ov,c");
8234         /* if it is only one byte then */
8235         if (size == 1) {
8236                 l = aopGet(AOP(left),0,FALSE,FALSE);
8237                 MOVA(l);
8238                 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8239                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8240                 pic14_emitcode("mov","c,ov");
8241                 pic14_emitcode("rrc","a");
8242                 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8243                 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8244                 aopPut(AOP(result),"a",0);
8245                 goto release ;
8246         }
8247         
8248         reAdjustPreg(AOP(result));
8249         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8250         pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
8251         pic14_emitcode("mov","c,ov");
8252         while (size--) {
8253                 l = aopGet(AOP(result),offset,FALSE,FALSE);
8254                 MOVA(l);
8255                 pic14_emitcode("rrc","a");         
8256                 aopPut(AOP(result),"a",offset--);
8257         }
8258         reAdjustPreg(AOP(result));
8259         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8260         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8261         
8262 release:
8263 #endif
8264         
8265         freeAsmop(left,NULL,ic,TRUE);
8266         freeAsmop(result,NULL,ic,TRUE);
8267         freeAsmop(right,NULL,ic,TRUE);
8268 }
8269 #endif
8270
8271 /*-----------------------------------------------------------------*/
8272 /* loadSignToC - load the operand's sign bit into CARRY            */
8273 /*-----------------------------------------------------------------*/
8274
8275 static void loadSignToC (operand *op)
8276 {
8277         FENTRY;
8278         assert (op && AOP(op) && AOP_SIZE(op));
8279
8280         emitCLRC;
8281         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8282         emitSETC;
8283 }
8284
8285 /*-----------------------------------------------------------------*/
8286 /* genRightShift - generate code for right shifting                */
8287 /*-----------------------------------------------------------------*/
8288 static void genGenericShift (iCode *ic, int shiftRight)
8289 {
8290         operand *right, *left, *result;
8291         sym_link *retype ;
8292         int size;
8293         symbol *tlbl, *tlbl1, *inverselbl;
8294         
8295         FENTRY;
8296         /* if signed then we do it the hard way preserve the
8297         sign bit moving it inwards */
8298         retype = getSpec(operandType(IC_RESULT(ic)));
8299         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8300         
8301         /* signed & unsigned types are treated the same : i.e. the
8302         signed is NOT propagated inwards : quoting from the
8303         ANSI - standard : "for E1 >> E2, is equivalent to division
8304         by 2**E2 if unsigned or if it has a non-negative value,
8305         otherwise the result is implementation defined ", MY definition
8306         is that the sign does not get propagated */
8307         
8308         right = IC_RIGHT(ic);
8309         left  = IC_LEFT(ic);
8310         result = IC_RESULT(ic);
8311         
8312         aopOp(right,ic,FALSE);
8313         aopOp(left,ic,FALSE);
8314         aopOp(result,ic,FALSE);
8315         
8316         /* if the shift count is known then do it 
8317         as efficiently as possible */
8318         if (AOP_TYPE(right) == AOP_LIT) {
8319                 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8320                 if (lit < 0)
8321                 {
8322                         lit = -lit;
8323                         shiftRight = !shiftRight;
8324                 }
8325                 
8326                 if (shiftRight)
8327                         shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8328                 else
8329                         shiftLeft_Left2ResultLit (left, result, lit);
8330                 //genRightShiftLiteral (left,right,result,ic, 0);
8331                 return ;
8332         }
8333         
8334         /* shift count is unknown then we have to form 
8335         a loop get the loop count in B : Note: we take
8336         only the lower order byte since shifting
8337         more that 32 bits make no sense anyway, ( the
8338         largest size of an object can be only 32 bits ) */  
8339
8340         /* we must not overwrite the shift counter */
8341         assert (!pic14_sameRegs(AOP(right),AOP(result)));
8342         
8343         /* now move the left to the result if they are not the
8344         same */
8345         if (!pic14_sameRegs(AOP(left),AOP(result)))
8346         {
8347                 size = min(AOP_SIZE(result), AOP_SIZE(left));
8348                 while (size--) {
8349                         mov2w(AOP(left), size);
8350                         movwf(AOP(result), size);
8351                 }
8352                 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8353         }
8354         
8355         tlbl = newiTempLabel(NULL);
8356         tlbl1= newiTempLabel(NULL);
8357         inverselbl = NULL;
8358         size = AOP_SIZE(result);
8359
8360         mov2w(AOP(right),0);
8361         if (!SPEC_USIGN(operandType(right)))
8362         {
8363                 inverselbl = newiTempLabel(NULL);
8364                 /* signed shift count -- invert shift direction for c<0 */
8365                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8366                 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8367         } // if
8368         emitpcode(POC_SUBLW, popGetLit(0));     /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8369         /* check for `a = b >> c' with `-c == 0' */
8370         emitSKPNZ;
8371         emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8372         emitpLabel(tlbl->key);
8373         /* propagate the sign bit inwards for SIGNED result */
8374         if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8375         genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8376         emitpcode(POC_ADDLW,  popGetLit(1));    /* clears CARRY (unless W==0 afterwards) */
8377         emitSKPC;
8378         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8379
8380         if (!SPEC_USIGN(operandType(right)))
8381         {
8382                 symbol *inv_loop = newiTempLabel(NULL);
8383
8384                 shiftRight = !shiftRight;       /* invert shift direction */
8385                 
8386                 /* we came here from the code above -- we are done */
8387                 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8388                 
8389                 /* emit code for shifting N<0 steps, count is already in W */
8390                 emitpLabel(inverselbl->key);
8391                 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8392                 emitpLabel(inv_loop->key);
8393                 /* propagate the sign bit inwards for SIGNED result */
8394                 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8395                 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8396                 emitpcode(POC_ADDLW, popGetLit(1));
8397                 emitSKPC;
8398                 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8399         } // if
8400         
8401         emitpLabel(tlbl1->key);
8402         
8403         freeAsmop(left,NULL,ic,TRUE);
8404         freeAsmop (right,NULL,ic,TRUE);
8405         freeAsmop(result,NULL,ic,TRUE);
8406 }
8407
8408 static void genRightShift (iCode *ic)
8409 {
8410         genGenericShift(ic, 1);
8411 }
8412
8413 static void genLeftShift (iCode *ic)
8414 {
8415         genGenericShift(ic, 0);
8416 }
8417
8418 /*-----------------------------------------------------------------*/
8419 /* SetIrp - Set IRP bit                                            */
8420 /*-----------------------------------------------------------------*/
8421 void SetIrp(operand *result) {
8422         FENTRY;
8423         if (AOP_TYPE(result) == AOP_LIT) {
8424                 unsigned lit = (unsigned)operandLitValue(result);
8425                 if (lit&0x100)
8426                         emitSETIRP;
8427                 else
8428                         emitCLRIRP;
8429         } else {
8430                 if (PCOP(AOP(result))->type == PO_LITERAL) {
8431                         int addrs = PCOL(AOP(result))->lit;
8432                         if (addrs & 0x100)
8433                                 emitSETIRP;
8434                         else
8435                                 emitCLRIRP;
8436                 } else {
8437                         emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8438                         if(AOP_SIZE(result) > 1) {
8439                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8440                                 emitSETIRP;
8441                         }
8442                 }
8443         }
8444 }
8445
8446 static void
8447 setup_fsr (operand *ptr)
8448 {
8449   mov2w_op(ptr, 0);
8450   emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8451
8452   /* also setup-up IRP */
8453   SetIrp (ptr);
8454 }
8455
8456 /*-----------------------------------------------------------------*/
8457 /* emitPtrByteGet - emits code to get a byte into WREG from an     */
8458 /*                  arbitrary pointer (__code, __data, generic)    */
8459 /*-----------------------------------------------------------------*/
8460 static void
8461 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8462 {
8463     FENTRY;
8464     switch (p_type)
8465     {
8466     case POINTER:
8467     case FPOINTER:
8468       if (!alreadyAddressed) setup_fsr (src);
8469       emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8470       break;
8471     
8472     case CPOINTER:
8473       assert( AOP_SIZE(src) == 2 );
8474       mov2w_op(src, 0);
8475       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8476       mov2w_op(src, 1);
8477       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8478       emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE));   /* GPOINTER tag for __code space */
8479       call_libraryfunc ("__gptrget1");
8480       break;
8481     
8482     case GPOINTER:
8483       assert( AOP_SIZE(src) == 3 );
8484       mov2w_op(src, 0);
8485       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8486       mov2w_op(src, 1);
8487       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8488       mov2w_op(src, 2);
8489       call_libraryfunc ("__gptrget1");
8490       break;
8491     
8492     default:
8493       assert( !"unhandled pointer type" );
8494       break;
8495     }
8496 }
8497
8498 /*-----------------------------------------------------------------*/
8499 /* emitPtrByteSet - emits code to set a byte from src through a    */
8500 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR).       */
8501 /*-----------------------------------------------------------------*/
8502 static void
8503 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8504 {
8505     FENTRY;
8506     switch (p_type)
8507     {
8508     case POINTER:
8509     case FPOINTER:
8510       if (!alreadyAddressed) setup_fsr (dst);
8511       emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8512       break;
8513     
8514     case CPOINTER:
8515       assert( !"trying to assign to __code pointer" );
8516       break;
8517     
8518     case GPOINTER:
8519       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8520       mov2w_op(dst, 0);
8521       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8522       mov2w_op(dst, 1);
8523       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8524       mov2w_op(dst, 2);
8525       call_libraryfunc ("__gptrput1");
8526       break;
8527
8528     default:
8529       assert( !"unhandled pointer type" );
8530       break;
8531     }
8532 }
8533
8534 /*-----------------------------------------------------------------*/
8535 /* genUnpackBits - generates code for unpacking bits               */
8536 /*-----------------------------------------------------------------*/
8537 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8538 {    
8539   int rsize;            /* result size */
8540   sym_link *etype;      /* bitfield type information */
8541   int blen;             /* bitfield length */
8542   int bstr;             /* bitfield starting bit within byte */
8543
8544   FENTRY;
8545   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8546   etype = getSpec(operandType(result));
8547   rsize = getSize (operandType (result));
8548   blen = SPEC_BLEN (etype);
8549   bstr = SPEC_BSTR (etype);
8550
8551   /* single bit field case */
8552   if (blen == 1) {
8553     if (ifx) { /* that is for an if statement */
8554       pCodeOp *pcop;
8555       resolvedIfx rIfx;
8556       resolveIfx(&rIfx,ifx);
8557       if (ptype == -1) /* direct */
8558         pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8559       else
8560         pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8561       emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8562       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8563       ifx->generated=1;
8564     } else {
8565       int i;
8566       assert (!pic14_sameRegs (AOP(result), AOP(left)));
8567       for (i=0; i < AOP_SIZE(result); i++)
8568         emitpcode (POC_CLRF, popGet (AOP(result), i));
8569
8570       switch (ptype)
8571       {
8572       case -1:
8573         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8574         /* adjust result below */
8575         break;
8576         
8577       case POINTER:
8578       case FPOINTER:
8579       case GPOINTER:
8580       case CPOINTER:
8581         emitPtrByteGet (left, ptype, FALSE);
8582         emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8583         emitSKPZ;
8584         /* adjust result below */
8585         break;
8586         
8587       default:
8588         assert( !"unhandled pointer type" );
8589       } // switch
8590
8591       /* move sign-/zero extended bit to result */
8592       if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8593         emitpcode (POC_INCF, popGet (AOP(result), 0));
8594       } else {
8595         emitpcode (POC_DECF, popGet (AOP(result), 0));
8596       }
8597       addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8598     }
8599     return;
8600   }
8601   else if (blen <= 8 && ((blen + bstr) <= 8))
8602   {
8603     /* blen > 1 */
8604     int i;
8605
8606     for (i=0; i < AOP_SIZE(result); i++)
8607       emitpcode (POC_CLRF, popGet (AOP(result), i));
8608
8609     switch (ptype)
8610     {
8611     case -1:
8612       mov2w(AOP(left), 0);
8613       break;
8614       
8615     case POINTER:
8616     case FPOINTER:
8617     case GPOINTER:
8618     case CPOINTER:
8619       emitPtrByteGet (left, ptype, FALSE);
8620       break;
8621       
8622     default:
8623       assert( !"unhandled pointer type" );
8624     } // switch
8625
8626     if (blen < 8)
8627       emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8628     movwf(AOP(result), 0);
8629     AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8630
8631     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8632     {
8633       /* signed bitfield */
8634       assert (bstr + blen > 0);
8635       emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8636       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8637       emitpcode(POC_IORWF, popGet(AOP(result),0));
8638     }
8639     addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8640     return;
8641   }
8642
8643   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8644 }
8645
8646 #if 1
8647 /*-----------------------------------------------------------------*/
8648 /* genDataPointerGet - generates code when ptr offset is known     */
8649 /*-----------------------------------------------------------------*/
8650 static void genDataPointerGet (operand *left, 
8651         operand *result, 
8652         iCode *ic)
8653 {
8654         int size , offset = 0;
8655                 
8656         FENTRY;
8657         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8658         
8659         
8660         /* optimization - most of the time, left and result are the same
8661         * address, but different types. for the pic code, we could omit
8662         * the following
8663         */
8664         aopOp(result,ic,TRUE);
8665         
8666         if (pic14_sameRegs (AOP(left), AOP(result)))
8667                 return;
8668         
8669         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8670         
8671         //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8672         
8673         size = AOP_SIZE(result);
8674         if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8675         
8676         offset = 0;
8677         while (size--) {
8678                 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8679                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8680                 offset++;
8681         }
8682         
8683         freeAsmop(left,NULL,ic,TRUE);
8684         freeAsmop(result,NULL,ic,TRUE);
8685 }
8686 #endif
8687
8688 /*-----------------------------------------------------------------*/
8689 /* genNearPointerGet - pic14_emitcode for near pointer fetch       */
8690 /*-----------------------------------------------------------------*/
8691 static void genNearPointerGet (operand *left, 
8692                                                            operand *result, 
8693                                                            iCode *ic)
8694 {
8695         asmop *aop = NULL;
8696         sym_link *ltype = operandType(left);
8697         sym_link *rtype = operandType(result);
8698         sym_link *retype= getSpec(rtype);      /* bitfield type information */
8699         int direct = 0;
8700
8701         FENTRY;
8702         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8703         
8704         
8705         aopOp(left,ic,FALSE);
8706         
8707         /* if left is rematerialisable and
8708         result is not bit variable type and
8709         the left is pointer to data space i.e
8710         lower 128 bytes of space */
8711         if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8712                 !IS_BITVAR(retype)         &&
8713                 PIC_IS_DATA_PTR(ltype)) {
8714                 genDataPointerGet (left,result,ic);
8715                 return ;
8716         }
8717         
8718         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8719         aopOp (result,ic,FALSE);
8720         
8721         /* Check if can access directly instead of via a pointer */
8722         if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8723                 && AOP_SIZE(result) == 1)
8724         {
8725                 direct = 1;
8726         }
8727
8728         if (IS_BITFIELD(getSpec(operandType(result)))) 
8729         {
8730                 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8731                 goto release;
8732         }
8733         
8734         /* If the pointer value is not in a the FSR then need to put it in */
8735         /* Must set/reset IRP bit for use with FSR. */
8736         if (!direct)
8737           setup_fsr (left);
8738         
8739 //      sym_link *etype;
8740         /* if bitfield then unpack the bits */
8741         {
8742                 /* we have can just get the values */
8743                 int size = AOP_SIZE(result);
8744                 int offset = 0 ;  
8745                 
8746                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8747                 
8748                 while(size--) {
8749                         if (direct)
8750                                 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8751                         else
8752                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8753                         if (AOP_TYPE(result) == AOP_LIT) {
8754                                 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8755                         } else {
8756                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8757                         }
8758                         if (size && !direct)
8759                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8760                         offset++;
8761                 }
8762         }
8763         
8764         /* now some housekeeping stuff */
8765         if (aop) {
8766                 /* we had to allocate for this iCode */
8767                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8768                 freeAsmop(NULL,aop,ic,TRUE);
8769         } else { 
8770                 /* we did not allocate which means left
8771                 already in a pointer register, then
8772                 if size > 0 && this could be used again
8773                 we have to point it back to where it 
8774                 belongs */
8775                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8776                 if (AOP_SIZE(result) > 1 &&
8777                         !OP_SYMBOL(left)->remat &&
8778                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8779                         ic->depth )) {
8780                         int size = AOP_SIZE(result) - 1;
8781                         while (size--)
8782                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8783                 }
8784         }
8785         
8786 release:
8787         /* done */
8788         freeAsmop(left,NULL,ic,TRUE);
8789         freeAsmop(result,NULL,ic,TRUE);
8790
8791 }
8792
8793 #if 0
8794 /*-----------------------------------------------------------------*/
8795 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8796 /*-----------------------------------------------------------------*/
8797 static void genPagedPointerGet (operand *left, 
8798                                                                 operand *result, 
8799                                                                 iCode *ic)
8800 {
8801         asmop *aop = NULL;
8802         regs *preg = NULL ;
8803         char *rname ;
8804         sym_link *rtype, *retype;    
8805         
8806         FENTRY;
8807         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8808         
8809         rtype = operandType(result);
8810         retype= getSpec(rtype);
8811         
8812         aopOp(left,ic,FALSE);
8813         
8814         /* if the value is already in a pointer register
8815         then don't need anything more */
8816         if (!AOP_INPREG(AOP(left))) {
8817                 /* otherwise get a free pointer register */
8818                 aop = newAsmop(0);
8819                 preg = getFreePtr(ic,&aop,FALSE);
8820                 pic14_emitcode("mov","%s,%s",
8821                         preg->name,
8822                         aopGet(AOP(left),0,FALSE,TRUE));
8823                 rname = preg->name ;
8824         } else
8825                 rname = aopGet(AOP(left),0,FALSE,FALSE);
8826         
8827         freeAsmop(left,NULL,ic,TRUE);
8828         aopOp (result,ic,FALSE);
8829         
8830         /* if bitfield then unpack the bits */
8831         if (IS_BITFIELD(retype)) 
8832                 genUnpackBits (result,left,rname,PPOINTER,0);
8833         else {
8834                 /* we have can just get the values */
8835                 int size = AOP_SIZE(result);
8836                 int offset = 0 ;  
8837                 
8838                 while (size--) {
8839                         
8840                         pic14_emitcode("movx","a,@%s",rname);
8841                         aopPut(AOP(result),"a",offset);
8842                         
8843                         offset++ ;
8844                         
8845                         if (size)
8846                                 pic14_emitcode("inc","%s",rname);
8847                 }
8848         }
8849         
8850         /* now some housekeeping stuff */
8851         if (aop) {
8852                 /* we had to allocate for this iCode */
8853                 freeAsmop(NULL,aop,ic,TRUE);
8854         } else { 
8855         /* we did not allocate which means left
8856         already in a pointer register, then
8857         if size > 0 && this could be used again
8858         we have to point it back to where it 
8859                 belongs */
8860                 if (AOP_SIZE(result) > 1 &&
8861                         !OP_SYMBOL(left)->remat &&
8862                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8863                         ic->depth )) {
8864                         int size = AOP_SIZE(result) - 1;
8865                         while (size--)
8866                                 pic14_emitcode("dec","%s",rname);
8867                 }
8868         }
8869         
8870         /* done */
8871         freeAsmop(result,NULL,ic,TRUE);
8872         
8873         
8874 }
8875
8876 /*-----------------------------------------------------------------*/
8877 /* genFarPointerGet - gget value from far space                    */
8878 /*-----------------------------------------------------------------*/
8879 static void genFarPointerGet (operand *left,
8880                                                           operand *result, iCode *ic)
8881 {
8882         int size, offset ;
8883         sym_link *retype = getSpec(operandType(result));
8884         
8885         FENTRY;
8886         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8887         
8888         aopOp(left,ic,FALSE);
8889         
8890         /* if the operand is already in dptr 
8891         then we do nothing else we move the value to dptr */
8892         if (AOP_TYPE(left) != AOP_STR) {
8893                 /* if this is remateriazable */
8894                 if (AOP_TYPE(left) == AOP_IMMD)
8895                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8896                 else { /* we need to get it byte by byte */
8897                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8898                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8899                         if (options.model == MODEL_FLAT24)
8900                         {
8901                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8902                         }
8903                 }
8904         }
8905         /* so dptr know contains the address */
8906         freeAsmop(left,NULL,ic,TRUE);
8907         aopOp(result,ic,FALSE);
8908         
8909         /* if bit then unpack */
8910         if (IS_BITFIELD(retype)) 
8911                 genUnpackBits(result,left,"dptr",FPOINTER,0);
8912         else {
8913                 size = AOP_SIZE(result);
8914                 offset = 0 ;
8915                 
8916                 while (size--) {
8917                         pic14_emitcode("movx","a,@dptr");
8918                         aopPut(AOP(result),"a",offset++);
8919                         if (size)
8920                                 pic14_emitcode("inc","dptr");
8921                 }
8922         }
8923         
8924         freeAsmop(result,NULL,ic,TRUE);
8925 }
8926 #endif
8927
8928 #if 0
8929 /*-----------------------------------------------------------------*/
8930 /* genCodePointerGet - get value from code space                  */
8931 /*-----------------------------------------------------------------*/
8932 static void genCodePointerGet (operand *left,
8933                                                            operand *result, iCode *ic)
8934 {
8935         int size, offset ;
8936         sym_link *retype = getSpec(operandType(result));
8937         
8938         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8939         
8940         aopOp(left,ic,FALSE);
8941         
8942         /* if the operand is already in dptr 
8943         then we do nothing else we move the value to dptr */
8944         if (AOP_TYPE(left) != AOP_STR) {
8945                 /* if this is remateriazable */
8946                 if (AOP_TYPE(left) == AOP_IMMD)
8947                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8948                 else { /* we need to get it byte by byte */
8949                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8950                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8951                         if (options.model == MODEL_FLAT24)
8952                         {
8953                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8954                         }
8955                 }
8956         }
8957         /* so dptr know contains the address */
8958         freeAsmop(left,NULL,ic,TRUE);
8959         aopOp(result,ic,FALSE);
8960         
8961         /* if bit then unpack */
8962         if (IS_BITFIELD(retype)) 
8963                 genUnpackBits(result,left,"dptr",CPOINTER,0);
8964         else {
8965                 size = AOP_SIZE(result);
8966                 offset = 0 ;
8967                 
8968                 while (size--) {
8969                         pic14_emitcode("clr","a");
8970                         pic14_emitcode("movc","a,@a+dptr");
8971                         aopPut(AOP(result),"a",offset++);
8972                         if (size)
8973                                 pic14_emitcode("inc","dptr");
8974                 }
8975         }
8976         
8977         freeAsmop(result,NULL,ic,TRUE);
8978 }
8979 #endif
8980 /*-----------------------------------------------------------------*/
8981 /* genGenPointerGet - gget value from generic pointer space        */
8982 /*-----------------------------------------------------------------*/
8983 static void genGenPointerGet (operand *left,
8984                                                           operand *result, iCode *ic)
8985 {
8986         FENTRY;
8987         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8988         aopOp(left,ic,FALSE);
8989         aopOp(result,ic,FALSE);
8990         
8991         
8992         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8993
8994         if (IS_BITFIELD(getSpec(operandType(result))))
8995         {
8996           genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
8997           return;
8998         }
8999
9000         {
9001           /* emit call to __gptrget */
9002           char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
9003           int size = AOP_SIZE(result);
9004           int idx = 0;
9005
9006           assert (size > 0 && size <= 4);
9007
9008           /* pass arguments */
9009           assert (AOP_SIZE(left) == 3);
9010           mov2w(AOP(left), 0);
9011           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9012           mov2w(AOP(left), 1);
9013           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9014           mov2w(AOP(left), 2);
9015           call_libraryfunc (func[size]);
9016           
9017           /* save result */
9018           movwf (AOP(result), --size);
9019           while (size--) {
9020             emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
9021             movwf (AOP(result), size);
9022           } // while
9023         }
9024         
9025         freeAsmop(left,NULL,ic,TRUE);
9026         freeAsmop(result,NULL,ic,TRUE);
9027         
9028 }
9029
9030 /*-----------------------------------------------------------------*/
9031 /* genConstPointerGet - get value from const generic pointer space */
9032 /*-----------------------------------------------------------------*/
9033 static void genConstPointerGet (operand *left,
9034                                                                 operand *result, iCode *ic)
9035 {
9036         //sym_link *retype = getSpec(operandType(result));
9037         #if 0
9038         symbol *albl, *blbl;//, *clbl;
9039         pCodeOp *pcop;
9040         #endif
9041         PIC_OPCODE poc;
9042         int i, size, lit;
9043         
9044         FENTRY;
9045         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9046         aopOp(left,ic,FALSE);
9047         aopOp(result,ic,FALSE);
9048         
9049         size = AOP_SIZE(result);
9050         
9051         DEBUGpic14_AopType(__LINE__,left,NULL,result);
9052         
9053         DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9054
9055         lit = op_isLitLike (left);
9056         poc = lit ? POC_MOVLW : POC_MOVFW;
9057
9058         if (IS_BITFIELD(getSpec(operandType(result))))
9059         {
9060                 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9061                 goto release;
9062         }
9063
9064         {
9065                 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9066                 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9067                 assert (size > 0 && size <= 4);
9068                 
9069                 mov2w_op(left, 0);
9070                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9071                 mov2w_op(left, 1);
9072                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9073                 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9074                 call_libraryfunc (func[size]);
9075
9076                 movwf(AOP(result),size-1);
9077                 for (i = 1; i < size; i++)
9078                 {
9079                         emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9080                         movwf(AOP(result),size - 1 - i);
9081                 } // for
9082         }
9083         
9084 release:
9085         freeAsmop(left,NULL,ic,TRUE);
9086         freeAsmop(result,NULL,ic,TRUE);
9087         
9088 }
9089 /*-----------------------------------------------------------------*/
9090 /* genPointerGet - generate code for pointer get                   */
9091 /*-----------------------------------------------------------------*/
9092 static void genPointerGet (iCode *ic)
9093 {
9094         operand *left, *result ;
9095         sym_link *type, *etype;
9096         int p_type = -1;
9097         
9098         FENTRY;
9099         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9100         
9101         left = IC_LEFT(ic);
9102         result = IC_RESULT(ic) ;
9103         
9104         /* depending on the type of pointer we need to
9105         move it to the correct pointer register */
9106         type = operandType(left);
9107         etype = getSpec(type);
9108         
9109         if (IS_PTR_CONST(type))
9110                 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9111         
9112         /* if left is of type of pointer then it is simple */
9113         if (IS_PTR(type) && !IS_FUNC(type->next)) 
9114                 p_type = DCL_TYPE(type);
9115         else {
9116                 /* we have to go by the storage class */
9117                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9118                 
9119                 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9120                 
9121                 if (SPEC_OCLS(etype)->codesp ) {
9122                         DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9123                         //p_type = CPOINTER ; 
9124                 }
9125                 else
9126                         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9127                                 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9128                         /*p_type = FPOINTER ;*/ 
9129                         else
9130                                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9131                                         DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9132                                 /*        p_type = PPOINTER; */
9133                                 else
9134                                         if (SPEC_OCLS(etype) == idata )
9135                                                 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9136                                         /*      p_type = IPOINTER; */
9137                                         else
9138                                                 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9139                                         /*      p_type = POINTER ; */
9140         }
9141         
9142         /* now that we have the pointer type we assign
9143         the pointer values */
9144         switch (p_type) {
9145                 
9146         case POINTER: 
9147         case FPOINTER:
9148         //case IPOINTER:
9149                 genNearPointerGet (left,result,ic);
9150                 break;
9151 /*
9152         case PPOINTER:
9153                 genPagedPointerGet(left,result,ic);
9154                 break;
9155                 
9156         case FPOINTER:
9157                 genFarPointerGet (left,result,ic);
9158                 break;
9159 */              
9160         case CPOINTER:
9161                 genConstPointerGet (left,result,ic);
9162                 break;
9163                 
9164         case GPOINTER:
9165                 genGenPointerGet (left,result,ic);
9166                 break;
9167         default:
9168                 assert ( !"unhandled pointer type" );
9169                 break;
9170         }
9171         
9172 }
9173
9174 /*-----------------------------------------------------------------*/
9175 /* genPackBits - generates code for packed bit storage             */
9176 /*-----------------------------------------------------------------*/
9177 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9178 {
9179   int blen;             /* bitfield length */
9180   int bstr;             /* bitfield starting bit within byte */
9181   int litval;           /* source literal value (if AOP_LIT) */
9182   unsigned char mask;   /* bitmask within current byte */
9183
9184   FENTRY;
9185   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9186
9187   blen = SPEC_BLEN (etype);
9188   bstr = SPEC_BSTR (etype);
9189
9190   /* If the bitfield length is less than a byte and does not cross byte boundaries */
9191   if ((blen <= 8) && ((bstr + blen) <= 8))
9192   {
9193     mask = ((unsigned char) (0xFF << (blen + bstr)) |
9194             (unsigned char) (0xFF >> (8 - bstr)));
9195
9196     if (AOP_TYPE (right) == AOP_LIT)
9197     {
9198       /* Case with a bitfield length <8 and literal source */
9199       int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9200       if (blen == 1) {
9201         pCodeOp *pcop;
9202         
9203         switch (p_type)
9204         {
9205         case -1:
9206           if (AOP(result)->type == AOP_PCODE)
9207             pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9208           else
9209             pcop = popGet(AOP(result),0);
9210           emitpcode(lit?POC_BSF:POC_BCF,pcop);
9211           break;
9212         
9213         case POINTER:
9214         case FPOINTER:
9215           setup_fsr (result);
9216           emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9217           break;
9218         
9219         case CPOINTER:
9220           assert( !"trying to assign to bitfield via pointer to __code space" );
9221           break;
9222         
9223         case GPOINTER:
9224           emitPtrByteGet(result, p_type, FALSE);
9225           if (lit) {
9226             emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9227           } else {
9228             emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9229           }
9230           emitPtrByteSet(result, p_type, TRUE);
9231           break;
9232         
9233         default:
9234           assert( !"unhandled pointer type" );
9235           break;
9236         } // switch (p_type)
9237       } else {
9238         /* blen > 1 */
9239         litval = lit << bstr;
9240         litval &= (~mask) & 0x00ff;
9241         
9242         switch (p_type)
9243         {
9244         case -1:
9245           mov2w (AOP(result), 0);
9246           if ((litval|mask) != 0x00ff)
9247             emitpcode(POC_ANDLW, popGetLit (mask));
9248           if (litval != 0x00)
9249             emitpcode(POC_IORLW, popGetLit (litval));
9250           movwf (AOP(result), 0);
9251           break;
9252         
9253         case POINTER:
9254         case FPOINTER:
9255         case GPOINTER:
9256           emitPtrByteGet(result, p_type, FALSE);
9257           if ((litval|mask) != 0x00ff)
9258             emitpcode(POC_ANDLW, popGetLit (mask));
9259           if (litval != 0x00)
9260             emitpcode(POC_IORLW, popGetLit (litval));
9261           emitPtrByteSet(result, p_type, TRUE);
9262           break;
9263         
9264         case CPOINTER:
9265           assert( !"trying to assign to bitfield via pointer to __code space" );
9266           break;
9267         
9268         default:
9269           assert( !"unhandled pointer type" );
9270           break;
9271         } // switch
9272       } // if (blen > 1)
9273     }
9274     else
9275     {
9276       /* right is no literal */
9277       if (blen==1) {
9278         switch (p_type)
9279         {
9280         case -1:
9281           /* Note more efficient code, of pre clearing bit then only setting it if required,
9282            * can only be done if it is known that the result is not a SFR */
9283           emitpcode(POC_RRFW,popGet(AOP(right),0));
9284           emitSKPC;
9285           emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9286           emitSKPNC;
9287           emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9288           break;
9289         
9290         case POINTER:
9291         case FPOINTER:
9292         case GPOINTER:
9293           emitPtrByteGet (result, p_type, FALSE);
9294           emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9295           emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9296           emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9297           emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9298           emitPtrByteSet (result, p_type, TRUE);
9299           break;
9300         
9301         case CPOINTER:
9302           assert( !"trying to assign to bitfield via pointer to __code space" );
9303           break;
9304         
9305         default:
9306           assert( !"unhandled pointer type" );
9307           break;
9308         } // switch
9309         return;
9310       } else {
9311         /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9312         pCodeOp *temp = popGetTempReg ();
9313
9314         mov2w (AOP(right), 0);
9315         if (blen < 8) {
9316           emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9317         }
9318         emitpcode(POC_MOVWF, temp);
9319         if (bstr) {
9320           AccLsh (temp, bstr);
9321         }
9322         
9323         switch (p_type)
9324         {
9325         case -1:
9326           mov2w (AOP(result), 0);
9327           emitpcode(POC_ANDLW, popGetLit (mask));
9328           emitpcode(POC_IORFW, temp);
9329           movwf (AOP(result), 0);
9330           break;
9331         
9332         case POINTER:
9333         case FPOINTER:
9334         case GPOINTER:
9335           emitPtrByteGet (result, p_type, FALSE);
9336           emitpcode(POC_ANDLW, popGetLit (mask));
9337           emitpcode(POC_IORFW, temp);
9338           emitPtrByteSet (result, p_type, TRUE);
9339           break;
9340         
9341         case CPOINTER:
9342           assert( !"trying to assign to bitfield via pointer to __code space" );
9343           break;
9344         
9345         default:
9346           assert( !"unhandled pointer type" );
9347           break;
9348         } // switch
9349
9350         popReleaseTempReg (temp);
9351       } // if (blen > 1)
9352     } // if (AOP(right)->type != AOP_LIT)
9353     return;
9354   } // if (blen <= 8 && ((blen + bstr) <= 8))
9355
9356   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9357 }
9358
9359 unsigned long
9360 bitpatternFromVal (value *val)
9361 {
9362   union {
9363     float d;
9364     unsigned long l;
9365   } float_long;
9366
9367   assert (sizeof (float) == sizeof (long));
9368
9369   //fprintf (stderr, "%s:%u(%s): val=%lf, type: %d, etype: %d\n", __FILE__, __LINE__, __FUNCTION__, floatFromVal(val), SPEC_NOUN(val->type), SPEC_NOUN(val->etype));
9370
9371   switch (SPEC_NOUN(val->type))
9372   {
9373   case V_INT:
9374   case V_CHAR:
9375     return (unsigned long)floatFromVal (val);
9376     
9377   case V_FLOAT:
9378   case V_DOUBLE:
9379     float_long.d = floatFromVal (val);
9380     return float_long.l;
9381     
9382   default:
9383     assert( !"unhandled value type" );
9384     break;
9385   }
9386
9387   float_long.d = floatFromVal (val);
9388   return float_long.l;
9389 }
9390
9391 /*-----------------------------------------------------------------*/
9392 /* genDataPointerSet - remat pointer to data space                 */
9393 /*-----------------------------------------------------------------*/
9394 static void genDataPointerSet(operand *right,
9395         operand *result,
9396         iCode *ic)
9397 {
9398         int size, offset = 0 ;
9399         int ressize;
9400         
9401         FENTRY;
9402         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9403         aopOp(right,ic,FALSE);
9404         aopOp(result,ic,FALSE);
9405         
9406         assert (IS_SYMOP(result));
9407         assert (IS_PTR(OP_SYM_TYPE(result)));
9408         
9409         size = AOP_SIZE(right);
9410         ressize = getSize(OP_SYM_ETYPE(result));
9411         if (size > ressize) size = ressize;
9412         //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9413         
9414         //assert( !"what's going on here?" );
9415
9416         /*
9417         if ( AOP_TYPE(result) == AOP_PCODE) {
9418         fprintf(stderr,"genDataPointerSet   %s, %d\n",
9419         AOP(result)->aopu.pcop->name,
9420         PCOI(AOP(result)->aopu.pcop)->offset);
9421         }
9422         */
9423         
9424         // tsd, was l+1 - the underline `_' prefix was being stripped
9425         while (size--) {
9426                 emitpComment ("%s:%u: size=%d/%d, offset=%i", __FILE__,__LINE__, size, ressize, offset);
9427                 
9428                 if (AOP_TYPE(right) == AOP_LIT) {
9429                         /* XXX: might be float... */
9430                         unsigned int lit = bitpatternFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9431                         lit = lit >> (8*offset);
9432                         //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9433                         if(lit&0xff) {
9434                                 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9435                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9436                         } else {
9437                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9438                         }
9439                 } else {
9440                         //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9441                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9442                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9443                 }
9444                 
9445                 offset++;
9446         }
9447         
9448         freeAsmop(right,NULL,ic,TRUE);
9449         freeAsmop(result,NULL,ic,TRUE);
9450 }
9451
9452 /*-----------------------------------------------------------------*/
9453 /* genNearPointerSet - pic14_emitcode for near pointer put         */
9454 /*-----------------------------------------------------------------*/
9455 static void genNearPointerSet (operand *right,
9456                                                            operand *result, 
9457                                                            iCode *ic)
9458 {
9459         asmop *aop = NULL;
9460         sym_link *ptype = operandType(result);
9461         sym_link *retype = getSpec(operandType(right));
9462         sym_link *letype = getSpec(ptype);
9463         int direct = 0;
9464         
9465         
9466         FENTRY;
9467         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9468         aopOp(result,ic,FALSE);
9469         
9470 #if 1
9471         /* if the result is rematerializable &
9472         in data space & not a bit variable */
9473         //if (AOP_TYPE(result) == AOP_IMMD &&
9474         if (AOP_TYPE(result) == AOP_PCODE &&
9475                 PIC_IS_DATA_PTR(ptype) &&
9476                 !IS_BITVAR (retype) &&
9477                 !IS_BITVAR (letype)) {
9478                 genDataPointerSet (right,result,ic);
9479                 freeAsmop(result,NULL,ic,TRUE);
9480                 return;
9481         }
9482 #endif
9483
9484         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9485         aopOp(right,ic,FALSE);
9486         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9487         
9488         /* Check if can access directly instead of via a pointer */
9489         if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9490                 direct = 1;
9491         }
9492         
9493         if (IS_BITFIELD (letype))
9494         {
9495           genPackBits (letype, result, right, direct?-1:POINTER);
9496           return;
9497         }
9498         
9499         /* If the pointer value is not in a the FSR then need to put it in */
9500         /* Must set/reset IRP bit for use with FSR. */
9501         /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9502         if (!direct)
9503                 setup_fsr (result);
9504
9505         {
9506                 /* we have can just get the values */
9507                 int size = AOP_SIZE(right);
9508                 int offset = 0 ;    
9509                 
9510                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9511                 while (size--) {
9512                         char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9513                         if (*l == '@' ) {
9514                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9515                         } else {
9516                                 if (AOP_TYPE(right) == AOP_LIT) {
9517                                         emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9518                                 } else {
9519                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9520                                 }
9521                                 if (direct)
9522                                         emitpcode(POC_MOVWF,popGet(AOP(result),0));
9523                                 else
9524                                         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9525                         }
9526                         if (size && !direct)
9527                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9528                         offset++;
9529                 }
9530         }
9531         
9532         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9533         /* now some housekeeping stuff */
9534         if (aop) {
9535                 /* we had to allocate for this iCode */
9536                 freeAsmop(NULL,aop,ic,TRUE);
9537         } else { 
9538                 /* we did not allocate which means left
9539                 already in a pointer register, then
9540                 if size > 0 && this could be used again
9541                 we have to point it back to where it 
9542                 belongs */
9543                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9544                 if (AOP_SIZE(right) > 1 &&
9545                         !OP_SYMBOL(result)->remat &&
9546                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9547                         ic->depth )) {
9548                         int size = AOP_SIZE(right) - 1;
9549                         while (size--)
9550                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9551                 }
9552         }
9553         
9554         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9555         /* done */
9556
9557         freeAsmop(right,NULL,ic,TRUE);
9558         freeAsmop(result,NULL,ic,TRUE);
9559 }
9560
9561 #if 0
9562 /*-----------------------------------------------------------------*/
9563 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
9564 /*-----------------------------------------------------------------*/
9565 static void genPagedPointerSet (operand *right,
9566                                                                 operand *result, 
9567                                                                 iCode *ic)
9568 {
9569         asmop *aop = NULL;
9570         regs *preg = NULL ;
9571         char *rname , *l;
9572         sym_link *retype;
9573         
9574         FENTRY;
9575         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9576         
9577         retype= getSpec(operandType(right));
9578         
9579         aopOp(result,ic,FALSE);
9580         
9581         /* if the value is already in a pointer register
9582         then don't need anything more */
9583         if (!AOP_INPREG(AOP(result))) {
9584                 /* otherwise get a free pointer register */
9585                 aop = newAsmop(0);
9586                 preg = getFreePtr(ic,&aop,FALSE);
9587                 pic14_emitcode("mov","%s,%s",
9588                         preg->name,
9589                         aopGet(AOP(result),0,FALSE,TRUE));
9590                 rname = preg->name ;
9591         } else
9592                 rname = aopGet(AOP(result),0,FALSE,FALSE);
9593         
9594         freeAsmop(result,NULL,ic,TRUE);
9595         aopOp (right,ic,FALSE);
9596         
9597         /* if bitfield then unpack the bits */
9598         if (IS_BITFIELD(retype)) 
9599                 genPackBits (retype,result,right,rname,PPOINTER);
9600         else {
9601                 /* we have can just get the values */
9602                 int size = AOP_SIZE(right);
9603                 int offset = 0 ;  
9604                 
9605                 while (size--) {
9606                         l = aopGet(AOP(right),offset,FALSE,TRUE);
9607                         
9608                         MOVA(l);
9609                         pic14_emitcode("movx","@%s,a",rname);
9610                         
9611                         if (size)
9612                                 pic14_emitcode("inc","%s",rname);
9613                         
9614                         offset++;
9615                 }
9616         }
9617         
9618         /* now some housekeeping stuff */
9619         if (aop) {
9620                 /* we had to allocate for this iCode */
9621                 freeAsmop(NULL,aop,ic,TRUE);
9622         } else { 
9623         /* we did not allocate which means left
9624         already in a pointer register, then
9625         if size > 0 && this could be used again
9626         we have to point it back to where it 
9627                 belongs */
9628                 if (AOP_SIZE(right) > 1 &&
9629                         !OP_SYMBOL(result)->remat &&
9630                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9631                         ic->depth )) {
9632                         int size = AOP_SIZE(right) - 1;
9633                         while (size--)
9634                                 pic14_emitcode("dec","%s",rname);
9635                 }
9636         }
9637         
9638         /* done */
9639         freeAsmop(right,NULL,ic,TRUE);
9640         
9641         
9642 }
9643
9644 /*-----------------------------------------------------------------*/
9645 /* genFarPointerSet - set value from far space                     */
9646 /*-----------------------------------------------------------------*/
9647 static void genFarPointerSet (operand *right,
9648                                                           operand *result, iCode *ic)
9649 {
9650         int size, offset ;
9651         sym_link *retype = getSpec(operandType(right));
9652         
9653         FENTRY;
9654         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9655         aopOp(result,ic,FALSE);
9656         
9657         /* if the operand is already in dptr 
9658         then we do nothing else we move the value to dptr */
9659         if (AOP_TYPE(result) != AOP_STR) {
9660                 /* if this is remateriazable */
9661                 if (AOP_TYPE(result) == AOP_IMMD)
9662                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9663                 else { /* we need to get it byte by byte */
9664                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9665                         pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9666                         if (options.model == MODEL_FLAT24)
9667                         {
9668                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9669                         }
9670                 }
9671         }
9672         /* so dptr know contains the address */
9673         freeAsmop(result,NULL,ic,TRUE);
9674         aopOp(right,ic,FALSE);
9675         
9676         /* if bit then unpack */
9677         if (IS_BITFIELD(retype)) 
9678                 genPackBits(retype,result,right,"dptr",FPOINTER);
9679         else {
9680                 size = AOP_SIZE(right);
9681                 offset = 0 ;
9682                 
9683                 while (size--) {
9684                         char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9685                         MOVA(l);
9686                         pic14_emitcode("movx","@dptr,a");
9687                         if (size)
9688                                 pic14_emitcode("inc","dptr");
9689                 }
9690         }
9691         
9692         freeAsmop(right,NULL,ic,TRUE);
9693 }
9694 #endif
9695
9696 /*-----------------------------------------------------------------*/
9697 /* genGenPointerSet - set value from generic pointer space         */
9698 /*-----------------------------------------------------------------*/
9699 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9700 {
9701         sym_link *retype = getSpec(operandType(result));
9702         
9703         FENTRY;
9704         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9705         aopOp(right,ic,FALSE);
9706         aopOp(result,ic,FALSE);
9707
9708         
9709         DEBUGpic14_AopType(__LINE__,right,NULL,result);
9710
9711         if (IS_BITFIELD(retype))
9712         {
9713           genPackBits (retype, result, right, GPOINTER);
9714           return;
9715         }
9716
9717         {
9718           /* emit call to __gptrput */
9719           char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9720           int size = AOP_SIZE(right);
9721           int idx = 0;
9722
9723           assert (size == getSize(OP_SYM_ETYPE(result)));
9724           assert (size > 0 && size <= 4);
9725
9726           /* pass arguments */
9727           /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9728           {
9729             int off = size;
9730             idx = 2;
9731             while (off--)
9732             {
9733               mov2w_op (right, off);
9734               emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9735             }
9736             idx = 0;
9737           }
9738           /* - address */
9739           assert (AOP_SIZE(result) == 3);
9740           mov2w(AOP(result), 0);
9741           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9742           mov2w(AOP(result), 1);
9743           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9744           mov2w(AOP(result), 2);
9745           call_libraryfunc (func[size]);
9746         }
9747         
9748         freeAsmop(right,NULL,ic,TRUE);
9749         freeAsmop(result,NULL,ic,TRUE);
9750 }
9751
9752 /*-----------------------------------------------------------------*/
9753 /* genPointerSet - stores the value into a pointer location        */
9754 /*-----------------------------------------------------------------*/
9755 static void genPointerSet (iCode *ic)
9756 {    
9757         operand *right, *result ;
9758         sym_link *type, *etype;
9759         int p_type;
9760         
9761         FENTRY;
9762         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9763         
9764         right = IC_RIGHT(ic);
9765         result = IC_RESULT(ic) ;
9766         
9767         /* depending on the type of pointer we need to
9768         move it to the correct pointer register */
9769         type = operandType(result);
9770         etype = getSpec(type);
9771         /* if left is of type of pointer then it is simple */
9772         if (IS_PTR(type) && !IS_FUNC(type->next)) {
9773                 p_type = DCL_TYPE(type);
9774         }
9775         else {
9776                 /* we have to go by the storage class */
9777                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9778                 
9779                 /*  if (SPEC_OCLS(etype)->codesp ) { */
9780                 /*      p_type = CPOINTER ;  */
9781                 /*  } */
9782                 /*  else */
9783                 /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9784                 /*    p_type = FPOINTER ; */
9785                 /*      else */
9786                 /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9787                 /*        p_type = PPOINTER ; */
9788                 /*    else */
9789                 /*        if (SPEC_OCLS(etype) == idata ) */
9790                 /*      p_type = IPOINTER ; */
9791                 /*        else */
9792                 /*      p_type = POINTER ; */
9793         }
9794         
9795         /* now that we have the pointer type we assign
9796         the pointer values */
9797         switch (p_type) {
9798                 
9799         case POINTER:
9800         case FPOINTER:
9801         //case IPOINTER:
9802                 genNearPointerSet (right,result,ic);
9803                 break;
9804 /*
9805         case PPOINTER:
9806                 genPagedPointerSet (right,result,ic);
9807                 break;
9808                 
9809         case FPOINTER:
9810                 genFarPointerSet (right,result,ic);
9811                 break;
9812 */
9813         case GPOINTER:
9814                 genGenPointerSet (right,result,ic);
9815                 break;
9816                 
9817         default:
9818                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9819                         "genPointerSet: illegal pointer type");
9820         }
9821 }
9822
9823 /*-----------------------------------------------------------------*/
9824 /* genIfx - generate code for Ifx statement                        */
9825 /*-----------------------------------------------------------------*/
9826 static void genIfx (iCode *ic, iCode *popIc)
9827 {
9828         operand *cond = IC_COND(ic);
9829         int isbit =0;
9830         
9831         FENTRY;
9832         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9833         
9834         aopOp(cond,ic,FALSE);
9835         
9836         /* get the value into acc */
9837         if (AOP_TYPE(cond) != AOP_CRY)
9838                 pic14_toBoolean(cond);
9839         else
9840                 isbit = 1;
9841         
9842         /* if there was something to be popped then do it */
9843         if (popIc)
9844                 genIpop(popIc);
9845         
9846         if (isbit)
9847         {
9848                 /* This assumes that CARRY is set iff cond is true */
9849                 if (IC_TRUE(ic))
9850                 {
9851                         assert (!IC_FALSE(ic));
9852                         emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9853                         //emitSKPNC;
9854                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9855                 } else {
9856                         assert (IC_FALSE(ic));
9857                         emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9858                         //emitSKPC;
9859                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9860                 }
9861                 if (0)
9862                 {
9863                         static int hasWarned = 0;
9864                         if (!hasWarned)
9865                         {
9866                                 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9867                                 hasWarned = 1;
9868                         }
9869                 }
9870         }
9871         else
9872         {
9873                 /* now Z is set iff !cond */
9874                 if (IC_TRUE(ic))
9875                 {
9876                         assert (!IC_FALSE(ic));
9877                         emitSKPZ;
9878                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9879                 } else {
9880                         emitSKPNZ;
9881                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9882                 }
9883         }
9884         
9885         ic->generated = 1;
9886         
9887         /* the result is now in the accumulator */
9888         freeAsmop(cond,NULL,ic,TRUE);
9889 }
9890
9891 /*-----------------------------------------------------------------*/
9892 /* genAddrOf - generates code for address of                       */
9893 /*-----------------------------------------------------------------*/
9894 static void genAddrOf (iCode *ic)
9895 {
9896         operand *right, *result, *left;
9897         int size, offset ;
9898         
9899         FENTRY;
9900         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9901         
9902         
9903         //aopOp(IC_RESULT(ic),ic,FALSE);
9904         
9905         aopOp((left=IC_LEFT(ic)),ic,FALSE);
9906         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9907         aopOp((result=IC_RESULT(ic)),ic,TRUE);
9908         
9909         DEBUGpic14_AopType(__LINE__,left,right,result);
9910         assert (IS_SYMOP (left));
9911         
9912         /* sanity check: generic pointers to code space are not yet supported,
9913          * pionters to codespace must not be assigned addresses of __data values. */
9914  #if 0
9915         fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9916         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)));
9917         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)));
9918         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)));
9919         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)));
9920 #endif
9921
9922         if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9923           fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9924                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9925                 OP_SYMBOL(left)->name);
9926         } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9927           fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9928                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9929                 OP_SYMBOL(left)->name);
9930         }
9931         
9932         size = AOP_SIZE(IC_RESULT(ic));
9933         if (IS_GENPTR(OP_SYM_TYPE(result))) {
9934                 /* strip tag */
9935                 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9936         }
9937         offset = 0;
9938         
9939         while (size--) {
9940                 /* fixing bug #863624, reported from (errolv) */
9941                 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9942                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9943                 
9944 #if 0
9945                 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9946                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9947 #endif
9948                 offset++;
9949         }
9950
9951         if (IS_GENPTR(OP_SYM_TYPE(result)))
9952         {
9953                 /* provide correct tag */
9954                 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9955                 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9956                 movwf (AOP(result), 2);
9957         }
9958         
9959         freeAsmop(left,NULL,ic,FALSE);
9960         freeAsmop(result,NULL,ic,TRUE);
9961         
9962 }
9963
9964 #if 0
9965 /*-----------------------------------------------------------------*/
9966 /* genFarFarAssign - assignment when both are in far space         */
9967 /*-----------------------------------------------------------------*/
9968 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9969 {
9970         int size = AOP_SIZE(right);
9971         int offset = 0;
9972         char *l ;
9973         /* first push the right side on to the stack */
9974         while (size--) {
9975                 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9976                 MOVA(l);
9977                 pic14_emitcode ("push","acc");
9978         }
9979         
9980         freeAsmop(right,NULL,ic,FALSE);
9981         /* now assign DPTR to result */
9982         aopOp(result,ic,FALSE);
9983         size = AOP_SIZE(result);
9984         while (size--) {
9985                 pic14_emitcode ("pop","acc");
9986                 aopPut(AOP(result),"a",--offset);
9987         }
9988         freeAsmop(result,NULL,ic,FALSE);
9989         
9990 }
9991 #endif
9992
9993 /*-----------------------------------------------------------------*/
9994 /* genAssign - generate code for assignment                        */
9995 /*-----------------------------------------------------------------*/
9996 static void genAssign (iCode *ic)
9997 {
9998         operand *result, *right;
9999         int size, offset,know_W;
10000         unsigned long lit = 0L;
10001         
10002         result = IC_RESULT(ic);
10003         right  = IC_RIGHT(ic) ;
10004         
10005         FENTRY;
10006         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10007         
10008         /* if they are the same */
10009         if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10010                 return ;
10011         
10012         aopOp(right,ic,FALSE);
10013         aopOp(result,ic,TRUE);
10014         
10015         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10016         
10017         /* if they are the same registers */
10018         if (pic14_sameRegs(AOP(right),AOP(result)))
10019                 goto release;
10020
10021         /* special case: assign from __code */
10022         if (!IS_ITEMP(right)                            /* --> iTemps never reside in __code */
10023                 && IS_SYMOP (right)                     /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
10024                 && !IS_FUNC(OP_SYM_TYPE(right))         /* --> we would want its address instead of the first instruction */
10025                 && !IS_CODEPTR(OP_SYM_TYPE(right))      /* --> get symbols address instread */
10026                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
10027         {
10028           emitpComment ("genAssign from CODESPACE");
10029           genConstPointerGet (right, result, ic);
10030           goto release;
10031         }
10032         
10033         /* just for symmetry reasons... */
10034         if (!IS_ITEMP(result)
10035                 && IS_SYMOP (result)
10036                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
10037         {
10038           assert ( !"cannot write to CODESPACE" );
10039         }
10040
10041         /* if the result is a bit */
10042         if (AOP_TYPE(result) == AOP_CRY) {
10043                 
10044         /* if the right size is a literal then
10045                 we know what the value is */
10046                 if (AOP_TYPE(right) == AOP_LIT) {
10047                         
10048                         emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10049                                 popGet(AOP(result),0));
10050                         
10051                         if (((int) operandLitValue(right))) 
10052                                 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10053                                 AOP(result)->aopu.aop_dir,
10054                                 AOP(result)->aopu.aop_dir);
10055                         else
10056                                 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10057                                 AOP(result)->aopu.aop_dir,
10058                                 AOP(result)->aopu.aop_dir);
10059                         goto release;
10060                 }
10061                 
10062                 /* the right is also a bit variable */
10063                 if (AOP_TYPE(right) == AOP_CRY) {
10064                         emitpcode(POC_BCF,    popGet(AOP(result),0));
10065                         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10066                         emitpcode(POC_BSF,    popGet(AOP(result),0));
10067                         
10068                         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10069                                 AOP(result)->aopu.aop_dir,
10070                                 AOP(result)->aopu.aop_dir);
10071                         pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10072                                 AOP(right)->aopu.aop_dir,
10073                                 AOP(right)->aopu.aop_dir);
10074                         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10075                                 AOP(result)->aopu.aop_dir,
10076                                 AOP(result)->aopu.aop_dir);
10077                         goto release ;
10078                 }
10079                 
10080                 /* we need to or */
10081                 emitpcode(POC_BCF,    popGet(AOP(result),0));
10082                 pic14_toBoolean(right);
10083                 emitSKPZ;
10084                 emitpcode(POC_BSF,    popGet(AOP(result),0));
10085                 //aopPut(AOP(result),"a",0);
10086                 goto release ;
10087         }
10088         
10089         /* bit variables done */
10090         /* general case */
10091         size = AOP_SIZE(result);
10092         offset = 0 ;
10093         if(AOP_TYPE(right) == AOP_LIT)
10094                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10095         
10096         if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10097                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10098                 if(aopIdx(AOP(result),0) == 4) {
10099                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10100                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10101                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10102                         goto release;
10103                 } else
10104                         DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10105         }
10106         
10107         know_W=-1;
10108         while (size--) {
10109                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10110                 if(AOP_TYPE(right) == AOP_LIT) {
10111                         if(lit&0xff) {
10112                                 if(know_W != (int)(lit&0xff))
10113                                         emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10114                                 know_W = lit&0xff;
10115                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10116                         } else
10117                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10118                         
10119                         lit >>= 8;
10120                         
10121                 } else if (AOP_TYPE(right) == AOP_CRY) {
10122                         emitpcode(POC_CLRF, popGet(AOP(result),offset));
10123                         if(offset == 0) {
10124                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10125                                 emitpcode(POC_INCF, popGet(AOP(result),0));
10126                         }
10127                 } else {
10128                         mov2w_op (right, offset);
10129                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10130                 }
10131                 
10132                 offset++;
10133         }
10134         
10135         
10136 release:
10137         freeAsmop (right,NULL,ic,FALSE);
10138         freeAsmop (result,NULL,ic,TRUE);
10139 }   
10140
10141 /*-----------------------------------------------------------------*/
10142 /* genJumpTab - genrates code for jump table                       */
10143 /*-----------------------------------------------------------------*/
10144 static void genJumpTab (iCode *ic)
10145 {
10146         symbol *jtab;
10147         char *l;
10148         
10149         FENTRY;
10150         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10151         
10152         aopOp(IC_JTCOND(ic),ic,FALSE);
10153         /* get the condition into accumulator */
10154         l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10155         MOVA(l);
10156         /* multiply by three */
10157         pic14_emitcode("add","a,acc");
10158         pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10159         
10160         jtab = newiTempLabel(NULL);
10161         pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10162         pic14_emitcode("jmp","@a+dptr");
10163         pic14_emitcode("","%05d_DS_:",jtab->key+100);
10164         
10165         emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10166         emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10167         emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10168         emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10169         emitSKPNC;
10170         emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10171         emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10172         emitpLabel(jtab->key);
10173         
10174         freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10175         
10176         /* now generate the jump labels */
10177         for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10178         jtab = setNextItem(IC_JTLABELS(ic))) {
10179                 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10180                 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10181                 
10182         }
10183         
10184 }
10185
10186 /*-----------------------------------------------------------------*/
10187 /* genMixedOperation - gen code for operators between mixed types  */
10188 /*-----------------------------------------------------------------*/
10189 /*
10190 TSD - Written for the PIC port - but this unfortunately is buggy.
10191 This routine is good in that it is able to efficiently promote 
10192 types to different (larger) sizes. Unfortunately, the temporary
10193 variables that are optimized out by this routine are sometimes
10194 used in other places. So until I know how to really parse the 
10195 iCode tree, I'm going to not be using this routine :(.
10196 */
10197 static int genMixedOperation (iCode *ic)
10198 {
10199         FENTRY;
10200 #if 0
10201         operand *result = IC_RESULT(ic);
10202         sym_link *ctype = operandType(IC_LEFT(ic));
10203         operand *right = IC_RIGHT(ic);
10204         int ret = 0;
10205         int big,small;
10206         int offset;
10207         
10208         iCode *nextic;
10209         operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10210         
10211         pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10212         
10213         nextic = ic->next;
10214         if(!nextic)
10215                 return 0;
10216         
10217         nextright = IC_RIGHT(nextic);
10218         nextleft  = IC_LEFT(nextic);
10219         nextresult = IC_RESULT(nextic);
10220         
10221         aopOp(right,ic,FALSE);
10222         aopOp(result,ic,FALSE);
10223         aopOp(nextright,  nextic, FALSE);
10224         aopOp(nextleft,   nextic, FALSE);
10225         aopOp(nextresult, nextic, FALSE);
10226         
10227         if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10228                 
10229                 operand *t = right;
10230                 right = nextright;
10231                 nextright = t; 
10232                 
10233                 pic14_emitcode(";remove right +","");
10234                 
10235         } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10236         /*
10237         operand *t = right;
10238         right = nextleft;
10239         nextleft = t; 
10240                 */
10241                 pic14_emitcode(";remove left +","");
10242         } else
10243                 return 0;
10244         
10245         big = AOP_SIZE(nextleft);
10246         small = AOP_SIZE(nextright);
10247         
10248         switch(nextic->op) {
10249                 
10250         case '+':
10251                 pic14_emitcode(";optimize a +","");
10252                 /* if unsigned or not an integral type */
10253                 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10254                         pic14_emitcode(";add a bit to something","");
10255                 } else {
10256                         
10257                         pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10258                         
10259                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10260                                 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10261                                 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10262                         } else
10263                                 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10264                         
10265                         offset = 0;
10266                         while(--big) {
10267                                 
10268                                 offset++;
10269                                 
10270                                 if(--small) {
10271                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10272                                                 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10273                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10274                                         }
10275                                         
10276                                         pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10277                                         emitSKPNC;
10278                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10279                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10280                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10281                                         pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10282                                         pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10283                                         
10284                                 } else {
10285                                         pic14_emitcode("rlf","known_zero,w");
10286                                         
10287                                         /*
10288                                         if right is signed
10289                                         btfsc  right,7
10290                                         addlw ff
10291                                         */
10292                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10293                                                 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10294                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10295                                         } else {
10296                                                 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10297                                         }
10298                                 }
10299                         }
10300                         ret = 1;
10301                 }
10302         }
10303         ret = 1;
10304         
10305 release:
10306         freeAsmop(right,NULL,ic,TRUE);
10307         freeAsmop(result,NULL,ic,TRUE);
10308         freeAsmop(nextright,NULL,ic,TRUE);
10309         freeAsmop(nextleft,NULL,ic,TRUE);
10310         if(ret)
10311                 nextic->generated = 1;
10312         
10313         return ret;
10314 #else
10315         return 0;
10316 #endif
10317 }
10318 /*-----------------------------------------------------------------*/
10319 /* genCast - gen code for casting                                  */
10320 /*-----------------------------------------------------------------*/
10321 static void genCast (iCode *ic)
10322 {
10323         operand *result = IC_RESULT(ic);
10324         sym_link *restype = operandType(result);
10325         sym_link *rtype = operandType(IC_RIGHT(ic));
10326         operand *right = IC_RIGHT(ic);
10327         int size, offset ;
10328         
10329         FENTRY;
10330         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10331         /* if they are equivalent then do nothing */
10332         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10333                 return ;
10334         
10335         aopOp(right,ic,FALSE) ;
10336         aopOp(result,ic,FALSE);
10337         
10338         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10339         
10340         /* if the result is a bit */
10341         if (AOP_TYPE(result) == AOP_CRY) {
10342                 assert(!"assigning to bit variables is not supported");
10343         }
10344         
10345         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10346                 int offset = 1;
10347                 size = AOP_SIZE(result);
10348                 
10349                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10350                 
10351                 emitpcode(POC_CLRF,   popGet(AOP(result),0));
10352                 emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10353                 emitpcode(POC_INCF,   popGet(AOP(result),0));
10354                 
10355                 while (size--)
10356                         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
10357                 
10358                 goto release;
10359         }
10360         
10361         if (IS_PTR(restype))
10362         {
10363           operand *result = IC_RESULT(ic);
10364           //operand *left = IC_LEFT(ic);
10365           operand *right = IC_RIGHT(ic);
10366           int tag = 0xff;
10367           
10368           /* copy common part */
10369           int max, size = AOP_SIZE(result);
10370           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10371           DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10372
10373           /* warn if we discard generic opinter tag */
10374           if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10375           {
10376             //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10377           } // if
10378
10379           max = size;
10380           while (size--)
10381           {
10382             mov2w_op (right, size);
10383             movwf (AOP(result), size);
10384           } // while
10385
10386           /* upcast into generic pointer type? */
10387           if (IS_GENPTR(restype)
10388                 && (size < AOP_SIZE(result))
10389                 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10390           {
10391             //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10392             if (IS_PTR(rtype))
10393             {
10394               switch (DCL_TYPE(rtype))
10395               {
10396               case POINTER:     /* __data */
10397               case FPOINTER:    /* __data */
10398                 assert (AOP_SIZE(right) == 2);
10399                 tag = GPTRTAG_DATA;
10400                 break;
10401
10402               case CPOINTER:    /* __code */
10403                 assert (AOP_SIZE(right) == 2);
10404                 tag = GPTRTAG_CODE;
10405                 break;
10406                 
10407               case GPOINTER:    /* unknown destination, __data or __code */
10408                 /* assume __data space (address of immediate) */
10409                 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10410                 if (AOP(right)->code)
10411                   tag = GPTRTAG_CODE;
10412                 else
10413                   tag = GPTRTAG_DATA;
10414                 break;
10415                 
10416               default:
10417                 assert (!"unhandled pointer type");
10418               } // switch
10419             } else {
10420               /* convert other values into pointers to __data space */
10421               tag = GPTRTAG_DATA;
10422             }
10423
10424             assert (AOP_SIZE(result) == 3);
10425             if (tag == 0) {
10426               emitpcode(POC_CLRF, popGet(AOP(result), 2));
10427             } else {
10428               emitpcode(POC_MOVLW, popGetLit(tag));
10429               movwf(AOP(result), 2);
10430             }
10431           } else {
10432             addSign(result, max, 0);
10433           } // if
10434           goto release;
10435         }
10436         
10437         /* if they are the same size : or less */
10438         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10439                 
10440                 /* if they are in the same place */
10441                 if (pic14_sameRegs(AOP(right),AOP(result)))
10442                         goto release;
10443                 
10444                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10445                 if (IS_PTR_CONST(rtype))
10446                         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10447                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10448                         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10449                 
10450                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10451                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10452                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
10453                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10454                         emitpcode(POC_MOVWF, popGet(AOP(result),1));
10455                         if(AOP_SIZE(result) <2)
10456                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10457                         
10458                 } else {
10459                         
10460                         /* if they in different places then copy */
10461                         size = AOP_SIZE(result);
10462                         offset = 0 ;
10463                         while (size--) {
10464                                 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10465                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10466                                 
10467                                 //aopPut(AOP(result),
10468                                 // aopGet(AOP(right),offset,FALSE,FALSE),
10469                                 // offset);
10470                                 
10471                                 offset++;
10472                         }
10473                 }
10474                 goto release;
10475         }
10476         
10477         /* so we now know that the size of destination is greater
10478         than the size of the source.
10479         Now, if the next iCode is an operator then we might be
10480         able to optimize the operation without performing a cast.
10481         */
10482         if(0 && genMixedOperation(ic)) {
10483                 /* XXX: cannot optimize: must copy regs! */
10484                 goto release;
10485         }
10486         
10487         /* we move to result for the size of source */
10488         size = AOP_SIZE(right);
10489         offset = 0 ;
10490         while (size--) {
10491                 emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
10492                 emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
10493                 offset++;
10494         }
10495
10496         addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10497
10498 release:
10499         freeAsmop(right,NULL,ic,TRUE);
10500         freeAsmop(result,NULL,ic,TRUE);
10501         
10502 }
10503
10504 /*-----------------------------------------------------------------*/
10505 /* genDjnz - generate decrement & jump if not zero instrucion      */
10506 /*-----------------------------------------------------------------*/
10507 static int genDjnz (iCode *ic, iCode *ifx)
10508 {
10509         symbol *lbl, *lbl1;
10510         FENTRY;
10511         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10512         
10513         if (!ifx)
10514                 return 0;
10515         
10516                 /* if the if condition has a false label
10517         then we cannot save */
10518         if (IC_FALSE(ifx))
10519                 return 0;
10520         
10521                 /* if the minus is not of the form 
10522         a = a - 1 */
10523         if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10524                 !IS_OP_LITERAL(IC_RIGHT(ic)))
10525                 return 0;
10526         
10527         if (operandLitValue(IC_RIGHT(ic)) != 1)
10528                 return 0;
10529         
10530                 /* if the size of this greater than one then no
10531         saving */
10532         if (getSize(operandType(IC_RESULT(ic))) > 1)
10533                 return 0;
10534         
10535         /* otherwise we can save BIG */
10536         lbl = newiTempLabel(NULL);
10537         lbl1= newiTempLabel(NULL);
10538         
10539         aopOp(IC_RESULT(ic),ic,FALSE);
10540         
10541         if (IS_AOP_PREG(IC_RESULT(ic))) {
10542                 pic14_emitcode("dec","%s",
10543                         aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10544                 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10545                 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10546         } else {  
10547                 
10548                 
10549                 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10550                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10551                 
10552                 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10553                 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10554                 
10555         }
10556         /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10557         /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10558         /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10559         /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10560         
10561         
10562         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10563         ifx->generated = 1;
10564         return 1;
10565 }
10566
10567 /*-----------------------------------------------------------------*/
10568 /* genReceive - generate code for a receive iCode                  */
10569 /*-----------------------------------------------------------------*/
10570 static void genReceive (iCode *ic)
10571 {
10572         FENTRY;
10573         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10574         
10575         if (isOperandInFarSpace(IC_RESULT(ic)) &&
10576                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10577                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10578                 
10579                 int size = getSize(operandType(IC_RESULT(ic)));
10580                 int offset =  fReturnSizePic - size;
10581                 while (size--) {
10582                         pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10583                                 fReturn[fReturnSizePic - offset - 1] : "acc"));
10584                         offset++;
10585                 }
10586                 aopOp(IC_RESULT(ic),ic,FALSE);
10587                 size = AOP_SIZE(IC_RESULT(ic));
10588                 offset = 0;
10589                 while (size--) {
10590                         pic14_emitcode ("pop","acc");
10591                         aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10592                 }
10593                 
10594         } else {
10595                 _G.accInUse++;
10596                 aopOp(IC_RESULT(ic),ic,FALSE);
10597                 _G.accInUse--;
10598                 assignResultValue(IC_RESULT(ic));
10599         }
10600         
10601         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10602 }
10603
10604 /*-----------------------------------------------------------------*/
10605 /* genDummyRead - generate code for dummy read of volatiles        */
10606 /*-----------------------------------------------------------------*/
10607 static void
10608 genDummyRead (iCode * ic)
10609 {
10610         FENTRY;
10611         pic14_emitcode ("; genDummyRead","");
10612         pic14_emitcode ("; not implemented","");
10613         
10614         ic = ic;
10615 }
10616
10617 /*-----------------------------------------------------------------*/
10618 /* genpic14Code - generate code for pic14 based controllers        */
10619 /*-----------------------------------------------------------------*/
10620 /*
10621 * At this point, ralloc.c has gone through the iCode and attempted
10622 * to optimize in a way suitable for a PIC. Now we've got to generate
10623 * PIC instructions that correspond to the iCode.
10624 *
10625 * Once the instructions are generated, we'll pass through both the
10626 * peep hole optimizer and the pCode optimizer.
10627 *-----------------------------------------------------------------*/
10628
10629 void genpic14Code (iCode *lic)
10630 {
10631         iCode *ic;
10632         int cln = 0;
10633         const char *cline;
10634         
10635         FENTRY;
10636         lineHead = lineCurr = NULL;
10637         
10638         pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10639         addpBlock(pb);
10640         
10641         /* if debug information required */
10642         if (options.debug && currFunc) { 
10643                 if (currFunc) {
10644                         debugFile->writeFunction (currFunc, lic);
10645                 }
10646         }
10647         
10648         
10649         for (ic = lic ; ic ; ic = ic->next ) {
10650                 
10651                 //DEBUGpic14_emitcode(";ic","");
10652                 //fprintf (stderr, "in ic loop\n");
10653                 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10654                 //ic->lineno, printCLine(ic->filename, ic->lineno));
10655                 
10656                 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10657                   cln = ic->lineno;
10658                   //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10659                   cline = printCLine (ic->filename, ic->lineno);
10660                   if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10661                   addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10662                   //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10663                 }
10664                 
10665                 if (options.iCodeInAsm) {
10666                   emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10667                 }
10668                 /* if the result is marked as
10669                 spilt and rematerializable or code for
10670                 this has already been generated then
10671                 do nothing */
10672                 if (resultRemat(ic) || ic->generated ) 
10673                         continue ;
10674                 
10675                 /* depending on the operation */
10676                 switch (ic->op) {
10677                 case '!' :
10678                         genNot(ic);
10679                         break;
10680                         
10681                 case '~' :
10682                         genCpl(ic);
10683                         break;
10684                         
10685                 case UNARYMINUS:
10686                         genUminus (ic);
10687                         break;
10688                         
10689                 case IPUSH:
10690                         genIpush (ic);
10691                         break;
10692                         
10693                 case IPOP:
10694                         /* IPOP happens only when trying to restore a 
10695                         spilt live range, if there is an ifx statement
10696                         following this pop then the if statement might
10697                         be using some of the registers being popped which
10698                         would destory the contents of the register so
10699                         we need to check for this condition and handle it */
10700                         if (ic->next            && 
10701                                 ic->next->op == IFX &&
10702                                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10703                                 genIfx (ic->next,ic);
10704                         else
10705                                 genIpop (ic);
10706                         break; 
10707                         
10708                 case CALL:
10709                         genCall (ic);
10710                         break;
10711                         
10712                 case PCALL:
10713                         genPcall (ic);
10714                         break;
10715                         
10716                 case FUNCTION:
10717                         genFunction (ic);
10718                         break;
10719                         
10720                 case ENDFUNCTION:
10721                         genEndFunction (ic);
10722                         break;
10723                         
10724                 case RETURN:
10725                         genRet (ic);
10726                         break;
10727                         
10728                 case LABEL:
10729                         genLabel (ic);
10730                         break;
10731                         
10732                 case GOTO:
10733                         genGoto (ic);
10734                         break;
10735                         
10736                 case '+' :
10737                         genPlus (ic) ;
10738                         break;
10739                         
10740                 case '-' :
10741                         if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10742                                 genMinus (ic);
10743                         break;
10744                         
10745                 case '*' :
10746                         genMult (ic);
10747                         break;
10748                         
10749                 case '/' :
10750                         genDiv (ic) ;
10751                         break;
10752                         
10753                 case '%' :
10754                         genMod (ic);
10755                         break;
10756                         
10757                 case '>' :
10758                         genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));         
10759                         break;
10760                         
10761                 case '<' :
10762                         genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10763                         break;
10764                         
10765                 case LE_OP:
10766                 case GE_OP:
10767                 case NE_OP:
10768                         
10769                         /* note these two are xlated by algebraic equivalence
10770                         during parsing SDCC.y */
10771                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10772                                 "got '>=' or '<=' shouldn't have come here");
10773                         break;  
10774                         
10775                 case EQ_OP:
10776                         genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10777                         break;      
10778                         
10779                 case AND_OP:
10780                         genAndOp (ic);
10781                         break;
10782                         
10783                 case OR_OP:
10784                         genOrOp (ic);
10785                         break;
10786                         
10787                 case '^' :
10788                         genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10789                         break;
10790                         
10791                 case '|' :
10792                         genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10793                         break;
10794                         
10795                 case BITWISEAND:
10796                         genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10797                         break;
10798                         
10799                 case INLINEASM:
10800                         genInline (ic);
10801                         break;
10802                         
10803                 case RRC:
10804                         genRRC (ic);
10805                         break;
10806                         
10807                 case RLC:
10808                         genRLC (ic);
10809                         break;
10810                         
10811                 case GETHBIT:
10812                         genGetHbit (ic);
10813                         break;
10814                         
10815                 case LEFT_OP:
10816                         genLeftShift (ic);
10817                         break;
10818                         
10819                 case RIGHT_OP:
10820                         genRightShift (ic);
10821                         break;
10822                         
10823                 case GET_VALUE_AT_ADDRESS:
10824                         genPointerGet(ic);
10825                         break;
10826                         
10827                 case '=' :
10828                         if (POINTER_SET(ic))
10829                                 genPointerSet(ic);
10830                         else
10831                                 genAssign(ic);
10832                         break;
10833                         
10834                 case IFX:
10835                         genIfx (ic,NULL);
10836                         break;
10837                         
10838                 case ADDRESS_OF:
10839                         genAddrOf (ic);
10840                         break;
10841                         
10842                 case JUMPTABLE:
10843                         genJumpTab (ic);
10844                         break;
10845                         
10846                 case CAST:
10847                         genCast (ic);
10848                         break;
10849                         
10850                 case RECEIVE:
10851                         genReceive(ic);
10852                         break;
10853                         
10854                 case SEND:
10855                         addSet(&_G.sendSet,ic);
10856                         break;
10857                         
10858                 case DUMMY_READ_VOLATILE:
10859                         genDummyRead (ic);
10860                         break;
10861                         
10862                 default :
10863                         fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10864                         ic = ic;
10865                         break;
10866                 }
10867         }
10868
10869         
10870         /* now we are ready to call the
10871         peep hole optimizer */
10872         if (!options.nopeep) {
10873                 peepHole (&lineHead);
10874         }
10875         /* now do the actual printing */
10876         printLine (lineHead,codeOutFile);
10877         
10878 #ifdef PCODE_DEBUG
10879         DFPRINTF((stderr,"printing pBlock\n\n"));
10880         printpBlock(stdout,pb);
10881 #endif
10882         
10883         return;
10884 }
10885
10886 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10887  * (meaning: representing its own address) or not (referencing its contents).
10888  * This can only be decided based on the operand's type. */
10889 int
10890 aop_isLitLike (asmop *aop)
10891 {
10892   assert (aop);
10893   if (aop->type == AOP_LIT) return 1;
10894 if (aop->type == AOP_IMMD) return 1;
10895   if ((aop->type == AOP_PCODE) &&
10896                 ((aop->aopu.pcop->type == PO_LITERAL)))
10897   {
10898     /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10899      * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10900     return 1;
10901   }
10902   return 0;
10903 }
10904
10905 int
10906 op_isLitLike (operand *op)
10907 {
10908   assert (op);
10909   if (aop_isLitLike (AOP(op))) return 1;
10910   if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10911   if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;
10912   return 0;
10913 }