* src/pic/gen.c (genFunction): set global pic14_hasInterrupt on
[fw/sdcc] / src / pic / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for pic
3   
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8     cont'd   -  Raphael Neider rneider@web.de (2005)
9   
10   This program is free software; you can redistribute it and/or modify it
11   under the terms of the GNU General Public License as published by the
12   Free Software Foundation; either version 2, or (at your option) any
13   later version.
14   
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License for more details.
19   
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23   
24   In other words, you are welcome to use, share and improve this program.
25   You are forbidden to forbid anyone else to use, share and improve
26   what you give them.   Help stamp out software-hoarding!
27   
28   Notes:
29   000123 mlh  Moved aopLiteral to SDCCglue.c to help the split
30       Made everything static
31 -------------------------------------------------------------------------*/
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include "SDCCglobl.h"
38 #include "newalloc.h"
39
40 #include "common.h"
41 #include "SDCCpeeph.h"
42 #include "ralloc.h"
43 #include "pcode.h"
44 #include "gen.h"
45
46 /* When changing these, you must also update the assembler template
47  * in device/lib/libsdcc/macros.inc */
48 #define GPTRTAG_DATA    0x00
49 #define GPTRTAG_CODE    0x80
50
51 /* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
52 #define PIC_IS_DATA_PTR(x)      (IS_DATA_PTR(x) || IS_FARPTR(x))
53 #define PIC_IS_FARPTR(x)        (PIC_IS_DATA_PTR(x))
54
55 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
56 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
57 void genMult8X8_8 (operand *, operand *,operand *);
58 extern void printpBlock(FILE *of, pBlock *pb);
59
60 static int labelOffset=0;
61 extern int debug_verbose;
62 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 = 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 = 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                         if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
946                         {
947                                 /* force a new aop if sizes differ */
948                                 sym->usl.spillLoc->aop = NULL;
949                         }
950                         DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
951                                 __FUNCTION__,__LINE__,
952                                 sym->usl.spillLoc->rname,
953                                 sym->rname, sym->usl.spillLoc->offset);
954                 
955                         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
956                         //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
957                         aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
958                                 getSize(sym->type), 
959                                 sym->usl.spillLoc->offset);
960                         aop->size = getSize(sym->type);
961                 
962                         return;
963                 }
964         }
965         
966         {
967                 sym_link *type = operandType(op);
968                 if(IS_PTR_CONST(type)) 
969                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
970         }
971         
972         /* must be in a register */
973         DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
974         sym->aop = op->aop = aop = newAsmop(AOP_REG);
975         aop->size = sym->nRegs;
976         for ( i = 0 ; i < sym->nRegs ;i++)
977                 aop->aopu.aop_reg[i] = sym->regs[i];
978 }
979
980 /*-----------------------------------------------------------------*/
981 /* freeAsmop - free up the asmop given to an operand                       */
982 /*----------------------------------------------------------------*/
983 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
984 {       
985         asmop *aop ;
986         
987         if (!op)
988                 aop = aaop;
989         else 
990                 aop = op->aop;
991         
992         if (!aop)
993                 return ;
994         
995         if (aop->freed)
996                 goto dealloc; 
997         
998         aop->freed = 1;
999         
1000         /* depending on the asmop type only three cases need work AOP_RO
1001         , AOP_R1 && AOP_STK */
1002 #if 0
1003         switch (aop->type) {
1004         case AOP_R0 :
1005                 if (_G.r0Pushed ) {
1006                         if (pop) {
1007                                 pic14_emitcode ("pop","ar0");     
1008                                 _G.r0Pushed--;
1009                         }
1010                 }
1011                 bitVectUnSetBit(ic->rUsed,R0_IDX);
1012                 break;
1013                 
1014         case AOP_R1 :
1015                 if (_G.r1Pushed ) {
1016                         if (pop) {
1017                                 pic14_emitcode ("pop","ar1");
1018                                 _G.r1Pushed--;
1019                         }
1020                 }
1021                 bitVectUnSetBit(ic->rUsed,R1_IDX);                      
1022                 break;
1023                 
1024         case AOP_STK :
1025                 {
1026                         int sz = aop->size;      
1027                         int stk = aop->aopu.aop_stk + aop->size;
1028                         bitVectUnSetBit(ic->rUsed,R0_IDX);
1029                         bitVectUnSetBit(ic->rUsed,R1_IDX);                
1030                         
1031                         getFreePtr(ic,&aop,FALSE);
1032                         
1033                         if (options.stack10bit)
1034                         {
1035                                 /* I'm not sure what to do here yet... */
1036                                 /* #STUB */
1037                                 fprintf(stderr, 
1038                                         "*** Warning: probably generating bad code for "
1039                                         "10 bit stack mode.\n");
1040                         }
1041                         
1042                         if (stk) {
1043                                 pic14_emitcode ("mov","a,_bp");
1044                                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1045                                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1046                         } else {
1047                                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1048                         }
1049                         
1050                         while (sz--) {
1051                                 pic14_emitcode("pop","acc");
1052                                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1053                                 if (!sz) break;
1054                                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1055                         }
1056                         op->aop = aop;
1057                         freeAsmop(op,NULL,ic,TRUE);
1058                         if (_G.r0Pushed) {
1059                                 pic14_emitcode("pop","ar0");
1060                                 _G.r0Pushed--;
1061                         }
1062                         
1063                         if (_G.r1Pushed) {
1064                                 pic14_emitcode("pop","ar1");
1065                                 _G.r1Pushed--;
1066                         }         
1067                 }
1068         }
1069 #endif
1070         
1071 dealloc:
1072         /* all other cases just dealloc */
1073         if (op ) {
1074                 op->aop = NULL;
1075                 if (IS_SYMOP(op)) {
1076                         OP_SYMBOL(op)->aop = NULL;      
1077                         /* if the symbol has a spill */
1078                         if (SPIL_LOC(op))
1079                                 SPIL_LOC(op)->aop = NULL;
1080                 }
1081         }
1082 }
1083
1084 /*-----------------------------------------------------------------*/
1085 /* aopGet - for fetching value of the aop                                                  */
1086 /*-----------------------------------------------------------------*/
1087 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1088 {
1089         char *s = buffer ;
1090         char *rs;
1091         
1092         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1093         /* offset is greater than
1094         size then zero */
1095         if (offset > (aop->size - 1) &&
1096                 aop->type != AOP_LIT)
1097                 return zero;
1098         
1099         /* depending on type */
1100         switch (aop->type) {
1101                 
1102         case AOP_R0:
1103         case AOP_R1:
1104                 DEBUGpic14_emitcode(";","%d",__LINE__);
1105                 /* if we need to increment it */           
1106                 while (offset > aop->coff) {            
1107                         pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);    
1108                         aop->coff++;
1109                 }
1110                 
1111                 while (offset < aop->coff) {
1112                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1113                         aop->coff--;
1114                 }
1115                 
1116                 aop->coff = offset ;
1117                 if (aop->paged) {
1118                         pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1119                         return (dname ? "acc" : "a");
1120                 }               
1121                 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1122                 rs = Safe_calloc(1,strlen(s)+1);
1123                 strcpy(rs,s);   
1124                 return rs;
1125                 
1126         case AOP_DPTR:
1127         case AOP_DPTR2:
1128                 DEBUGpic14_emitcode(";","%d",__LINE__);
1129                 if (aop->type == AOP_DPTR2)
1130                 {
1131                         genSetDPTR(1);
1132                 }
1133                 
1134                 while (offset > aop->coff) {
1135                         pic14_emitcode ("inc","dptr");
1136                         aop->coff++;
1137                 }
1138                 
1139                 while (offset < aop->coff) {            
1140                         pic14_emitcode("lcall","__decdptr");
1141                         aop->coff--;
1142                 }
1143                 
1144                 aop->coff = offset;
1145                 if (aop->code) {
1146                         pic14_emitcode("clr","a");
1147                         pic14_emitcode("movc","a,@a+dptr");
1148                 }
1149                 else {
1150                         pic14_emitcode("movx","a,@dptr");
1151                 }
1152                 
1153                 if (aop->type == AOP_DPTR2)
1154                 {
1155                         genSetDPTR(0);
1156                 }
1157                 
1158                 return (dname ? "acc" : "a");
1159                 
1160                 
1161         case AOP_IMMD:
1162                 if (bit16) 
1163                         sprintf (s,"%s",aop->aopu.aop_immd);
1164                 else
1165                         if (offset) 
1166                                 sprintf(s,"(%s >> %d)",
1167                                 aop->aopu.aop_immd,
1168                                 offset*8);
1169                         else
1170                                 sprintf(s,"%s",
1171                                 aop->aopu.aop_immd);
1172                         DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1173                         rs = Safe_calloc(1,strlen(s)+1);
1174                         strcpy(rs,s);   
1175                         return rs;
1176                         
1177         case AOP_DIR:
1178                 if (offset) {
1179                         sprintf(s,"(%s + %d)",
1180                                 aop->aopu.aop_dir,
1181                                 offset);
1182                         DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1183                 } else
1184                         sprintf(s,"%s",aop->aopu.aop_dir);
1185                 rs = Safe_calloc(1,strlen(s)+1);
1186                 strcpy(rs,s);   
1187                 return rs;
1188                 
1189         case AOP_REG:
1190                 //if (dname) 
1191                 //        return aop->aopu.aop_reg[offset]->dname;
1192                 //else
1193                 return aop->aopu.aop_reg[offset]->name;
1194                 
1195         case AOP_CRY:
1196                 //pic14_emitcode(";","%d",__LINE__);
1197                 return aop->aopu.aop_dir;
1198                 
1199         case AOP_ACC:
1200                 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1201                 return "AOP_accumulator_bug";
1202                 
1203         case AOP_LIT:
1204                 sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1205                 rs = Safe_calloc(1,strlen(s)+1);
1206                 strcpy(rs,s);   
1207                 return rs;
1208                 
1209         case AOP_STR:
1210                 aop->coff = offset ;
1211                 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1212                         dname)
1213                         return "acc";
1214                 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1215                 
1216                 return aop->aopu.aop_str[offset];
1217                 
1218         case AOP_PCODE:
1219                 {
1220                         pCodeOp *pcop = aop->aopu.pcop;
1221                         DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1222                         if(pcop->name) {
1223                                 if (offset) {
1224                                         DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1225                                         sprintf(s,"(%s+%d)", pcop->name,offset);
1226                                 } else {
1227                                         DEBUGpic14_emitcode(";","%s",pcop->name);
1228                                         sprintf(s,"%s", pcop->name);
1229                                 }
1230                         } else
1231                                 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1232                         
1233                 }
1234                 rs = Safe_calloc(1,strlen(s)+1);
1235                 strcpy(rs,s);   
1236                 return rs;
1237                 
1238   }
1239   
1240   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1241           "aopget got unsupported aop->type");
1242   exit(0);
1243 }
1244
1245
1246 /*-----------------------------------------------------------------*/
1247 /* popGetTempReg - create a new temporary pCodeOp                                  */
1248 /*-----------------------------------------------------------------*/
1249 pCodeOp *popGetTempReg(void)
1250 {
1251         
1252         pCodeOp *pcop;
1253         
1254         pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1255         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1256                 PCOR(pcop)->r->wasUsed=1;
1257                 PCOR(pcop)->r->isFree=0;
1258         }
1259         
1260         return pcop;
1261 }
1262
1263 /*-----------------------------------------------------------------*/
1264 /* popReleaseTempReg - create a new temporary pCodeOp                              */
1265 /*-----------------------------------------------------------------*/
1266 void popReleaseTempReg(pCodeOp *pcop)
1267 {
1268         
1269         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1270                 PCOR(pcop)->r->isFree = 1;
1271         
1272 }
1273 /*-----------------------------------------------------------------*/
1274 /* popGetLabel - create a new pCodeOp of type PO_LABEL                     */
1275 /*-----------------------------------------------------------------*/
1276 pCodeOp *popGetLabel(unsigned int key)
1277 {
1278         
1279         DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1280         
1281         if(key>(unsigned int)max_key)
1282                 max_key = key;
1283         
1284         return newpCodeOpLabel(NULL,key+100+labelOffset);
1285 }
1286
1287 /*-------------------------------------------------------------------*/
1288 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1289 /*-------------------------------------------------------------------*/
1290 pCodeOp *popGetHighLabel(unsigned int key)
1291 {
1292         pCodeOp *pcop;
1293         pcop = popGetLabel(key);
1294         PCOLAB(pcop)->offset = 1;
1295         return pcop;
1296 }
1297
1298 /*-----------------------------------------------------------------*/
1299 /* popGetLit - asm operator to pcode operator conversion                           */
1300 /*-----------------------------------------------------------------*/
1301 pCodeOp *popGetLit(unsigned int lit)
1302 {
1303         
1304         return newpCodeOpLit((unsigned char)lit);
1305 }
1306
1307 /*-----------------------------------------------------------------*/
1308 /* popGetImmd - asm operator to pcode immediate conversion                 */
1309 /*-----------------------------------------------------------------*/
1310 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1311 {
1312         
1313         return newpCodeOpImmd(name, offset,index, 0, is_func);
1314 }
1315
1316 extern set *externs;
1317
1318 /*-----------------------------------------------------------------*/
1319 /* popGetWithString - asm operator to pcode operator conversion                    */
1320 /*-----------------------------------------------------------------*/
1321 pCodeOp *popGetWithString(char *str, int isExtern)
1322 {
1323         pCodeOp *pcop;
1324         
1325         
1326         if(!str) {
1327                 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1328                 exit (1);
1329         }
1330         
1331         pcop = newpCodeOp(str,PO_STR);
1332         PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1333
1334         return pcop;
1335 }
1336
1337 pCodeOp *popGetExternal (char *str)
1338 {
1339         pCodeOp *pcop = popGetWithString (str, 1);
1340         
1341         if (str) {
1342           symbol *sym;
1343           bool found = 0;
1344
1345           for (sym = setFirstItem (externs); !found && sym; sym = setNextItem (externs))
1346           {
1347             if (!strcmp (str, sym->rname))
1348               found = 1;
1349           }
1350           
1351           if (!found)
1352           {
1353             sym = newSymbol(str, 0);
1354             strncpy(sym->rname, str, SDCC_NAME_MAX);
1355             addSet (&externs, sym);
1356           } // if
1357         }
1358         return pcop;
1359 }
1360
1361 /*-----------------------------------------------------------------*/
1362 /* popRegFromString -                                                                                      */
1363 /*-----------------------------------------------------------------*/
1364 pCodeOp *popRegFromString(char *str, int size, int offset)
1365 {
1366         
1367         pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1368         pcop->type = PO_DIR;
1369         
1370         DEBUGpic14_emitcode(";","%d",__LINE__);
1371         
1372         if(!str)
1373                 str = "BAD_STRING";
1374         
1375         pcop->name = Safe_calloc(1,strlen(str)+1);
1376         strcpy(pcop->name,str);
1377         
1378         //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1379         
1380         PCOR(pcop)->r = dirregWithName(pcop->name);
1381         if(PCOR(pcop)->r == NULL) {
1382                 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1383                 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1384                 DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1385         } else {
1386                 DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1387         }
1388         PCOR(pcop)->instance = offset;
1389         
1390         return pcop;
1391 }
1392
1393 /*-----------------------------------------------------------------*/
1394 /*-----------------------------------------------------------------*/
1395 pCodeOp *popRegFromIdx(int rIdx)
1396 {
1397         pCodeOp *pcop;
1398         
1399         DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1400                 __FUNCTION__,__LINE__,rIdx);
1401         
1402         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1403         
1404         PCOR(pcop)->rIdx = rIdx;
1405         PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1406         PCOR(pcop)->r->isFree = 0;
1407         PCOR(pcop)->r->wasUsed = 1;
1408         
1409         pcop->type = PCOR(pcop)->r->pc_type;
1410         
1411         
1412         return pcop;
1413 }
1414
1415 /*-----------------------------------------------------------------*/
1416 /* popGet - asm operator to pcode operator conversion                      */
1417 /*-----------------------------------------------------------------*/
1418 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1419 {
1420         //char *s = buffer ;
1421         //char *rs;
1422         
1423         pCodeOp *pcop;
1424         
1425         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1426         /* offset is greater than
1427         size then zero */
1428
1429         assert (aop);
1430
1431         /* XXX: still needed for BIT operands (AOP_CRY) */
1432         if (offset > (aop->size - 1) &&
1433                 aop->type != AOP_LIT)
1434                 return NULL;  //zero;
1435         
1436         /* depending on type */
1437         switch (aop->type) {
1438                 
1439         case AOP_R0:
1440         case AOP_R1:
1441         case AOP_DPTR:
1442         case AOP_DPTR2:
1443         case AOP_ACC:
1444                 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1445                 return NULL;
1446                 
1447         case AOP_IMMD:
1448                 DEBUGpic14_emitcode(";","%d",__LINE__);
1449                 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1450                 
1451         case AOP_DIR:
1452                 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1453 #if 0
1454                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1455                 pcop->type = PO_DIR;
1456                 
1457                 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1458                 strcpy(pcop->name,aop->aopu.aop_dir);   
1459                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1460                 if(PCOR(pcop)->r == NULL) {
1461                         //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1462                         PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1463                         DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1464                 } else {
1465                         DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1466                 }
1467                 PCOR(pcop)->instance = offset;
1468                 
1469                 return pcop;
1470 #endif
1471                 
1472         case AOP_REG:
1473                 {
1474                         int rIdx;
1475                         assert (offset < aop->size);
1476                         rIdx = aop->aopu.aop_reg[offset]->rIdx;
1477                         
1478                         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1479                         PCOR(pcop)->rIdx = rIdx;
1480                         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1481                         PCOR(pcop)->r->wasUsed=1;
1482                         PCOR(pcop)->r->isFree=0;
1483                         
1484                         PCOR(pcop)->instance = offset;
1485                         pcop->type = PCOR(pcop)->r->pc_type;
1486                         //rs = aop->aopu.aop_reg[offset]->name;
1487                         DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1488                         return pcop;
1489                 }
1490                 
1491         case AOP_CRY:
1492                 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1493                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1494                 //if(PCOR(pcop)->r == NULL)
1495                 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1496                 return pcop;
1497                 
1498         case AOP_LIT:
1499                 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1500                 
1501         case AOP_STR:
1502                 DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1503                 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1504                 /*
1505                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1506                 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1507                 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1508                 pcop->type = PCOR(pcop)->r->pc_type;
1509                 pcop->name = PCOR(pcop)->r->name;
1510                 
1511                   return pcop;
1512                 */
1513                 
1514         case AOP_PCODE:
1515                 pcop = NULL;
1516                 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1517                         __LINE__, 
1518                         ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1519                 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1520                 switch (aop->aopu.pcop->type)
1521                 {
1522                 case PO_IMMEDIATE:
1523                   pcop = pCodeOpCopy (aop->aopu.pcop);
1524                   /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1525                    * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1526                   PCOI(pcop)->index += offset;
1527                   //PCOI(pcop)->offset = 0;
1528                   break;
1529                 case PO_DIR:
1530                   pcop = pCodeOpCopy (aop->aopu.pcop);
1531                   PCOR(pcop)->instance = offset;
1532                   break;
1533                 default:
1534                   assert ( !"unhandled pCode type" );
1535                   break;
1536                 } // switch
1537                 return pcop;
1538         }
1539         
1540         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1541                 "popGet got unsupported aop->type");
1542         exit(0);
1543 }
1544
1545 /*-----------------------------------------------------------------*/
1546 /* popGetAddr - access the low/high word of a symbol (immediate)   */
1547 /*              (for non-PO_IMMEDIATEs this is the same as popGet) */
1548 /*-----------------------------------------------------------------*/
1549 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1550 {
1551   if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1552   {
1553     pCodeOp *pcop = aop->aopu.pcop;
1554     assert (offset <= GPTRSIZE);
1555
1556     /* special case: index >= 2 should return GPOINTER-style values */
1557     if (offset == 2)
1558     {
1559       pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1560       return pcop;
1561     }
1562     
1563     pcop = pCodeOpCopy (pcop);
1564     /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1565      * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1566     PCOI(pcop)->offset += offset;
1567     PCOI(pcop)->index += index;
1568     //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);
1569     return pcop;
1570   } else {
1571     return popGet (aop, offset + index);
1572   }
1573 }
1574
1575 /*-----------------------------------------------------------------*/
1576 /* aopPut - puts a string for a aop                                                        */
1577 /*-----------------------------------------------------------------*/
1578 void aopPut (asmop *aop, char *s, int offset)
1579 {
1580         char *d = buffer ;
1581         symbol *lbl ;
1582         
1583         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1584         
1585         if (aop->size && offset > ( aop->size - 1)) {
1586                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1587                         "aopPut got offset > aop->size");
1588                 exit(0);
1589         }
1590         
1591         /* will assign value to value */
1592         /* depending on where it is ofcourse */
1593         switch (aop->type) {
1594         case AOP_DIR:
1595                 if (offset) {
1596                         sprintf(d,"(%s + %d)",
1597                                 aop->aopu.aop_dir,offset);
1598                         fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1599                         
1600                 } else
1601                         sprintf(d,"%s",aop->aopu.aop_dir);
1602                 
1603                 if (strcmp(d,s)) {
1604                         DEBUGpic14_emitcode(";","%d",__LINE__);
1605                         if(strcmp(s,"W"))
1606                                 pic14_emitcode("movf","%s,w",s);
1607                         pic14_emitcode("movwf","%s",d);
1608                         
1609                         if(strcmp(s,"W")) {
1610                                 pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1611                                 if(offset >= aop->size) {
1612                                         emitpcode(POC_CLRF,popGet(aop,offset));
1613                                         break;
1614                                 } else {
1615                                         emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1616                                 }
1617                         }
1618                         emitpcode(POC_MOVWF,popGet(aop,offset));
1619                 
1620                 }
1621                 break;
1622                 
1623         case AOP_REG:
1624                 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1625                         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1626                         /*
1627                         if (*s == '@'             ||
1628                         strcmp(s,"r0") == 0 ||
1629                         strcmp(s,"r1") == 0 ||
1630                         strcmp(s,"r2") == 0 ||
1631                         strcmp(s,"r3") == 0 ||
1632                         strcmp(s,"r4") == 0 ||
1633                         strcmp(s,"r5") == 0 ||
1634                         strcmp(s,"r6") == 0 || 
1635                         strcmp(s,"r7") == 0 )
1636                         pic14_emitcode("mov","%s,%s  ; %d",
1637                         aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1638                         else
1639                         */
1640                         
1641                         if(strcmp(s,"W")==0 )
1642                                 pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1643                         
1644                         pic14_emitcode("movwf","%s",
1645                                 aop->aopu.aop_reg[offset]->name);
1646                         
1647                         if(strcmp(s,zero)==0) {
1648                                 emitpcode(POC_CLRF,popGet(aop,offset));
1649                                 
1650                         } else if(strcmp(s,"W")==0) {
1651                                 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1652                                 pcop->type = PO_GPR_REGISTER;
1653                                 
1654                                 PCOR(pcop)->rIdx = -1;
1655                                 PCOR(pcop)->r = NULL;
1656                                 
1657                                 DEBUGpic14_emitcode(";","%d",__LINE__);
1658                                 pcop->name = Safe_strdup(s);
1659                                 emitpcode(POC_MOVFW,pcop);
1660                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1661                         } else if(strcmp(s,one)==0) {
1662                                 emitpcode(POC_CLRF,popGet(aop,offset));
1663                                 emitpcode(POC_INCF,popGet(aop,offset));
1664                         } else {
1665                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1666                         }
1667                 }
1668                 break;
1669                 
1670         case AOP_DPTR:
1671         case AOP_DPTR2:
1672                 
1673                 if (aop->type == AOP_DPTR2)
1674                 {
1675                         genSetDPTR(1);
1676                 }
1677                 
1678                 if (aop->code) {
1679                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1680                                 "aopPut writting to code space");
1681                         exit(0);
1682                 }
1683                 
1684                 while (offset > aop->coff) {
1685                         aop->coff++;
1686                         pic14_emitcode ("inc","dptr");
1687                 }
1688                 
1689                 while (offset < aop->coff) {
1690                         aop->coff-- ;
1691                         pic14_emitcode("lcall","__decdptr");
1692                 }
1693                 
1694                 aop->coff = offset;
1695                 
1696                 /* if not in accumulater */
1697                 MOVA(s);
1698                 
1699                 pic14_emitcode ("movx","@dptr,a");
1700                 
1701                 if (aop->type == AOP_DPTR2)
1702                 {
1703                         genSetDPTR(0);
1704                 }
1705                 break;
1706                 
1707         case AOP_R0:
1708         case AOP_R1:
1709                 while (offset > aop->coff) {
1710                         aop->coff++;
1711                         pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1712                 }
1713                 while (offset < aop->coff) {
1714                         aop->coff-- ;
1715                         pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1716                 }
1717                 aop->coff = offset;
1718                 
1719                 if (aop->paged) {
1720                         MOVA(s);                         
1721                         pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1722                         
1723                 } else
1724                         if (*s == '@') {
1725                                 MOVA(s);
1726                                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1727                         } else
1728                                 if (strcmp(s,"r0") == 0 ||
1729                                         strcmp(s,"r1") == 0 ||
1730                                         strcmp(s,"r2") == 0 ||
1731                                         strcmp(s,"r3") == 0 ||
1732                                         strcmp(s,"r4") == 0 ||
1733                                         strcmp(s,"r5") == 0 ||
1734                                         strcmp(s,"r6") == 0 || 
1735                                         strcmp(s,"r7") == 0 ) {
1736                                         char buffer[10];
1737                                         sprintf(buffer,"a%s",s);
1738                                         pic14_emitcode("mov","@%s,%s",
1739                                                 aop->aopu.aop_ptr->name,buffer);
1740                                 } else
1741                                         pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1742                                 
1743                                 break;
1744                                 
1745         case AOP_STK:
1746                 if (strcmp(s,"a") == 0)
1747                         pic14_emitcode("push","acc");
1748                 else
1749                         pic14_emitcode("push","%s",s);
1750                 
1751                 break;
1752                 
1753         case AOP_CRY:
1754                 /* if bit variable */
1755                 if (!aop->aopu.aop_dir) {
1756                         pic14_emitcode("clr","a");
1757                         pic14_emitcode("rlc","a");
1758                 } else {
1759                         if (s == zero) 
1760                                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1761                         else
1762                                 if (s == one)
1763                                         pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1764                                 else
1765                                         if (!strcmp(s,"c"))
1766                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1767                                         else {
1768                                                 lbl = newiTempLabel(NULL);
1769                                                 
1770                                                 if (strcmp(s,"a")) {
1771                                                         MOVA(s);
1772                                                 }
1773                                                 pic14_emitcode("clr","c");
1774                                                 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1775                                                 pic14_emitcode("cpl","c");
1776                                                 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1777                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1778                                         }
1779                 }
1780                 break;
1781                 
1782         case AOP_STR:
1783                 aop->coff = offset;
1784                 if (strcmp(aop->aopu.aop_str[offset],s))
1785                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1786                 break;
1787                 
1788         case AOP_ACC:
1789                 aop->coff = offset;
1790                 if (!offset && (strcmp(s,"acc") == 0))
1791                         break;
1792                 
1793                 if (strcmp(aop->aopu.aop_str[offset],s))
1794                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1795                 break;
1796                 
1797         default :
1798                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1799                         "aopPut got unsupported aop->type");
1800                 exit(0);
1801         }
1802         
1803 }
1804
1805 /*-----------------------------------------------------------------*/
1806 /* mov2w_op - generate either a MOVLW or MOVFW based operand type  */
1807 /*-----------------------------------------------------------------*/
1808 static void mov2w_op (operand *op, int offset)
1809 {
1810         assert (op);
1811         FENTRY;
1812
1813         /* for PO_IMMEDIATEs: use address or value? */
1814         if (op_isLitLike (op))
1815         {
1816                 /* access address of op */
1817                 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1818                 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1819                 {
1820                         if (offset == GPTRSIZE-1)
1821                                 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1822                         else
1823                                 emitpcode (POC_MOVLW, popGetLit (0));
1824                 }
1825                 else
1826                         emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1827         } else {
1828                 /* access value stored in op */
1829                 mov2w (AOP(op), offset);
1830         }
1831 }
1832
1833
1834 /*-----------------------------------------------------------------*/
1835 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1836 /*-----------------------------------------------------------------*/
1837 void mov2w (asmop *aop, int offset)
1838 {
1839         
1840         if(!aop)
1841                 return;
1842         
1843         DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1844         
1845         if ( aop_isLitLike (aop) )
1846                 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1847         else
1848                 emitpcode(POC_MOVFW,popGet(aop,offset));
1849         
1850 }
1851
1852 static void movwf (asmop *op, int offset)
1853 {
1854         emitpcode (POC_MOVWF, popGet(op, offset));
1855 }
1856
1857 static pCodeOp *get_argument_pcop (int idx)
1858 {
1859         assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1860         return popRegFromIdx (Gstack_base_addr - (idx - 1));
1861 }
1862
1863 static pCodeOp *get_return_val_pcop (int offset)
1864 {
1865         assert (offset > 0 && "the most significant byte is returned via WREG");
1866         return popRegFromIdx (Gstack_base_addr - (offset - 1));
1867 }
1868
1869 static void pass_argument (operand *op, int offset, int idx)
1870 {
1871         if (op)
1872                 mov2w_op (op, offset);
1873         if (idx != 0)
1874                 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1875 }
1876
1877 static void get_returnvalue (operand *op, int offset, int idx)
1878 {
1879         if (idx != 0)
1880                 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1881         movwf(AOP(op), offset);
1882 }
1883
1884 static void call_libraryfunc (char *name)
1885 {
1886   /* library code might reside in different page... */
1887   emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1888   /* call the library function */
1889   emitpcode (POC_CALL, popGetExternal (name));
1890   /* might return from different page... */
1891   emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1892 }
1893 #if 0
1894 /*-----------------------------------------------------------------*/
1895 /* reAdjustPreg - points a register back to where it should        */
1896 /*-----------------------------------------------------------------*/
1897 static void reAdjustPreg (asmop *aop)
1898 {
1899         int size ;
1900         
1901         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1902         aop->coff = 0;
1903         if ((size = aop->size) <= 1)
1904                 return ;
1905         size-- ;
1906         switch (aop->type) {
1907         case AOP_R0 :
1908         case AOP_R1 :
1909                 while (size--)
1910                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1911                 break;                  
1912         case AOP_DPTR :
1913         case AOP_DPTR2:
1914                 if (aop->type == AOP_DPTR2)
1915                 {
1916                         genSetDPTR(1);
1917                 } 
1918                 while (size--)
1919                 {
1920                         pic14_emitcode("lcall","__decdptr");
1921                 }
1922                 
1923                 if (aop->type == AOP_DPTR2)
1924                 {
1925                         genSetDPTR(0);
1926                 }
1927                 break;
1928                 
1929         }
1930         
1931 }
1932 #endif
1933
1934
1935 #if 0
1936 /*-----------------------------------------------------------------*/
1937 /* opIsGptr: returns non-zero if the passed operand is             */
1938 /* a generic pointer type.                                         */
1939 /*-----------------------------------------------------------------*/ 
1940 static int opIsGptr(operand *op)
1941 {
1942         sym_link *type = operandType(op);
1943         
1944         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1945         if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1946         {
1947                 return 1;
1948         }
1949         return 0;          
1950 }
1951 #endif
1952
1953 /*-----------------------------------------------------------------*/
1954 /* pic14_getDataSize - get the operand data size                   */
1955 /*-----------------------------------------------------------------*/
1956 int pic14_getDataSize(operand *op)
1957 {
1958         int size;
1959         
1960         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1961         
1962 #if 0
1963         size = getSize(OP_SYM_ETYPE(op));
1964         return size;
1965         //return AOP_SIZE(op);
1966         
1967         // tsd- in the pic port, the genptr size is 1, so this code here
1968         // fails. ( in the 8051 port, the size was 4).
1969 #else
1970         size = AOP_SIZE(op);
1971         if (IS_GENPTR(OP_SYM_TYPE(op)))
1972         {
1973                 sym_link *type = operandType(op);
1974                 if (IS_GENPTR(type))
1975                 {
1976                         /* generic pointer; arithmetic operations
1977                         * should ignore the high byte (pointer type).
1978                         */
1979                         size--;
1980                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1981                 }
1982         }
1983         return size;
1984 #endif
1985 }
1986
1987 /*-----------------------------------------------------------------*/
1988 /* pic14_outAcc - output Acc                                       */
1989 /*-----------------------------------------------------------------*/
1990 void pic14_outAcc(operand *result)
1991 {
1992         int size,offset;
1993         DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1994         DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1995         
1996         
1997         size = pic14_getDataSize(result);
1998         if(size){
1999                 emitpcode(POC_MOVWF,popGet(AOP(result),0));
2000                 size--;
2001                 offset = 1;
2002                 /* unsigned or positive */
2003                 while(size--)
2004                         emitpcode(POC_CLRF,popGet(AOP(result),offset++));
2005         }
2006         
2007 }
2008
2009 /*-----------------------------------------------------------------*/
2010 /* pic14_outBitC - output a bit C                                  */
2011 /*-----------------------------------------------------------------*/
2012 void pic14_outBitC(operand *result)
2013 {
2014         
2015         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2016         /* if the result is bit */
2017         if (AOP_TYPE(result) == AOP_CRY) 
2018                 aopPut(AOP(result),"c",0);
2019         else {
2020                 pic14_emitcode("clr","a  ; %d", __LINE__);
2021                 pic14_emitcode("rlc","a");
2022                 pic14_outAcc(result);
2023         }
2024 }
2025
2026 /*-----------------------------------------------------------------*/
2027 /* pic14_toBoolean - emit code for orl a,operator(sizeop)          */
2028 /*-----------------------------------------------------------------*/
2029 void pic14_toBoolean(operand *oper)
2030 {
2031         int size = AOP_SIZE(oper);
2032         int offset = 0;
2033         
2034         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2035
2036         assert (size > 0);
2037
2038         if (size == 1) {
2039                 /* MOVFW does not load the flags... */
2040                 if (AOP_TYPE(oper) == AOP_ACC) {
2041                         emitpcode(POC_IORLW, popGetLit(0));
2042                         offset = 1;
2043                 } else {
2044                         emitpcode(POC_MOVLW, popGetLit(0));
2045                         offset = 0;
2046                 }
2047         } else {
2048                 if ( AOP_TYPE(oper) != AOP_ACC) {
2049                         emitpcode(POC_MOVFW,popGet(AOP(oper),0));
2050                         offset = 1;
2051                 }
2052         }
2053         
2054         while (offset < size) {
2055                 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
2056         }
2057         /* Z is set iff (oper == 0) */
2058 }
2059
2060
2061 /*-----------------------------------------------------------------*/
2062 /* genNot - generate code for ! operation                          */
2063 /*-----------------------------------------------------------------*/
2064 static void genNot (iCode *ic)
2065 {
2066         //symbol *tlbl;
2067         int size;
2068
2069         FENTRY;
2070         
2071         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2072         /* assign asmOps to operand & result */
2073         aopOp (IC_LEFT(ic),ic,FALSE);
2074         aopOp (IC_RESULT(ic),ic,TRUE);
2075         
2076         DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2077         /* if in bit space then a special case */
2078         if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2079                 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2080                         emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2081                         emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2082                 } else {
2083                         emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2084                         emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2085                         emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2086                 }
2087                 goto release;
2088         }
2089         
2090         size = AOP_SIZE(IC_LEFT(ic));
2091         mov2w (AOP(IC_LEFT(ic)),0);
2092         while (--size > 0)
2093         {
2094           if (op_isLitLike (IC_LEFT(ic)))
2095             emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2096           else
2097             emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2098         }
2099         emitpcode(POC_MOVLW, popGetLit (0));
2100         emitSKPNZ;
2101         emitpcode(POC_MOVLW, popGetLit (1));
2102         movwf(AOP(IC_RESULT(ic)), 0);
2103
2104         for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2105         {
2106           emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2107         }
2108         goto release;
2109         
2110 release:        
2111         /* release the aops */
2112         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2113         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2114 }
2115
2116
2117 /*-----------------------------------------------------------------*/
2118 /* genCpl - generate code for complement                                                   */
2119 /*-----------------------------------------------------------------*/
2120 static void genCpl (iCode *ic)
2121 {
2122         operand *left, *result;
2123         int size, offset=0;  
2124         
2125         FENTRY;
2126         
2127         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2128         aopOp((left = IC_LEFT(ic)),ic,FALSE);
2129         aopOp((result=IC_RESULT(ic)),ic,TRUE);
2130         
2131         /* if both are in bit space then 
2132         a special case */
2133         if (AOP_TYPE(result) == AOP_CRY &&
2134                 AOP_TYPE(left) == AOP_CRY ) { 
2135                 
2136                 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir); 
2137                 pic14_emitcode("cpl","c"); 
2138                 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir); 
2139                 goto release; 
2140         } 
2141         
2142         size = AOP_SIZE(result);
2143         if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2144         while (size--) {
2145                 
2146                 if(AOP_TYPE(left) == AOP_ACC) 
2147                         emitpcode(POC_XORLW, popGetLit(0xff));
2148                 else
2149                         emitpcode(POC_COMFW,popGet(AOP(left),offset));
2150                 
2151                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2152                 offset++;
2153         }
2154         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2155         
2156         
2157 release:
2158         /* release the aops */
2159         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2160         freeAsmop(result,NULL,ic,TRUE);
2161 }
2162
2163 /*-----------------------------------------------------------------*/
2164 /* genUminusFloat - unary minus for floating points                        */
2165 /*-----------------------------------------------------------------*/
2166 static void genUminusFloat(operand *op,operand *result)
2167 {
2168         int size ,offset =0 ;
2169         char *l;
2170         
2171         FENTRY;
2172
2173         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2174         /* for this we just need to flip the 
2175         first it then copy the rest in place */
2176         size = AOP_SIZE(op) - 1;
2177         l = aopGet(AOP(op),3,FALSE,FALSE);
2178         
2179         MOVA(l);          
2180         
2181         pic14_emitcode("cpl","acc.7");
2182         aopPut(AOP(result),"a",3);      
2183         
2184         while(size--) {
2185                 aopPut(AOP(result),
2186                         aopGet(AOP(op),offset,FALSE,FALSE),
2187                         offset);
2188                 offset++;
2189         }                
2190 }
2191
2192 /*-----------------------------------------------------------------*/
2193 /* genUminus - unary minus code generation                                                 */
2194 /*-----------------------------------------------------------------*/
2195 static void genUminus (iCode *ic)
2196 {
2197         int size, i;
2198         sym_link *optype, *rtype;
2199         
2200         FENTRY;
2201         
2202         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2203         /* assign asmops */
2204         aopOp(IC_LEFT(ic),ic,FALSE);
2205         aopOp(IC_RESULT(ic),ic,TRUE);
2206         
2207         /* if both in bit space then special
2208         case */
2209         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2210                 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2211                 
2212                 emitpcode(POC_BCF,       popGet(AOP(IC_RESULT(ic)),0));
2213                 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2214                 emitpcode(POC_BSF,       popGet(AOP(IC_RESULT(ic)),0));
2215                 
2216                 goto release; 
2217         } 
2218         
2219         optype = operandType(IC_LEFT(ic));
2220         rtype = operandType(IC_RESULT(ic));
2221         
2222         /* if float then do float stuff */
2223         if (IS_FLOAT(optype)) {
2224                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2225                 goto release;
2226         }
2227         
2228         /* otherwise subtract from zero by taking the 2's complement */
2229         size = AOP_SIZE(IC_LEFT(ic));
2230         
2231         for(i=0; i<size; i++) {
2232                 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2233                         emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
2234                 else {
2235                         emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2236                         emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2237                 }
2238         }
2239         
2240         emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
2241         for(i=1; i<size; i++) {
2242                 emitSKPNZ;
2243                 emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
2244         }
2245         
2246 release:
2247         /* release the aops */
2248         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2249         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);  
2250 }
2251
2252 /*-----------------------------------------------------------------*/
2253 /* saveRegisters - will look for a call and save the registers     */
2254 /*-----------------------------------------------------------------*/
2255 static void saveRegisters(iCode *lic) 
2256 {
2257         int i;
2258         iCode *ic;
2259         bitVect *rsave;
2260         sym_link *dtype;
2261         
2262         FENTRY;
2263
2264         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2265         /* look for call */
2266         for (ic = lic ; ic ; ic = ic->next) 
2267                 if (ic->op == CALL || ic->op == PCALL)
2268                         break;
2269                 
2270                 if (!ic) {
2271                         fprintf(stderr,"found parameter push with no function call\n");
2272                         return ;
2273                 }
2274                 
2275                 /* if the registers have been saved already then
2276                 do nothing */
2277                 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2278                         return ;
2279                 
2280                         /* find the registers in use at this time 
2281                 and push them away to safety */
2282                 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2283                         ic->rUsed);
2284                 
2285                 ic->regsSaved = 1;
2286                 if (options.useXstack) {
2287                         if (bitVectBitValue(rsave,R0_IDX))
2288                                 pic14_emitcode("mov","b,r0");
2289                         pic14_emitcode("mov","r0,%s",spname);
2290                         for (i = 0 ; i < pic14_nRegs ; i++) {
2291                                 if (bitVectBitValue(rsave,i)) {
2292                                         if (i == R0_IDX)
2293                                                 pic14_emitcode("mov","a,b");
2294                                         else
2295                                                 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2296                                         pic14_emitcode("movx","@r0,a");
2297                                         pic14_emitcode("inc","r0");
2298                                 }
2299                         }
2300                         pic14_emitcode("mov","%s,r0",spname);
2301                         if (bitVectBitValue(rsave,R0_IDX))
2302                                 pic14_emitcode("mov","r0,b");     
2303                 }// else
2304                 //for (i = 0 ; i < pic14_nRegs ; i++) {
2305                 //        if (bitVectBitValue(rsave,i))
2306                 //      pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2307                 //}
2308                 
2309                 dtype = operandType(IC_LEFT(ic));
2310                 if (currFunc && dtype && 
2311                         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2312                         IFFUNC_ISISR(currFunc->type) &&
2313                         !ic->bankSaved) 
2314                         
2315                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2316                 
2317 }
2318 /*-----------------------------------------------------------------*/
2319 /* unsaveRegisters - pop the pushed registers                                      */
2320 /*-----------------------------------------------------------------*/
2321 static void unsaveRegisters (iCode *ic)
2322 {
2323         int i;
2324         bitVect *rsave;
2325         
2326         FENTRY;
2327
2328         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2329         /* find the registers in use at this time 
2330         and push them away to safety */
2331         rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2332                 ic->rUsed);
2333         
2334         if (options.useXstack) {
2335                 pic14_emitcode("mov","r0,%s",spname); 
2336                 for (i =  pic14_nRegs ; i >= 0 ; i--) {
2337                         if (bitVectBitValue(rsave,i)) {
2338                                 pic14_emitcode("dec","r0");
2339                                 pic14_emitcode("movx","a,@r0");
2340                                 if (i == R0_IDX)
2341                                         pic14_emitcode("mov","b,a");
2342                                 else
2343                                         pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2344                         }       
2345                         
2346                 }
2347                 pic14_emitcode("mov","%s,r0",spname);
2348                 if (bitVectBitValue(rsave,R0_IDX))
2349                         pic14_emitcode("mov","r0,b");
2350         } //else
2351         //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2352         //      if (bitVectBitValue(rsave,i))
2353         //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2354         //}
2355         
2356 }  
2357
2358
2359 /*-----------------------------------------------------------------*/
2360 /* pushSide -                            */
2361 /*-----------------------------------------------------------------*/
2362 static void pushSide(operand * oper, int size)
2363 {
2364 #if 0
2365         int offset = 0;
2366         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2367         while (size--) {
2368                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2369                 if (AOP_TYPE(oper) != AOP_REG &&
2370                         AOP_TYPE(oper) != AOP_DIR &&
2371                         strcmp(l,"a") ) {
2372                         pic14_emitcode("mov","a,%s",l);
2373                         pic14_emitcode("push","acc");
2374                 } else
2375                         pic14_emitcode("push","%s",l);
2376         }
2377 #endif
2378 }
2379
2380 /*-----------------------------------------------------------------*/
2381 /* assignResultValue -                           */
2382 /*-----------------------------------------------------------------*/
2383 static void assignResultValue(operand * oper)
2384 {
2385         int size = AOP_SIZE(oper);
2386         int offset = 0;
2387         
2388         FENTRY;
2389
2390         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2391         
2392         DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2393         
2394         /* assign MSB first (passed via WREG) */
2395         while (size--) {
2396                 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2397                 GpsuedoStkPtr++;
2398         }
2399 }
2400
2401
2402 /*-----------------------------------------------------------------*/
2403 /* genIpush - genrate code for pushing this gets a little complex  */
2404 /*-----------------------------------------------------------------*/
2405 static void genIpush (iCode *ic)
2406 {
2407         FENTRY;
2408         
2409         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2410 #if 0
2411         int size, offset = 0 ;
2412         char *l;
2413         
2414         
2415         /* if this is not a parm push : ie. it is spill push 
2416         and spill push is always done on the local stack */
2417         if (!ic->parmPush) {
2418                 
2419                 /* and the item is spilt then do nothing */
2420                 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2421                         return ;
2422                 
2423                 aopOp(IC_LEFT(ic),ic,FALSE);
2424                 size = AOP_SIZE(IC_LEFT(ic));
2425                 /* push it on the stack */
2426                 while(size--) {
2427                         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2428                         if (*l == '#') {
2429                                 MOVA(l);
2430                                 l = "acc";
2431                         }
2432                         pic14_emitcode("push","%s",l);
2433                 }
2434                 return ;                
2435         }
2436         
2437         /* this is a paramter push: in this case we call
2438         the routine to find the call and save those
2439         registers that need to be saved */   
2440         saveRegisters(ic);
2441         
2442         /* then do the push */
2443         aopOp(IC_LEFT(ic),ic,FALSE);
2444         
2445         
2446         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2447         size = AOP_SIZE(IC_LEFT(ic));
2448         
2449         while (size--) {
2450                 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2451                 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2452                         AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2453                         strcmp(l,"a") ) {
2454                         pic14_emitcode("mov","a,%s",l);
2455                         pic14_emitcode("push","acc");
2456                 } else
2457                         pic14_emitcode("push","%s",l);
2458         }         
2459         
2460         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2461 #endif
2462 }
2463
2464 /*-----------------------------------------------------------------*/
2465 /* genIpop - recover the registers: can happen only for spilling   */
2466 /*-----------------------------------------------------------------*/
2467 static void genIpop (iCode *ic)
2468 {
2469         FENTRY;
2470
2471         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2472         assert (!"genIpop -- unimplemented");
2473 #if 0
2474         int size,offset ;
2475         
2476         
2477         /* if the temp was not pushed then */
2478         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2479                 return ;
2480         
2481         aopOp(IC_LEFT(ic),ic,FALSE);
2482         size = AOP_SIZE(IC_LEFT(ic));
2483         offset = (size-1);
2484         while (size--) 
2485                 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2486                 FALSE,TRUE));
2487         
2488         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2489 #endif
2490 }
2491
2492 /*-----------------------------------------------------------------*/
2493 /* unsaverbank - restores the resgister bank from stack                    */
2494 /*-----------------------------------------------------------------*/
2495 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2496 {
2497         FENTRY;
2498
2499         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2500 #if 0
2501         int i;
2502         asmop *aop ;
2503         regs *r = NULL;
2504         
2505         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2506         if (popPsw) {
2507                 if (options.useXstack) {
2508                         aop = newAsmop(0);
2509                         r = getFreePtr(ic,&aop,FALSE);
2510                         
2511                         
2512                         pic14_emitcode("mov","%s,_spx",r->name);
2513                         pic14_emitcode("movx","a,@%s",r->name);
2514                         pic14_emitcode("mov","psw,a");
2515                         pic14_emitcode("dec","%s",r->name);
2516                         
2517                 }else
2518                         pic14_emitcode ("pop","psw");
2519         }
2520         
2521         for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2522                 if (options.useXstack) {           
2523                         pic14_emitcode("movx","a,@%s",r->name);
2524                         //pic14_emitcode("mov","(%s+%d),a",
2525                         //         regspic14[i].base,8*bank+regspic14[i].offset);
2526                         pic14_emitcode("dec","%s",r->name);
2527                         
2528                 } else 
2529                         pic14_emitcode("pop",""); //"(%s+%d)",
2530                 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2531         }
2532         
2533         if (options.useXstack) {
2534                 
2535                 pic14_emitcode("mov","_spx,%s",r->name);
2536                 freeAsmop(NULL,aop,ic,TRUE);
2537                 
2538         }
2539 #endif 
2540 }
2541
2542 /*-----------------------------------------------------------------*/
2543 /* saverbank - saves an entire register bank on the stack                  */
2544 /*-----------------------------------------------------------------*/
2545 static void saverbank (int bank, iCode *ic, bool pushPsw)
2546 {
2547         FENTRY;
2548
2549         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2550 #if 0
2551         int i;
2552         asmop *aop ;
2553         regs *r = NULL;
2554         
2555         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2556         if (options.useXstack) {
2557                 
2558                 aop = newAsmop(0);
2559                 r = getFreePtr(ic,&aop,FALSE);  
2560                 pic14_emitcode("mov","%s,_spx",r->name);
2561                 
2562         }
2563         
2564         for (i = 0 ; i < pic14_nRegs ;i++) {
2565                 if (options.useXstack) {
2566                         pic14_emitcode("inc","%s",r->name);
2567                         //pic14_emitcode("mov","a,(%s+%d)",
2568                         //               regspic14[i].base,8*bank+regspic14[i].offset);
2569                         pic14_emitcode("movx","@%s,a",r->name);                 
2570                 } else 
2571                         pic14_emitcode("push","");// "(%s+%d)",
2572                 //regspic14[i].base,8*bank+regspic14[i].offset);
2573         }
2574         
2575         if (pushPsw) {
2576                 if (options.useXstack) {
2577                         pic14_emitcode("mov","a,psw");
2578                         pic14_emitcode("movx","@%s,a",r->name); 
2579                         pic14_emitcode("inc","%s",r->name);
2580                         pic14_emitcode("mov","_spx,%s",r->name);                 
2581                         freeAsmop (NULL,aop,ic,TRUE);
2582                         
2583                 } else
2584                         pic14_emitcode("push","psw");
2585                 
2586                 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2587         }
2588         ic->bankSaved = 1;
2589 #endif
2590 }
2591
2592 /*-----------------------------------------------------------------*/
2593 /* genCall - generates a call statement                                                    */
2594 /*-----------------------------------------------------------------*/
2595 static void genCall (iCode *ic)
2596 {
2597         sym_link *dtype;         
2598         symbol *sym;
2599         unsigned char *name;
2600         int isExtern;
2601         
2602         FENTRY;
2603
2604         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2605         
2606         /* if caller saves & we have not saved then */
2607         if (!ic->regsSaved)
2608                 saveRegisters(ic);
2609         
2610                 /* if we are calling a function that is not using
2611                 the same register bank then we need to save the
2612         destination registers on the stack */
2613         dtype = operandType(IC_LEFT(ic));
2614         if (currFunc && dtype && 
2615                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2616                 IFFUNC_ISISR(currFunc->type) &&
2617                 !ic->bankSaved) 
2618                 
2619                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2620         
2621         /* if send set is not empty the assign */
2622         if (_G.sendSet) {
2623                 iCode *sic;
2624                 /* For the Pic port, there is no data stack.
2625                 * So parameters passed to functions are stored
2626                 * in registers. (The pCode optimizer will get
2627                 * rid of most of these :).
2628                 */
2629                 int psuedoStkPtr=-1;
2630                 int firstTimeThruLoop = 1;
2631                 
2632                 _G.sendSet = reverseSet(_G.sendSet);
2633                 
2634                 /* First figure how many parameters are getting passed */
2635                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2636                 sic = setNextItem(_G.sendSet)) {
2637                         
2638                         aopOp(IC_LEFT(sic),sic,FALSE);
2639                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2640                         freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2641                 }
2642                 
2643                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2644                 sic = setNextItem(_G.sendSet)) {
2645                         int size, offset = 0;
2646                         
2647                         aopOp(IC_LEFT(sic),sic,FALSE);
2648                         size = AOP_SIZE(IC_LEFT(sic));
2649                         
2650                         while (size--) {
2651                                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2652                                         AopType(AOP_TYPE(IC_LEFT(sic))));
2653                                 
2654                                 if(!firstTimeThruLoop) {
2655                                         /* If this is not the first time we've been through the loop
2656                                         * then we need to save the parameter in a temporary
2657                                         * register. The last byte of the last parameter is
2658                                         * passed in W. */
2659                                         emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2660                                         
2661                                 }
2662                                 firstTimeThruLoop=0;
2663                                 
2664                                 mov2w_op (IC_LEFT(sic),  offset);
2665                                 offset++;
2666                         }
2667                         freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2668                 }
2669                 _G.sendSet = NULL;
2670         }
2671         /* make the call */
2672         sym = OP_SYMBOL(IC_LEFT(ic));
2673         name = sym->rname[0] ? sym->rname : sym->name;
2674         isExtern = IS_EXTERN(sym->etype);
2675         if (isExtern) {
2676                 emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2677         }
2678         emitpcode(POC_CALL,popGetWithString(name,isExtern));
2679         if (isExtern) {
2680                 emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel to restore PCLATH before next goto or call instruction */
2681         }
2682         GpsuedoStkPtr=0;
2683         /* if we need assign a result value */
2684         if ((IS_ITEMP(IC_RESULT(ic)) && 
2685                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2686                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2687                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2688                 
2689                 _G.accInUse++;
2690                 aopOp(IC_RESULT(ic),ic,FALSE);
2691                 _G.accInUse--;
2692                 
2693                 assignResultValue(IC_RESULT(ic));
2694                 
2695                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2696                         AopType(AOP_TYPE(IC_RESULT(ic))));
2697                 
2698                 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2699         }
2700         
2701         /* if register bank was saved then pop them */
2702         if (ic->bankSaved)
2703                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2704         
2705         /* if we hade saved some registers then unsave them */
2706         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2707                 unsaveRegisters (ic);
2708         
2709         
2710 }
2711
2712 /*-----------------------------------------------------------------*/
2713 /* genPcall - generates a call by pointer statement                        */
2714 /*-----------------------------------------------------------------*/
2715 static void genPcall (iCode *ic)
2716 {
2717         sym_link *dtype;
2718         symbol *albl = newiTempLabel(NULL);
2719         symbol *blbl = newiTempLabel(NULL);
2720         PIC_OPCODE poc;
2721         pCodeOp *pcop;
2722         operand *left;
2723         
2724         FENTRY;
2725
2726         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2727         /* if caller saves & we have not saved then */
2728         if (!ic->regsSaved)
2729                 saveRegisters(ic);
2730         
2731                 /* if we are calling a function that is not using
2732                 the same register bank then we need to save the
2733         destination registers on the stack */
2734         dtype = operandType(IC_LEFT(ic));
2735         if (currFunc && dtype && 
2736                 IFFUNC_ISISR(currFunc->type) &&
2737                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2738                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2739         
2740         left = IC_LEFT(ic);
2741         aopOp(left,ic,FALSE);
2742         DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2743         
2744         poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2745         
2746         pushSide(IC_LEFT(ic), FPTRSIZE);
2747         
2748         /* if send set is not empty, assign parameters */
2749         if (_G.sendSet) {
2750                 
2751                 DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2752                 /* no way to pass args - W always gets used to make the call */
2753         }
2754         /* first idea - factor out a common helper function and call it.
2755         But don't know how to get it generated only once in its own block
2756         
2757         if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2758                 char *rname;
2759                 char *buffer;
2760                 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2761                 DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2762                 buffer = Safe_calloc(1,strlen(rname)+16);
2763                 sprintf(buffer, "%s_goto_helper", rname);
2764                 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2765                 free(buffer);
2766         }
2767         */
2768         emitpcode(POC_CALL,popGetLabel(albl->key));
2769         pcop = popGetLabel(blbl->key);
2770         emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2771         emitpcode(POC_GOTO,pcop);
2772         emitpLabel(albl->key);
2773         
2774         emitpcode(poc,popGetAddr(AOP(left),1,0));
2775         emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2776         emitpcode(poc,popGetAddr(AOP(left),0,0));
2777         emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2778         
2779         emitpLabel(blbl->key);
2780         
2781         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2782         
2783         /* if we need to assign a result value */
2784         if ((IS_ITEMP(IC_RESULT(ic)) &&
2785                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2786                 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2787                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2788                 
2789                 _G.accInUse++;
2790                 aopOp(IC_RESULT(ic),ic,FALSE);
2791                 _G.accInUse--;
2792
2793                 GpsuedoStkPtr = 0;
2794                 
2795                 assignResultValue(IC_RESULT(ic));
2796                 
2797                 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2798         }
2799         
2800         /* if register bank was saved then unsave them */
2801         if (currFunc && dtype && 
2802                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2803                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2804         
2805                 /* if we hade saved some registers then
2806         unsave them */
2807         if (ic->regsSaved)
2808                 unsaveRegisters (ic);
2809         
2810 }
2811
2812 /*-----------------------------------------------------------------*/
2813 /* resultRemat - result  is rematerializable                                       */
2814 /*-----------------------------------------------------------------*/
2815 static int resultRemat (iCode *ic)
2816 {
2817         //      DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2818         FENTRY;
2819
2820         if (SKIP_IC(ic) || ic->op == IFX)
2821                 return 0;
2822         
2823         if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2824                 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2825                 if (sym->remat && !POINTER_SET(ic)) 
2826                         return 1;
2827         }
2828         
2829         return 0;
2830 }
2831
2832 #if defined(__BORLANDC__) || defined(_MSC_VER)
2833 #define STRCASECMP stricmp
2834 #else
2835 #define STRCASECMP strcasecmp
2836 #endif
2837
2838 #if 0
2839 /*-----------------------------------------------------------------*/
2840 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2841 /*-----------------------------------------------------------------*/
2842 static bool inExcludeList(char *s)
2843 {
2844         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2845         int i =0;
2846         
2847         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2848         if (options.excludeRegs[i] &&
2849                 STRCASECMP(options.excludeRegs[i],"none") == 0)
2850                 return FALSE ;
2851         
2852         for ( i = 0 ; options.excludeRegs[i]; i++) {
2853                 if (options.excludeRegs[i] &&
2854                         STRCASECMP(s,options.excludeRegs[i]) == 0)
2855                         return TRUE;
2856         }
2857         return FALSE ;
2858 }
2859 #endif
2860
2861 /*-----------------------------------------------------------------*/
2862 /* genFunction - generated code for function entry                                 */
2863 /*-----------------------------------------------------------------*/
2864 static void genFunction (iCode *ic)
2865 {
2866         symbol *sym;
2867         sym_link *ftype;
2868         
2869         FENTRY;
2870
2871         DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2872         
2873         labelOffset += (max_key+4);
2874         max_key=0;
2875         GpsuedoStkPtr=0;
2876         _G.nRegsSaved = 0;
2877         /* create the function header */
2878         pic14_emitcode(";","-----------------------------------------");
2879         pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2880         pic14_emitcode(";","-----------------------------------------");
2881         
2882         pic14_emitcode("","%s:",sym->rname);
2883         addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2884         
2885         ftype = operandType(IC_LEFT(ic));
2886         
2887         /* if critical function then turn interrupts off */
2888         if (IFFUNC_ISCRITICAL(ftype))
2889                 pic14_emitcode("clr","ea");
2890         
2891                 /* here we need to generate the equates for the
2892         register bank if required */
2893 #if 0
2894         if (FUNC_REGBANK(ftype) != rbank) {
2895                 int i ;
2896                 
2897                 rbank = FUNC_REGBANK(ftype);
2898                 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2899                         if (strcmp(regspic14[i].base,"0") == 0)
2900                                 pic14_emitcode("","%s = 0x%02x",
2901                                 regspic14[i].dname,
2902                                 8*rbank+regspic14[i].offset);
2903                         else
2904                                 pic14_emitcode ("","%s = %s + 0x%02x",
2905                                 regspic14[i].dname,
2906                                 regspic14[i].base,
2907                                 8*rbank+regspic14[i].offset);
2908                 }
2909         }
2910 #endif
2911         
2912         /* if this is an interrupt service routine */
2913         if (IFFUNC_ISISR(sym->type)) {
2914         /*  already done in pic14createInterruptVect() - delete me
2915         addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2916         emitpcodeNULLop(POC_NOP);
2917         emitpcodeNULLop(POC_NOP);
2918         emitpcodeNULLop(POC_NOP);
2919                 */
2920                 emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2921                 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2922                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2923                 emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2924                 emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2925                 emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2926                 emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2927                 
2928                 pBlockConvert2ISR(pb);
2929                 pic14_hasInterrupt = 1;
2930 #if 0  
2931                 if (!inExcludeList("acc"))              
2932                         pic14_emitcode ("push","acc");  
2933                 if (!inExcludeList("b"))
2934                         pic14_emitcode ("push","b");
2935                 if (!inExcludeList("dpl"))
2936                         pic14_emitcode ("push","dpl");
2937                 if (!inExcludeList("dph"))
2938                         pic14_emitcode ("push","dph");
2939                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2940                 {
2941                         pic14_emitcode ("push", "dpx");
2942                         /* Make sure we're using standard DPTR */
2943                         pic14_emitcode ("push", "dps");
2944                         pic14_emitcode ("mov", "dps, #0x00");
2945                         if (options.stack10bit)
2946                         { 
2947                                 /* This ISR could conceivably use DPTR2. Better save it. */
2948                                 pic14_emitcode ("push", "dpl1");
2949                                 pic14_emitcode ("push", "dph1");
2950                                 pic14_emitcode ("push", "dpx1");
2951                         }
2952                 }
2953                 /* if this isr has no bank i.e. is going to
2954                 run with bank 0 , then we need to save more
2955                 registers :-) */
2956                 if (!FUNC_REGBANK(sym->type)) {
2957                         
2958                 /* if this function does not call any other
2959                 function then we can be economical and
2960                         save only those registers that are used */
2961                         if (! IFFUNC_HASFCALL(sym->type)) {
2962                                 int i;
2963                                 
2964                                 /* if any registers used */
2965                                 if (sym->regsUsed) {
2966                                         /* save the registers used */
2967                                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2968                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2969                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2970                                                         pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);               
2971                                         }
2972                                 }
2973                                 
2974                         } else {
2975                         /* this function has    a function call cannot
2976                         determines register usage so we will have the
2977                                 entire bank */
2978                                 saverbank(0,ic,FALSE);
2979                         }       
2980                 }
2981 #endif
2982         } else {
2983         /* if callee-save to be used for this function
2984                 then save the registers being used in this function */
2985                 if (IFFUNC_CALLEESAVES(sym->type)) {
2986                         int i;
2987                         
2988                         /* if any registers used */
2989                         if (sym->regsUsed) {
2990                                 /* save the registers used */
2991                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2992                                         if (bitVectBitValue(sym->regsUsed,i) ||
2993                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2994                                                 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2995                                                 _G.nRegsSaved++;
2996                                         }
2997                                 }
2998                         }
2999                 }
3000         }
3001         
3002         /* set the register bank to the desired value */
3003         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
3004                 pic14_emitcode("push","psw");
3005                 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);       
3006         }
3007         
3008         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3009                 
3010                 if (options.useXstack) {
3011                         pic14_emitcode("mov","r0,%s",spname);
3012                         pic14_emitcode("mov","a,_bp");
3013                         pic14_emitcode("movx","@r0,a");
3014                         pic14_emitcode("inc","%s",spname);
3015                 }
3016                 else
3017                 {
3018                         /* set up the stack */
3019                         pic14_emitcode ("push","_bp");   /* save the callers stack      */
3020                 }
3021                 pic14_emitcode ("mov","_bp,%s",spname);
3022         }
3023         
3024         /* adjust the stack for the function */
3025         if (sym->stack) {
3026                 
3027                 int i = sym->stack;
3028                 if (i > 256 ) 
3029                         werror(W_STACK_OVERFLOW,sym->name);
3030                 
3031                 if (i > 3 && sym->recvSize < 4) {                
3032                         
3033                         pic14_emitcode ("mov","a,sp");
3034                         pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3035                         pic14_emitcode ("mov","sp,a");
3036                         
3037                 }
3038                 else
3039                         while(i--)
3040                                 pic14_emitcode("inc","sp");
3041         }
3042         
3043         if (sym->xstack) {
3044                 
3045                 pic14_emitcode ("mov","a,_spx");
3046                 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3047                 pic14_emitcode ("mov","_spx,a");
3048         }
3049         
3050 }
3051
3052 /*-----------------------------------------------------------------*/
3053 /* genEndFunction - generates epilogue for functions                       */
3054 /*-----------------------------------------------------------------*/
3055 static void genEndFunction (iCode *ic)
3056 {
3057         symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3058         
3059         FENTRY;
3060
3061         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3062         
3063         if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3064         {
3065                 pic14_emitcode ("mov","%s,_bp",spname);
3066         }
3067         
3068         /* if use external stack but some variables were
3069         added to the local stack then decrement the
3070         local stack */
3071         if (options.useXstack && sym->stack) {    
3072                 pic14_emitcode("mov","a,sp");
3073                 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3074                 pic14_emitcode("mov","sp,a");
3075         }
3076         
3077         
3078         if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3079                 if (options.useXstack) {
3080                         pic14_emitcode("mov","r0,%s",spname);
3081                         pic14_emitcode("movx","a,@r0");
3082                         pic14_emitcode("mov","_bp,a");
3083                         pic14_emitcode("dec","%s",spname);
3084                 }
3085                 else
3086                 {
3087                         pic14_emitcode ("pop","_bp");
3088                 }
3089         }
3090         
3091         /* restore the register bank    */        
3092         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3093                 pic14_emitcode ("pop","psw");
3094         
3095         if (IFFUNC_ISISR(sym->type)) {
3096                 
3097                 /* now we need to restore the registers */
3098                 /* if this isr has no bank i.e. is going to
3099                 run with bank 0 , then we need to save more
3100 registers :-) */
3101                 if (!FUNC_REGBANK(sym->type)) {
3102                         
3103                 /* if this function does not call any other
3104                 function then we can be economical and
3105                         save only those registers that are used */
3106                         if (! IFFUNC_HASFCALL(sym->type)) {
3107                                 int i;
3108                                 
3109                                 /* if any registers used */
3110                                 if (sym->regsUsed) {
3111                                         /* save the registers used */
3112                                         for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3113                                                 if (bitVectBitValue(sym->regsUsed,i) ||
3114                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3115                                                         pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3116                                         }
3117                                 }
3118                                 
3119                         } else {
3120                         /* this function has    a function call cannot
3121                         determines register usage so we will have the
3122                                 entire bank */
3123                                 unsaverbank(0,ic,FALSE);
3124                         }       
3125                 }
3126 #if 0
3127                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3128                 {
3129                         if (options.stack10bit)
3130                         {
3131                                 pic14_emitcode ("pop", "dpx1");
3132                                 pic14_emitcode ("pop", "dph1");
3133                                 pic14_emitcode ("pop", "dpl1");
3134                         } 
3135                         pic14_emitcode ("pop", "dps");
3136                         pic14_emitcode ("pop", "dpx");
3137                 }
3138                 if (!inExcludeList("dph"))
3139                         pic14_emitcode ("pop","dph");
3140                 if (!inExcludeList("dpl"))
3141                         pic14_emitcode ("pop","dpl");
3142                 if (!inExcludeList("b"))
3143                         pic14_emitcode ("pop","b");
3144                 if (!inExcludeList("acc"))
3145                         pic14_emitcode ("pop","acc");
3146                 
3147                 if (IFFUNC_ISCRITICAL(sym->type))
3148                         pic14_emitcode("setb","ea");
3149 #endif
3150                 
3151                 /* if debug then send end of function */
3152                 /*      if (options.debug && currFunc) { */
3153                 if (currFunc) {
3154                         debugFile->writeEndFunction (currFunc, ic, 1);
3155                 }
3156                 
3157                 pic14_emitcode ("reti","");
3158                 emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
3159                 emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
3160                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
3161                 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3162                 emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
3163                 emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
3164                 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3165                 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3166                 emitpcodeNULLop(POC_RETFIE);
3167         }
3168         else {
3169                 if (IFFUNC_ISCRITICAL(sym->type))
3170                         pic14_emitcode("setb","ea");
3171                 
3172                 if (IFFUNC_CALLEESAVES(sym->type)) {
3173                         int i;
3174                         
3175                         /* if any registers used */
3176                         if (sym->regsUsed) {
3177                                 /* save the registers used */
3178                                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3179                                         if (bitVectBitValue(sym->regsUsed,i) ||
3180                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3181                                                 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3182                                 }
3183                         }
3184                         
3185                 }
3186                 
3187                 /* if debug then send end of function */
3188                 if (currFunc) {
3189                         debugFile->writeEndFunction (currFunc, ic, 1);
3190                 }
3191                 
3192                 pic14_emitcode ("return","");
3193                 emitpcodeNULLop(POC_RETURN);
3194                 
3195                 /* Mark the end of a function */
3196                 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3197         }
3198         
3199 }
3200
3201 /*-----------------------------------------------------------------*/
3202 /* genRet - generate code for return statement                                     */
3203 /*-----------------------------------------------------------------*/
3204 static void genRet (iCode *ic)
3205 {
3206         int size,offset = 0;
3207         
3208         FENTRY;
3209
3210         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3211         /* if we have no return value then
3212         just generate the "ret" */
3213         if (!IC_LEFT(ic)) 
3214                 goto jumpret;           
3215         
3216                 /* we have something to return then
3217         move the return value into place */
3218         aopOp(IC_LEFT(ic),ic,FALSE);
3219         size = AOP_SIZE(IC_LEFT(ic));
3220
3221         for (offset = 0; offset < size; offset++)
3222         {
3223                 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3224         }
3225         
3226         freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3227         
3228 jumpret:
3229         /* generate a jump to the return label
3230         if the next is not the return statement */
3231         if (!(ic->next && ic->next->op == LABEL &&
3232                 IC_LABEL(ic->next) == returnLabel)) {
3233                 
3234                 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3235         }
3236         
3237 }
3238
3239 /*-----------------------------------------------------------------*/
3240 /* genLabel - generates a label                                                                    */
3241 /*-----------------------------------------------------------------*/
3242 static void genLabel (iCode *ic)
3243 {
3244         FENTRY;
3245
3246         /* special case never generate */
3247         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3248         if (IC_LABEL(ic) == entryLabel)
3249                 return ;
3250         
3251         emitpLabel(IC_LABEL(ic)->key);
3252         pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3253 }
3254
3255 /*-----------------------------------------------------------------*/
3256 /* genGoto - generates a goto                                                                      */
3257 /*-----------------------------------------------------------------*/
3258 //tsd
3259 static void genGoto (iCode *ic)
3260 {
3261         FENTRY;
3262
3263         emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3264         pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3265 }
3266
3267
3268 /*-----------------------------------------------------------------*/
3269 /* genMultbits :- multiplication of bits                                                   */
3270 /*-----------------------------------------------------------------*/
3271 static void genMultbits (operand *left, 
3272                                                  operand *right, 
3273                                                  operand *result)
3274 {
3275         FENTRY;
3276         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3277         
3278         if(!pic14_sameRegs(AOP(result),AOP(right)))
3279                 emitpcode(POC_BSF,      popGet(AOP(result),0));
3280         
3281         emitpcode(POC_BTFSC,popGet(AOP(right),0));
3282         emitpcode(POC_BTFSS,popGet(AOP(left),0));
3283         emitpcode(POC_BCF,  popGet(AOP(result),0));
3284         
3285 }
3286
3287
3288 /*-----------------------------------------------------------------*/
3289 /* genMultOneByte : 8 bit multiplication & division                        */
3290 /*-----------------------------------------------------------------*/
3291 static void genMultOneByte (operand *left,
3292                                                         operand *right,
3293                                                         operand *result)
3294 {
3295         char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3296         
3297         // symbol *lbl ;
3298         int size,offset,i;
3299         
3300         
3301         FENTRY;
3302         
3303         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3304         DEBUGpic14_AopType(__LINE__,left,right,result);
3305         DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3306         
3307         /* (if two literals, the value is computed before) */
3308         /* if one literal, literal on the right */
3309         if (AOP_TYPE(left) == AOP_LIT){
3310                 operand *t = right;
3311                 right = left;
3312                 left = t;
3313         }
3314
3315         assert (AOP_SIZE(left) == AOP_SIZE(right));
3316         
3317         size = min(AOP_SIZE(result),AOP_SIZE(left));
3318         offset = Gstack_base_addr - (2*size - 1);
3319
3320         /* pass right operand as argument */
3321         for (i=0; i < size; i++)
3322         {
3323                 mov2w (AOP(right), i);
3324                 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3325         } // for
3326         
3327         /* pass left operand as argument */
3328         for (i=0; i < size; i++)
3329         {
3330                 mov2w (AOP(left), i);
3331                 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3332         } // for
3333         assert (offset == Gstack_base_addr);
3334         
3335         /* call library routine */
3336         assert (size > 0 && size <= 4);
3337         call_libraryfunc (func[size]);
3338         
3339         /* assign result */
3340         movwf (AOP(result), size-1);
3341         for (i=0; i < size - 1; i++)
3342         {
3343                 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3344                 movwf (AOP(result), size - 2 - i);
3345         } // for
3346
3347         /* now (zero-/sign) extend the result to its size */
3348         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3349 }
3350
3351 /*-----------------------------------------------------------------*/
3352 /* genMult - generates code for multiplication                                     */
3353 /*-----------------------------------------------------------------*/
3354 static void genMult (iCode *ic)
3355 {
3356         operand *left = IC_LEFT(ic);
3357         operand *right = IC_RIGHT(ic);
3358         operand *result= IC_RESULT(ic); 
3359         
3360         FENTRY;
3361
3362         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3363         /* assign the amsops */
3364         aopOp (left,ic,FALSE);
3365         aopOp (right,ic,FALSE);
3366         aopOp (result,ic,TRUE);
3367         
3368         DEBUGpic14_AopType(__LINE__,left,right,result);
3369         
3370         /* special cases first */
3371         /* both are bits */
3372         if (AOP_TYPE(left) == AOP_CRY &&
3373                 AOP_TYPE(right)== AOP_CRY) {
3374                 genMultbits(left,right,result);
3375                 goto release ;
3376         }
3377         
3378         /* if both are of size == 1 */
3379         if (AOP_SIZE(left) == 1 &&
3380                 AOP_SIZE(right) == 1 ) {
3381                 genMultOneByte(left,right,result);
3382                 goto release ;
3383         }
3384         
3385         /* should have been converted to function call */
3386         assert(0) ;
3387         
3388 release :
3389         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3390         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3391         freeAsmop(result,NULL,ic,TRUE); 
3392 }
3393
3394 /*-----------------------------------------------------------------*/
3395 /* genDivbits :- division of bits                                                                  */
3396 /*-----------------------------------------------------------------*/
3397 static void genDivbits (operand *left, 
3398                                                 operand *right, 
3399                                                 operand *result)
3400 {
3401         
3402         char *l;
3403         
3404         FENTRY;
3405
3406         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3407         /* the result must be bit */      
3408         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3409         l = aopGet(AOP(left),0,FALSE,FALSE);
3410         
3411         MOVA(l);          
3412         
3413         pic14_emitcode("div","ab");
3414         pic14_emitcode("rrc","a");
3415         aopPut(AOP(result),"c",0);
3416 }
3417
3418 /*-----------------------------------------------------------------*/
3419 /* genDivOneByte : 8 bit division                                                                  */
3420 /*-----------------------------------------------------------------*/
3421 static void genDivOneByte (operand *left,
3422                                                    operand *right,
3423                                                    operand *result)
3424 {
3425         int size;
3426         
3427         FENTRY;
3428         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3429         
3430         assert (AOP_SIZE(result) == 1);
3431         assert (AOP_SIZE(right) == 1);
3432         assert (AOP_SIZE(left) == 1);
3433
3434         size = min(AOP_SIZE(result),AOP_SIZE(left));
3435
3436         if (AOP_TYPE(right) == AOP_LIT)
3437         {
3438                 /* XXX: might add specialized code */
3439         }
3440
3441         if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3442         {
3443                 /* unsigned division */
3444         #if 1
3445                 mov2w(AOP(right),0);
3446                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3447                 mov2w(AOP(left),0);
3448                 call_libraryfunc("__divuchar");
3449                 movwf(AOP(result),0);
3450         #else
3451                 pCodeOp *temp;
3452                 symbol *lbl;
3453
3454                 temp = popGetTempReg();
3455                 lbl = newiTempLabel(NULL);
3456                 
3457                 /* XXX: improve this naive approach:
3458                    [result] = [a] / [b]
3459                         ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3460
3461                    In PIC assembler:
3462                    movf  left,W
3463                    movwf temp           // temp <-- left
3464                    movf  right,W        // W <-- right
3465                    clrf  result
3466                    label1:
3467                    incf  result
3468                    subwf temp,F         // temp <-- temp - W
3469                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if temp < W
3470                    goto  label1
3471                    decf result          // we just subtract once too often
3472                  */
3473
3474                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3475                 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3476                 
3477                 mov2w(AOP(left),0);
3478                 emitpcode(POC_MOVWF, temp);
3479                 mov2w(AOP(right),0);
3480                 emitpcode(POC_CLRF, popGet(AOP(result),0));
3481
3482                 emitpLabel(lbl->key);
3483                 emitpcode(POC_INCF, popGet(AOP(result),0));
3484                 emitpcode(POC_SUBWF, temp);
3485                 emitSKPNC;
3486                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3487                 emitpcode(POC_DECF, popGet(AOP(result),0));
3488         #endif
3489         }
3490         else
3491         {
3492                 /* signed division */
3493                 mov2w(AOP(right),0);
3494                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3495                 mov2w(AOP(left),0);
3496                 call_libraryfunc("__divschar");
3497                 movwf(AOP(result),0);
3498         }
3499
3500         /* now performed the signed/unsigned division -- extend result */
3501         addSign(result, 1, !SPEC_USIGN(operandType(result)));
3502 }
3503
3504 /*-----------------------------------------------------------------*/
3505 /* genDiv - generates code for division                            */
3506 /*-----------------------------------------------------------------*/
3507 static void genDiv (iCode *ic)
3508 {
3509         operand *left = IC_LEFT(ic);
3510         operand *right = IC_RIGHT(ic);
3511         operand *result= IC_RESULT(ic); 
3512         
3513         FENTRY;
3514         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3515         /* assign the amsops */
3516         aopOp (left,ic,FALSE);
3517         aopOp (right,ic,FALSE);
3518         aopOp (result,ic,TRUE);
3519         
3520         /* special cases first */
3521         /* both are bits */
3522         if (AOP_TYPE(left) == AOP_CRY &&
3523                 AOP_TYPE(right)== AOP_CRY) {
3524                 genDivbits(left,right,result);
3525                 goto release ;
3526         }
3527         
3528         /* if both are of size == 1 */
3529         if (AOP_SIZE(left) == 1 &&
3530                 AOP_SIZE(right) == 1 ) {
3531                 genDivOneByte(left,right,result);
3532                 goto release ;
3533         }
3534         
3535         /* should have been converted to function call */
3536         assert(0);
3537 release :
3538         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3539         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3540         freeAsmop(result,NULL,ic,TRUE); 
3541 }
3542
3543 /*-----------------------------------------------------------------*/
3544 /* genModbits :- modulus of bits                                                                   */
3545 /*-----------------------------------------------------------------*/
3546 static void genModbits (operand *left, 
3547                                                 operand *right, 
3548                                                 operand *result)
3549 {
3550         
3551         char *l;
3552         
3553         FENTRY;
3554         /* the result must be bit */      
3555         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3556         l = aopGet(AOP(left),0,FALSE,FALSE);
3557         
3558         MOVA(l);
3559         
3560         pic14_emitcode("div","ab");
3561         pic14_emitcode("mov","a,b");
3562         pic14_emitcode("rrc","a");
3563         aopPut(AOP(result),"c",0);
3564 }
3565
3566 /*-----------------------------------------------------------------*/
3567 /* genModOneByte : 8 bit modulus                                                                   */
3568 /*-----------------------------------------------------------------*/
3569 static void genModOneByte (operand *left,
3570                                                    operand *right,
3571                                                    operand *result)
3572 {
3573         int size;
3574         
3575         FENTRY;
3576         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3577         
3578         assert (AOP_SIZE(result) == 1);
3579         assert (AOP_SIZE(right) == 1);
3580         assert (AOP_SIZE(left) == 1);
3581
3582         size = min(AOP_SIZE(result),AOP_SIZE(left));
3583
3584         if (AOP_TYPE(right) == AOP_LIT)
3585         {
3586                 /* XXX: might add specialized code */
3587         }
3588
3589         if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3590         {
3591                 /* unsigned division */
3592         #if 1
3593                 mov2w(AOP(right),0);
3594                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3595                 mov2w(AOP(left),0);
3596                 call_libraryfunc("__moduchar");
3597                 movwf(AOP(result),0);
3598         #else
3599                 pCodeOp *temp;
3600                 symbol *lbl;
3601
3602                 lbl = newiTempLabel(NULL);
3603                 
3604                 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3605
3606                 /* XXX: improve this naive approach:
3607                    [result] = [a] % [b]
3608                         ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3609
3610                    In PIC assembler:
3611                    movf  left,W
3612                    movwf result         // result <-- left
3613                    movf  right,W        // W <-- right
3614                    label1:
3615                    subwf result,F       // result <-- result - W
3616                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if result < W
3617                    goto  label1
3618                    addwf result, F      // we just subtract once too often
3619                  */
3620
3621                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3622                 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3623                 
3624                 if (!pic14_sameRegs(AOP(left), AOP(result)))
3625                 {
3626                         mov2w(AOP(left),0);
3627                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
3628                 }
3629                 mov2w(AOP(right),0);
3630
3631                 emitpLabel(lbl->key);
3632                 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3633                 emitSKPNC;
3634                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3635                 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3636         #endif
3637         }
3638         else
3639         {
3640                 /* signed division */
3641                 mov2w(AOP(right),0);
3642                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3643                 mov2w(AOP(left),0);
3644                 call_libraryfunc("__modschar");
3645                 movwf(AOP(result),0);
3646         }
3647
3648         /* now we performed the signed/unsigned modulus -- extend result */
3649         addSign(result, 1, !SPEC_USIGN(operandType(result)));
3650 }
3651
3652 /*-----------------------------------------------------------------*/
3653 /* genMod - generates code for division                                                    */
3654 /*-----------------------------------------------------------------*/
3655 static void genMod (iCode *ic)
3656 {
3657         operand *left = IC_LEFT(ic);
3658         operand *right = IC_RIGHT(ic);
3659         operand *result= IC_RESULT(ic);  
3660         
3661         FENTRY;
3662         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3663         /* assign the amsops */
3664         aopOp (left,ic,FALSE);
3665         aopOp (right,ic,FALSE);
3666         aopOp (result,ic,TRUE);
3667         
3668         /* special cases first */
3669         /* both are bits */
3670         if (AOP_TYPE(left) == AOP_CRY &&
3671                 AOP_TYPE(right)== AOP_CRY) {
3672                 genModbits(left,right,result);
3673                 goto release ;
3674         }
3675         
3676         /* if both are of size == 1 */
3677         if (AOP_SIZE(left) == 1 &&
3678                 AOP_SIZE(right) == 1 ) {
3679                 genModOneByte(left,right,result);
3680                 goto release ;
3681         }
3682         
3683         /* should have been converted to function call */
3684         assert(0);
3685         
3686 release :
3687         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3688         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3689         freeAsmop(result,NULL,ic,TRUE); 
3690 }
3691
3692 /*-----------------------------------------------------------------*/
3693 /* genIfxJump :- will create a jump depending on the ifx                   */
3694 /*-----------------------------------------------------------------*/
3695 /*
3696 note: May need to add parameter to indicate when a variable is in bit space.
3697 */
3698 static void genIfxJump (iCode *ic, char *jval)
3699 {
3700         
3701         FENTRY;
3702         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3703         /* if true label then we jump if condition
3704         supplied is true */
3705         if ( IC_TRUE(ic) ) {
3706                 
3707                 if(strcmp(jval,"a") == 0)
3708                         emitSKPZ;
3709                 else if (strcmp(jval,"c") == 0)
3710                         emitSKPC;
3711                 else {
3712                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3713                         emitpcode(POC_BTFSC,    newpCodeOpBit(jval,-1,1));
3714                 }
3715                 
3716                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3717                 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3718                 
3719         }
3720         else {
3721                 /* false label is present */
3722                 if(strcmp(jval,"a") == 0)
3723                         emitSKPNZ;
3724                 else if (strcmp(jval,"c") == 0)
3725                         emitSKPNC;
3726                 else {
3727                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3728                         emitpcode(POC_BTFSS,    newpCodeOpBit(jval,-1,1));
3729                 }
3730                 
3731                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3732                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3733                 
3734         }
3735         
3736         
3737         /* mark the icode as generated */
3738         ic->generated = 1;
3739 }
3740
3741 #if 0
3742 /*-----------------------------------------------------------------*/
3743 /* genSkip                                                                                                                 */
3744 /*-----------------------------------------------------------------*/
3745 static void genSkip(iCode *ifx,int status_bit)
3746 {
3747         FENTRY;
3748         if(!ifx)
3749                 return;
3750         
3751         if ( IC_TRUE(ifx) ) {
3752                 switch(status_bit) {
3753                 case 'z':
3754                         emitSKPNZ;
3755                         break;
3756                         
3757                 case 'c':
3758                         emitSKPNC;
3759                         break;
3760                         
3761                 case 'd':
3762                         emitSKPDC;
3763                         break;
3764                         
3765                 }
3766                 
3767                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3768                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3769                 
3770         } else {
3771                 
3772                 switch(status_bit) {
3773                         
3774                 case 'z':
3775                         emitSKPZ;
3776                         break;
3777                         
3778                 case 'c':
3779                         emitSKPC;
3780                         break;
3781                         
3782                 case 'd':
3783                         emitSKPDC;
3784                         break;
3785                 }
3786                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3787                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3788                 
3789         }
3790         
3791 }
3792 #endif
3793
3794 /*-----------------------------------------------------------------*/
3795 /* genSkipc                                                                                                        */
3796 /*-----------------------------------------------------------------*/
3797 static void genSkipc(resolvedIfx *rifx)
3798 {
3799         FENTRY;
3800         if(!rifx)
3801                 return;
3802         
3803         if(rifx->condition)
3804                 emitSKPNC;
3805         else
3806                 emitSKPC;
3807         
3808         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3809         emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3810         rifx->generated = 1;
3811 }
3812
3813 #if 0
3814 /*-----------------------------------------------------------------*/
3815 /* genSkipz2                                                                                                       */
3816 /*-----------------------------------------------------------------*/
3817 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3818 {
3819         FENTRY;
3820         if(!rifx)
3821                 return;
3822         
3823         if( (rifx->condition ^ invert_condition) & 1)
3824                 emitSKPZ;
3825         else
3826                 emitSKPNZ;
3827         
3828         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3829         rifx->generated = 1;
3830 }
3831 #endif
3832
3833 #if 0
3834 /*-----------------------------------------------------------------*/
3835 /* genSkipz                                                        */
3836 /*-----------------------------------------------------------------*/
3837 static void genSkipz(iCode *ifx, int condition)
3838 {
3839         FENTRY;
3840         assert (ifx != NULL);
3841         
3842         if(condition)
3843                 emitSKPNZ;
3844         else
3845                 emitSKPZ;
3846         
3847         if ( IC_TRUE(ifx) )
3848                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3849         else
3850                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3851         
3852         if ( IC_TRUE(ifx) )
3853                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3854         else
3855                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3856         
3857 }
3858 #endif
3859
3860 #if 0
3861 /*-----------------------------------------------------------------*/
3862 /* genSkipCond                                                     */
3863 /*-----------------------------------------------------------------*/
3864 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3865 {
3866         FENTRY;
3867         if(!rifx)
3868                 return;
3869         
3870         if(rifx->condition)
3871                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3872         else
3873                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3874         
3875         
3876         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3877         rifx->generated = 1;
3878 }
3879 #endif
3880
3881 #if 0
3882 /*-----------------------------------------------------------------*/
3883 /* genChkZeroes :- greater or less than comparison                 */
3884 /*     For each byte in a literal that is zero, inclusive or the   */
3885 /*     the corresponding byte in the operand with W                */
3886 /*     returns true if any of the bytes are zero                   */
3887 /*-----------------------------------------------------------------*/
3888 static int genChkZeroes(operand *op, int lit,  int size)
3889 {
3890         
3891         int i;
3892         int flag =1;
3893         
3894         while(size--) {
3895                 i = (lit >> (size*8)) & 0xff;
3896                 
3897                 if(i==0) {
3898                         if(flag) 
3899                                 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3900                         else
3901                                 emitpcode(POC_IORFW, popGet(AOP(op),size));
3902                         flag = 0;
3903                 }
3904         }
3905         
3906         return (flag==0);
3907 }
3908 #endif
3909
3910
3911 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3912 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
3913 #define DEBUGpc           emitpComment
3914
3915 /*-----------------------------------------------------------------*/
3916 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
3917 /*                  aop (if it's NOT a literal) or from lit (if    */
3918 /*                  aop is a literal)                              */
3919 /*-----------------------------------------------------------------*/
3920 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3921   if (aop->type == AOP_LIT) {
3922     emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3923   } else {
3924     emitpcode (POC_MOVFW, popGet (aop, offset));
3925   }
3926 }
3927
3928 /* genCmp performs a left < right comparison, stores
3929  * the outcome in result (if != NULL) and generates
3930  * control flow code for the ifx (if != NULL).
3931  *
3932  * This version leaves in sequences like
3933  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3934  * which should be optmized by the peephole
3935  * optimizer - RN 2005-01-01 */
3936 static void genCmp (operand *left,operand *right,
3937                     operand *result, iCode *ifx, int sign)
3938 {
3939   resolvedIfx rIfx;
3940   int size;
3941   int offs;
3942   symbol *templbl;
3943   operand *dummy;
3944   unsigned long lit;
3945   unsigned long mask;
3946   int performedLt;
3947   int invert_result = 0;
3948
3949   FENTRY;
3950   
3951   assert (AOP_SIZE(left) == AOP_SIZE(right));
3952   assert (left && right);
3953
3954   size = AOP_SIZE(right) - 1;
3955   mask = (0x100UL << (size*8)) - 1;
3956   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3957   performedLt = 1;
3958   templbl = NULL;
3959   lit = 0;
3960   
3961   resolveIfx (&rIfx, ifx);
3962
3963   /**********************************************************************
3964    * handle bits - bit compares are promoted to int compares seemingly! *
3965    **********************************************************************/
3966 #if 0
3967   // THIS IS COMPLETELY UNTESTED!
3968   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3969     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3970     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3971     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3972
3973     emitSETC;
3974     // 1 < {0,1} is false --> clear C by skipping the next instruction
3975     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3976     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3977     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3978     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3979     emitCLRC; // only skipped for left=0 && right=1
3980
3981     goto correct_result_in_carry;
3982   } // if
3983 #endif
3984
3985   /*************************************************
3986    * make sure that left is register (or the like) *
3987    *************************************************/
3988   if (!isAOP_REGlike(left)) {
3989     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3990     assert (isAOP_LIT(left));
3991     assert (isAOP_REGlike(right));
3992     // swap left and right
3993     // left < right <==> right > left <==> (right >= left + 1)
3994     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3995
3996     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
3997       // MAXVALUE < right? always false
3998       if (performedLt) emitCLRC; else emitSETC;
3999       goto correct_result_in_carry;
4000     } // if
4001
4002     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4003     // that's why we handled it above.
4004     lit++;
4005
4006     dummy = left;
4007     left = right;
4008     right = dummy;
4009
4010     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4011   } else if (isAOP_LIT(right)) {
4012     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4013   } // if
4014
4015   assert (isAOP_REGlike(left)); // left must be register or the like
4016   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4017
4018   /*************************************************
4019    * special cases go here                         *
4020    *************************************************/
4021
4022   if (isAOP_LIT(right)) {
4023     if (!sign) {
4024       // unsigned comparison to a literal
4025       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4026       if (lit == 0) {
4027         // unsigned left < 0? always false
4028         if (performedLt) emitCLRC; else emitSETC;
4029         goto correct_result_in_carry;
4030       }
4031     } else {
4032       // signed comparison to a literal
4033       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4034       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4035         // signed left < 0x80000000? always false
4036         if (performedLt) emitCLRC; else emitSETC;
4037         goto correct_result_in_carry;
4038       } else if (lit == 0) {
4039         // compare left < 0; set CARRY if SIGNBIT(left) is set
4040         if (performedLt) emitSETC; else emitCLRC;
4041         emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
4042         if (performedLt) emitCLRC; else emitSETC;
4043         goto correct_result_in_carry;
4044       }
4045     } // if (!sign)
4046   } // right is literal
4047
4048   /*************************************************
4049    * perform a general case comparison             *
4050    * make sure we get CARRY==1 <==> left >= right  *
4051    *************************************************/
4052   // compare most significant bytes
4053   //DEBUGpc ("comparing bytes at offset %d", size);
4054   if (!sign) {
4055     // unsigned comparison
4056     pic14_mov2w_regOrLit (AOP(right), lit, size);
4057     emitpcode (POC_SUBFW, popGet (AOP(left), size));
4058   } else {
4059     // signed comparison
4060     // (add 2^n to both operands then perform an unsigned comparison)
4061     if (isAOP_LIT(right)) {
4062       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4063       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4064
4065       if (litbyte == 0x80) {
4066         // left >= 0x80 -- always true, but more bytes to come
4067         mov2w (AOP(left), size);
4068         emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
4069         emitSETC;
4070       } else {
4071         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4072         mov2w (AOP(left), size);
4073         emitpcode (POC_ADDLW, popGetLit (0x80));
4074         emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4075       } // if
4076     } else {
4077       pCodeOp *pctemp = popGetTempReg();
4078       mov2w (AOP(left), size);
4079       emitpcode (POC_ADDLW, popGetLit (0x80));
4080       emitpcode (POC_MOVWF, pctemp);
4081       mov2w (AOP(right), size);
4082       emitpcode (POC_ADDLW, popGetLit (0x80));
4083       emitpcode (POC_SUBFW, pctemp);
4084       popReleaseTempReg(pctemp);
4085     }
4086   } // if (!sign)
4087
4088   // compare remaining bytes (treat as unsigned case from above)
4089   templbl = newiTempLabel ( NULL );
4090   offs = size;
4091   while (offs--) {
4092     //DEBUGpc ("comparing bytes at offset %d", offs);
4093     emitSKPZ;
4094     emitpcode (POC_GOTO, popGetLabel (templbl->key));
4095     pic14_mov2w_regOrLit (AOP(right), lit, offs);
4096     emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4097   } // while (offs)
4098   emitpLabel (templbl->key);
4099   goto result_in_carry;
4100
4101 result_in_carry:
4102   
4103   /****************************************************
4104    * now CARRY contains the result of the comparison: *
4105    * SUBWF sets CARRY iff                             *
4106    * F-W >= 0 <==> F >= W <==> !(F < W)               *
4107    * (F=left, W=right)                                *
4108    ****************************************************/
4109
4110   if (performedLt) {
4111     invert_result = 1;
4112     // value will be used in the following genSkipc()
4113     rIfx.condition ^= 1;
4114   } // if
4115
4116 correct_result_in_carry:
4117
4118   // assign result to variable (if neccessary)
4119   if (result && AOP_TYPE(result) != AOP_CRY) {
4120     //DEBUGpc ("assign result");
4121     size = AOP_SIZE(result);
4122     while (size--) {
4123       emitpcode (POC_CLRF, popGet (AOP(result), size));
4124     } // while
4125     if (invert_result) {
4126       emitSKPC;
4127       emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4128     } else {
4129       emitpcode (POC_RLF, popGet (AOP(result), 0));
4130     }
4131   } // if (result)
4132
4133   // perform conditional jump
4134   if (ifx) {
4135     //DEBUGpc ("generate control flow");
4136     genSkipc (&rIfx);
4137     ifx->generated = 1;
4138   } // if
4139 }
4140
4141
4142 #if 0
4143 /* OLD VERSION -- BUGGY, DO NOT USE */
4144
4145 /*-----------------------------------------------------------------*/
4146 /* genCmp :- greater or less than comparison                       */
4147 /*-----------------------------------------------------------------*/
4148 static void genCmp (operand *left,operand *right,
4149                                         operand *result, iCode *ifx, int sign)
4150 {
4151         int size; //, offset = 0 ;
4152         unsigned long lit = 0L,i = 0;
4153         resolvedIfx rFalseIfx;
4154         //  resolvedIfx rTrueIfx;
4155         symbol *truelbl;
4156
4157         FENTRY;
4158         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4159         /*
4160         if(ifx) {
4161         DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4162         DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4163         }
4164         */
4165         
4166         resolveIfx(&rFalseIfx,ifx);
4167         truelbl  = newiTempLabel(NULL);
4168         size = max(AOP_SIZE(left),AOP_SIZE(right));
4169         
4170         DEBUGpic14_AopType(__LINE__,left,right,result);
4171         
4172 #define _swapp
4173         
4174         /* if literal is on the right then swap with left */
4175         if ((AOP_TYPE(right) == AOP_LIT)) {
4176                 operand *tmp = right ;
4177                 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4178                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4179 #ifdef _swapp
4180                 
4181                 lit = (lit - 1) & mask;
4182                 right = left;
4183                 left = tmp;
4184                 rFalseIfx.condition ^= 1;
4185 #endif
4186                 
4187         } else if ((AOP_TYPE(left) == AOP_LIT)) {
4188                 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4189         }
4190         
4191         
4192         //if(IC_TRUE(ifx) == NULL)
4193         /* if left & right are bit variables */
4194         if (AOP_TYPE(left) == AOP_CRY &&
4195                 AOP_TYPE(right) == AOP_CRY ) {
4196                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4197                 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4198         } else {
4199         /* subtract right from left if at the
4200         end the carry flag is set then we know that
4201                 left is greater than right */
4202                 
4203                 symbol *lbl  = newiTempLabel(NULL);
4204                 
4205 #ifndef _swapp
4206                 if(AOP_TYPE(right) == AOP_LIT) {
4207                         
4208                         //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4209                         
4210                         DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4211                         
4212                         /* special cases */
4213                         
4214                         if(lit == 0) {
4215                                 
4216                                 if(sign != 0) 
4217                                         genSkipCond(&rFalseIfx,left,size-1,7);
4218                                 else 
4219                                         /* no need to compare to 0...*/
4220                                         /* NOTE: this is a de-generate compare that most certainly 
4221                                         *       creates some dead code. */
4222                                         emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4223                                 
4224                                 if(ifx) ifx->generated = 1;
4225                                 return;
4226                                 
4227                         }
4228                         size--;
4229                         
4230                         if(size == 0) {
4231                                 //i = (lit >> (size*8)) & 0xff;
4232                                 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4233                                 
4234                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4235                                 
4236                                 i = ((0-lit) & 0xff);
4237                                 if(sign) {
4238                                         if( i == 0x81) { 
4239                                         /* lit is 0x7f, all signed chars are less than
4240                                                 * this except for 0x7f itself */
4241                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4242                                                 genSkipz2(&rFalseIfx,0);
4243                                         } else {
4244                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4245                                                 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4246                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4247                                         }
4248                                         
4249                                 } else {
4250                                         if(lit == 1) {
4251                                                 genSkipz2(&rFalseIfx,1);
4252                                         } else {
4253                                                 emitpcode(POC_ADDLW, popGetLit(i));
4254                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4255                                         }
4256                                 }
4257                                 
4258                                 if(ifx) ifx->generated = 1;
4259                                 return;
4260                         }
4261                         
4262                         /* chars are out of the way. now do ints and longs */
4263                         
4264                         
4265                         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4266                         
4267                         /* special cases */
4268                         
4269                         if(sign) {
4270                                 
4271                                 if(lit == 0) {
4272                                         genSkipCond(&rFalseIfx,left,size,7);
4273                                         if(ifx) ifx->generated = 1;
4274                                         return;
4275                                 }
4276                                 
4277                                 if(lit <0x100) {
4278                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4279                                         
4280                                         //rFalseIfx.condition ^= 1;
4281                                         //genSkipCond(&rFalseIfx,left,size,7);
4282                                         //rFalseIfx.condition ^= 1;
4283                                         
4284                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4285                                         if(rFalseIfx.condition)
4286                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4287                                         else
4288                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4289                                         
4290                                         emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4291                                         emitpcode(POC_ADDFW, popGet(AOP(left),0));
4292                                         emitpcode(POC_MOVFW, popGet(AOP(left),1));
4293                                         
4294                                         while(size > 1)
4295                                                 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4296                                         
4297                                         if(rFalseIfx.condition) {
4298                                                 emitSKPZ;
4299                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4300                                                 
4301                                         } else {
4302                                                 emitSKPNZ;
4303                                         }
4304                                         
4305                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4306                                         emitpLabel(truelbl->key);
4307                                         if(ifx) ifx->generated = 1;
4308                                         return;
4309                                         
4310                                 }
4311                                 
4312                                 if(size == 1) {
4313                                         
4314                                         if( (lit & 0xff) == 0) {
4315                                                 /* lower byte is zero */
4316                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4317                                                 i = ((lit >> 8) & 0xff) ^0x80;
4318                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4319                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4320                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4321                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4322                                                 
4323                                                 
4324                                                 if(ifx) ifx->generated = 1;
4325                                                 return;
4326                                                 
4327                                         }
4328                                 } else {
4329                                         /* Special cases for signed longs */
4330                                         if( (lit & 0xffffff) == 0) {
4331                                                 /* lower byte is zero */
4332                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4333                                                 i = ((lit >> 8*3) & 0xff) ^0x80;
4334                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4335                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4336                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4337                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4338                                                 
4339                                                 
4340                                                 if(ifx) ifx->generated = 1;
4341                                                 return;
4342                                                 
4343                                         }
4344                                         
4345                                 }
4346                                 
4347                                 
4348                                 if(lit & (0x80 << (size*8))) {
4349                                         /* lit is negative */
4350                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4351                                         
4352                                         //genSkipCond(&rFalseIfx,left,size,7);
4353                                         
4354                                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4355                                         
4356                                         if(rFalseIfx.condition)
4357                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4358                                         else
4359                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4360                                         
4361                                         
4362                                 } else {
4363                                         /* lit is positive */
4364                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4365                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4366                                         if(rFalseIfx.condition)
4367                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4368                                         else
4369                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4370                                         
4371                                 }
4372                                 
4373                                 /* There are no more special cases, so perform a general compare */
4374                                 
4375                                 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4376                                 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4377                                 
4378                                 while(size--) {
4379                                         
4380                                         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4381                                         emitSKPNZ;
4382                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4383                                 }
4384                                 //rFalseIfx.condition ^= 1;
4385                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4386                                 
4387                                 emitpLabel(truelbl->key);
4388                                 
4389                                 if(ifx) ifx->generated = 1;
4390                                 return;
4391                                 
4392                                 
4393                         }
4394
4395
4396                         /* sign is out of the way. So now do an unsigned compare */
4397                         DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4398
4399
4400                         /* General case - compare to an unsigned literal on the right.*/
4401
4402                         i = (lit >> (size*8)) & 0xff;
4403                         emitpcode(POC_MOVLW, popGetLit(i));
4404                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4405                         while(size--) {
4406                                 i = (lit >> (size*8)) & 0xff;
4407                                 
4408                                 if(i) {
4409                                         emitpcode(POC_MOVLW, popGetLit(i));
4410                                         emitSKPNZ;
4411                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4412                                 } else {
4413                                 /* this byte of the lit is zero, 
4414                                         *if it's not the last then OR in the variable */
4415                                         if(size)
4416                                                 emitpcode(POC_IORFW, popGet(AOP(left),size));
4417                                 }
4418                         }
4419
4420
4421                 emitpLabel(lbl->key);
4422                 //if(emitFinalCheck)
4423                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4424                 if(sign)
4425                         emitpLabel(truelbl->key);
4426
4427                 if(ifx) ifx->generated = 1;
4428                 return;
4429
4430
4431                 }
4432 #endif  // _swapp
4433
4434                 if(AOP_TYPE(left) == AOP_LIT) {
4435                         //symbol *lbl = newiTempLabel(NULL);
4436                         
4437                         //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4438                         
4439                         
4440                         DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4441                         
4442                         /* Special cases */
4443                         if((lit == 0) && (sign == 0)){
4444                                 
4445                                 size--;
4446                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4447                                 while(size) 
4448                                         emitpcode(POC_IORFW, popGet(AOP(right),--size));
4449                                 
4450                                 genSkipz2(&rFalseIfx,0);
4451                                 if(ifx) ifx->generated = 1;
4452                                 return;
4453                         }
4454                         
4455                         if(size==1) {
4456                                 /* Special cases */
4457                                 lit &= 0xff;
4458                                 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4459                                         /* degenerate compare can never be true */
4460                                         if(rFalseIfx.condition == 0)
4461                                                 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4462                                         
4463                                         if(ifx) ifx->generated = 1;
4464                                         return;
4465                                 }
4466                                 
4467                                 if(sign) {
4468                                         /* signed comparisons to a literal byte */
4469                                         
4470                                         int lp1 = (lit+1) & 0xff;
4471                                         
4472                                         DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4473                                         switch (lp1) {
4474                                         case 0:
4475                                                 rFalseIfx.condition ^= 1;
4476                                                 genSkipCond(&rFalseIfx,right,0,7);
4477                                                 break;
4478                                         case 0x7f:
4479                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4480                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4481                                                 genSkipz2(&rFalseIfx,1);
4482                                                 break;
4483                                         default:
4484                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4485                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4486                                                 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4487                                                 rFalseIfx.condition ^= 1;
4488                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4489                                                 break;
4490                                         }
4491                                         if(ifx) ifx->generated = 1;
4492                                 } else {
4493                                         /* unsigned comparisons to a literal byte */
4494                                         
4495                                         switch(lit & 0xff ) {
4496                                         case 0:
4497                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4498                                                 genSkipz2(&rFalseIfx,0);
4499                                                 if(ifx) ifx->generated = 1;
4500                                                 break;
4501                                         case 0x7f:
4502                                                 genSkipCond(&rFalseIfx,right,0,7);
4503                                                 if(ifx) ifx->generated = 1;
4504                                                 break;
4505                                                 
4506                                         default:
4507                                                 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4508                                                 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4509                                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4510                                                 rFalseIfx.condition ^= 1;
4511                                                 if (AOP_TYPE(result) == AOP_CRY) {
4512                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4513                                                         if(ifx) ifx->generated = 1;
4514                                                 } else {
4515                                                         DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4516                                                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4517                                                         emitpcode(POC_RLF, popGet(AOP(result),0));
4518                                                         emitpcode(POC_MOVLW, popGetLit(0x01));
4519                                                         emitpcode(POC_XORWF, popGet(AOP(result),0));
4520                                                 }       
4521                                                 break;
4522                                         }
4523                                 }
4524                                 
4525                                 //goto check_carry;
4526                                 return;
4527                                 
4528                         } else {
4529                                 
4530                                 /* Size is greater than 1 */
4531                                 
4532                                 if(sign) {
4533                                         int lp1 = lit+1;
4534                                         
4535                                         size--;
4536                                         
4537                                         if(lp1 == 0) {
4538                                                 /* this means lit = 0xffffffff, or -1 */
4539                                                 
4540                                                 
4541                                                 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4542                                                 rFalseIfx.condition ^= 1;
4543                                                 genSkipCond(&rFalseIfx,right,size,7);
4544                                                 if(ifx) ifx->generated = 1;
4545                                                 return;
4546                                         }
4547                                         
4548                                         if(lit == 0) {
4549                                                 int s = size;
4550                                                 
4551                                                 if(rFalseIfx.condition) {
4552                                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4553                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4554                                                 }
4555                                                 
4556                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4557                                                 while(size--)
4558                                                         emitpcode(POC_IORFW, popGet(AOP(right),size));
4559                                                 
4560                                                 
4561                                                 emitSKPZ;
4562                                                 if(rFalseIfx.condition) {
4563                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4564                                                         emitpLabel(truelbl->key);
4565                                                 }else {
4566                                                         rFalseIfx.condition ^= 1;
4567                                                         genSkipCond(&rFalseIfx,right,s,7);
4568                                                 }
4569                                                 
4570                                                 if(ifx) ifx->generated = 1;
4571                                                 return;
4572                                         }
4573                                         
4574                                         if((size == 1) &&  (0 == (lp1&0xff))) {
4575                                                 /* lower byte of signed word is zero */
4576                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4577                                                 i = ((lp1 >> 8) & 0xff) ^0x80;
4578                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4579                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4580                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4581                                                 rFalseIfx.condition ^= 1;
4582                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4583                                                 
4584                                                 
4585                                                 if(ifx) ifx->generated = 1;
4586                                                 return;
4587                                         }
4588                                         
4589                                         if(lit & (0x80 << (size*8))) {
4590                                                 /* Lit is less than zero */
4591                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4592                                                 //rFalseIfx.condition ^= 1;
4593                                                 //genSkipCond(&rFalseIfx,left,size,7);
4594                                                 //rFalseIfx.condition ^= 1;
4595                                                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4596                                                 //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4597                                                 
4598                                                 if(rFalseIfx.condition)
4599                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4600                                                 else
4601                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4602                                                 
4603                                                 
4604                                         } else {
4605                                                 /* Lit is greater than or equal to zero */
4606                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4607                                                 //rFalseIfx.condition ^= 1;
4608                                                 //genSkipCond(&rFalseIfx,right,size,7);
4609                                                 //rFalseIfx.condition ^= 1;
4610                                                 
4611                                                 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4612                                                 //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4613                                                 
4614                                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4615                                                 if(rFalseIfx.condition)
4616                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4617                                                 else
4618                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4619                                                 
4620                                         }
4621                                         
4622                                         
4623                                         emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4624                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4625                                         
4626                                         while(size--) {
4627                                                 
4628                                                 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4629                                                 emitSKPNZ;
4630                                                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4631                                         }
4632                                         rFalseIfx.condition ^= 1;
4633                                         //rFalseIfx.condition = 1;
4634                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4635                                         
4636                                         emitpLabel(truelbl->key);
4637                                         
4638                                         if(ifx) ifx->generated = 1;
4639                                         return;
4640                                         // end of if (sign)
4641                                 } else {
4642                                         
4643                                         /* compare word or long to an unsigned literal on the right.*/
4644                                         
4645                                         
4646                                         size--;
4647                                         if(lit < 0xff) {
4648                                                 DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4649                                                 switch (lit) {
4650                                                 case 0:
4651                                                         break; /* handled above */
4652                                                 /*
4653                                                 case 0xff:
4654                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4655                                                         while(size--)
4656                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4657                                                         genSkipz2(&rFalseIfx,0);
4658                                                         break;
4659                                                 */
4660                                                 default:
4661                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4662                                                         while(--size)
4663                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4664                                                         
4665                                                         emitSKPZ;
4666                                                         if(rFalseIfx.condition)
4667                                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4668                                                         else
4669                                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4670                                                         
4671                                                         
4672                                                         emitpcode(POC_MOVLW, popGetLit(lit+1));
4673                                                         emitpcode(POC_SUBFW, popGet(AOP(right),0));
4674                                                         
4675                                                         rFalseIfx.condition ^= 1;
4676                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4677                                                 }
4678                                                 
4679                                                 emitpLabel(truelbl->key);
4680                                                 
4681                                                 if(ifx) ifx->generated = 1;
4682                                                 return;
4683                                         }
4684                                         
4685                                         
4686                                         lit++;
4687                                         DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4688                                         i = (lit >> (size*8)) & 0xff;
4689                                         
4690                                         emitpcode(POC_MOVLW, popGetLit(i));
4691                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4692                                         
4693                                         while(size--) {
4694                                                 i = (lit >> (size*8)) & 0xff;
4695                                                 
4696                                                 if(i) {
4697                                                         emitpcode(POC_MOVLW, popGetLit(i));
4698                                                         emitSKPNZ;
4699                                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4700                                                 } else {
4701                                                 /* this byte of the lit is zero, 
4702                                                         *if it's not the last then OR in the variable */
4703                                                         if(size)
4704                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4705                                                 }
4706                                         }
4707                                         
4708                                         
4709                                         emitpLabel(lbl->key);
4710                                         
4711                                         rFalseIfx.condition ^= 1;
4712                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4713                                 }
4714                                 
4715                                 if(sign)
4716                                         emitpLabel(truelbl->key);
4717                                 if(ifx) ifx->generated = 1;
4718                                 return;
4719                         }
4720                 }
4721                 /* Compare two variables */
4722                 
4723                 DEBUGpic14_emitcode(";sign","%d",sign);
4724                 
4725                 size--;
4726                 if(sign) {
4727                         /* Sigh. thus sucks... */
4728                         if(size) {
4729                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4730                                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4731                                 emitpcode(POC_MOVLW, popGetLit(0x80));
4732                                 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4733                                 emitpcode(POC_XORFW, popGet(AOP(right),size));
4734                                 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4735                         } else {
4736                                 /* Signed char comparison */
4737                                 /* Special thanks to Nikolai Golovchenko for this snippet */
4738                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4739                                 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4740                                 emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4741                                 emitpcode(POC_XORFW, popGet(AOP(left),0));
4742                                 emitpcode(POC_XORFW, popGet(AOP(right),0));
4743                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4744                                 
4745                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4746                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4747                                 
4748                                 if(ifx) ifx->generated = 1;
4749                                 return;
4750                         }
4751                         
4752                 } else {
4753                         
4754                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4755                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4756                 }
4757                 
4758                 
4759                 /* The rest of the bytes of a multi-byte compare */
4760                 while (size) {
4761                         
4762                         emitSKPZ;
4763                         emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4764                         size--;
4765                         
4766                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4767                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4768                         
4769                         
4770                 }
4771                 
4772                 emitpLabel(lbl->key);
4773                 
4774                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4775                 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4776                         (AOP_TYPE(result) == AOP_REG)) {
4777                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4778                         emitpcode(POC_RLF, popGet(AOP(result),0));
4779                 } else {
4780                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4781                 }       
4782                 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4783                 if(ifx) ifx->generated = 1;
4784                 
4785                 return;
4786                 
4787         }
4788         
4789         // check_carry:
4790         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4791                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4792                 pic14_outBitC(result);
4793         } else {
4794                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4795                 /* if the result is used in the next
4796                 ifx conditional branch then generate
4797                 code a little differently */
4798                 if (ifx )
4799                         genIfxJump (ifx,"c");
4800                 else
4801                         pic14_outBitC(result);
4802                 /* leave the result in acc */
4803         }
4804         
4805 }
4806 #endif
4807
4808 /*-----------------------------------------------------------------*/
4809 /* genCmpGt :- greater than comparison                             */
4810 /*-----------------------------------------------------------------*/
4811 static void genCmpGt (iCode *ic, iCode *ifx)
4812 {
4813         operand *left, *right, *result;
4814         sym_link *letype , *retype;
4815         int sign ;
4816         
4817         FENTRY;
4818         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4819         left = IC_LEFT(ic);
4820         right= IC_RIGHT(ic);
4821         result = IC_RESULT(ic);
4822         
4823         letype = getSpec(operandType(left));
4824         retype =getSpec(operandType(right));
4825         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4826         /* assign the amsops */
4827         aopOp (left,ic,FALSE);
4828         aopOp (right,ic,FALSE);
4829         aopOp (result,ic,TRUE);
4830         
4831         genCmp(right, left, result, ifx, sign);
4832         
4833         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4834         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4835         freeAsmop(result,NULL,ic,TRUE); 
4836 }
4837
4838 /*-----------------------------------------------------------------*/
4839 /* genCmpLt - less than comparisons                                */
4840 /*-----------------------------------------------------------------*/
4841 static void genCmpLt (iCode *ic, iCode *ifx)
4842 {
4843         operand *left, *right, *result;
4844         sym_link *letype , *retype;
4845         int sign ;
4846         
4847         FENTRY;
4848         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4849         left = IC_LEFT(ic);
4850         right= IC_RIGHT(ic);
4851         result = IC_RESULT(ic);
4852         
4853         letype = getSpec(operandType(left));
4854         retype =getSpec(operandType(right));
4855         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4856         
4857         /* assign the amsops */
4858         aopOp (left,ic,FALSE);
4859         aopOp (right,ic,FALSE);
4860         aopOp (result,ic,TRUE);
4861         
4862         genCmp(left, right, result, ifx, sign);
4863         
4864         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4865         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4866         freeAsmop(result,NULL,ic,TRUE); 
4867 }
4868
4869 #if 0
4870 /*-----------------------------------------------------------------*/
4871 /* genc16bit2lit - compare a 16 bit value to a literal             */
4872 /*-----------------------------------------------------------------*/
4873 static void genc16bit2lit(operand *op, int lit, int offset)
4874 {
4875         int i;
4876         
4877         FENTRY;
4878         DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4879         if( (lit&0xff) == 0) 
4880                 i=1;
4881         else
4882                 i=0;
4883         
4884         switch( BYTEofLONG(lit,i)) { 
4885         case 0:
4886                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4887                 break;
4888         case 1:
4889                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4890                 break;
4891         case 0xff:
4892                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4893                 break;
4894         default:
4895                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4896                 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4897         }
4898         
4899         i ^= 1;
4900         
4901         switch( BYTEofLONG(lit,i)) { 
4902         case 0:
4903                 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4904                 break;
4905         case 1:
4906                 emitSKPNZ;
4907                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4908                 break;
4909         case 0xff:
4910                 emitSKPNZ;
4911                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4912                 break;
4913         default:
4914                 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4915                 emitSKPNZ;
4916                 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4917                 
4918         }
4919         
4920 }
4921 #endif
4922
4923 #if 0
4924 /*-----------------------------------------------------------------*/
4925 /* gencjneshort - compare and jump if not equal                    */
4926 /*-----------------------------------------------------------------*/
4927 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4928 {
4929         int size = min(AOP_SIZE(left),AOP_SIZE(right));
4930         int offset = 0;
4931         //resolvedIfx rIfx;
4932         symbol *lbl;
4933         
4934         //unsigned long lit = 0L;
4935         FENTRY;
4936         if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4937           emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4938           return;
4939         }
4940         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4941         DEBUGpic14_AopType(__LINE__,left,right,result);
4942         
4943         assert (!pic14_sameRegs (AOP(left), AOP(result)));
4944         assert (!pic14_sameRegs (AOP(right), AOP(result)));
4945         if (AOP_SIZE(result)) {
4946           for (offset = 0; offset < AOP_SIZE(result); offset++)
4947             emitpcode (POC_CLRF, popGet (AOP(result), offset));
4948         }
4949         
4950         assert (AOP_SIZE(left) == AOP_SIZE(right));
4951         //resolveIfx(&rIfx,ifx);
4952         lbl = newiTempLabel (NULL);
4953         while (size--)
4954         {
4955           mov2w (AOP(right),size);
4956           emitpcode (POC_XORFW, popGet (AOP(left), size));
4957           if (size)
4958           {
4959             emitSKPZ;
4960             emitpcode (POC_GOTO, popGetLabel (lbl->key));
4961           }
4962         } // while
4963         emitpLabel (lbl->key);
4964         if (AOP_SIZE(result)) {
4965           emitSKPNZ;
4966           emitpcode (POC_INCF, popGet (AOP(result), 0));
4967         } else {
4968           assert (ifx);
4969           genSkipz (ifx, NULL != IC_TRUE(ifx));
4970           ifx->generated = 1;
4971         }
4972         return;
4973 #if 0   
4974         if(result)
4975         {
4976                 DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4977                 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4978                 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4979                 for (offset=0; offset < AOP_SIZE(result); offset++)
4980                 {
4981                         emitpcode (POC_CLRF, popGet (AOP(result), offset));
4982                 } // for offset
4983         }
4984         
4985         
4986         /* if the left side is a literal or 
4987         if the right is in a pointer register and left 
4988         is not */
4989         if ((AOP_TYPE(left) == AOP_LIT) || 
4990                 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4991                 operand *t = right;
4992                 right = left;
4993                 left = t;
4994         }
4995         if(AOP_TYPE(right) == AOP_LIT)
4996                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4997         
4998         /* if the right side is a literal then anything goes */
4999         if (AOP_TYPE(right) == AOP_LIT &&
5000                 AOP_TYPE(left) != AOP_DIR ) {
5001                 switch(size) {
5002                 case 2:
5003                         genc16bit2lit(left, lit, 0);
5004                         emitSKPNZ;
5005                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
5006                         break;
5007                 default:
5008                         offset = 0;
5009                         while (size--) {
5010                                 if(lit & 0xff) {
5011                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5012                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5013                                 } else {
5014                                         emitpcode(POC_MOVF,popGet(AOP(left),offset));
5015                                 }
5016                                 
5017                                 emitSKPNZ;
5018                                 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5019                                 offset++;
5020                                 lit >>= 8;
5021                         }
5022                         break;
5023                 }
5024         }
5025         
5026         /* if the right side is in a register or in direct space or
5027         if the left is a pointer register & right is not */    
5028         else if (AOP_TYPE(right) == AOP_REG ||
5029                 AOP_TYPE(right) == AOP_DIR || 
5030                 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5031                 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5032                 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5033                 int lbl_key = lbl->key;
5034                 
5035                 if(!result) {
5036                         DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5037                         fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5038                                 __FUNCTION__,__LINE__);
5039                         return;
5040                 }
5041                 
5042                 /*     switch(size) { */
5043                 /*     case 2: */
5044                 /*       genc16bit2lit(left, lit, 0); */
5045                 /*       emitSKPNZ; */
5046                 /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
5047                 /*       break; */
5048                 /*     default: */
5049                 offset = 0;
5050                 while (size--) {
5051                         int emit_skip=1;
5052                         if((AOP_TYPE(left) == AOP_DIR) && 
5053                                 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5054                                 
5055                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5056                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5057                                 
5058                         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5059                                 
5060                                 switch (lit & 0xff) {
5061                                 case 0:
5062                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5063                                         break;
5064                                 case 1:
5065                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5066                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5067                                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
5068                                         emit_skip=0;
5069                                         break;
5070                                 case 0xff:
5071                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5072                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5073                                         //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5074                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5075                                         emit_skip=0;
5076                                         break;
5077                                 default:
5078                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5079                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5080                                 }
5081                                 lit >>= 8;
5082                                 
5083                         } else {
5084                                 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5085                         }
5086                         if(emit_skip) {
5087                                 if(AOP_TYPE(result) == AOP_CRY) {
5088                                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5089                                         if(rIfx.condition)
5090                                                 emitSKPNZ;
5091                                         else
5092                                                 emitSKPZ;
5093                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5094                                 } else {
5095                                         /* fix me. probably need to check result size too */
5096                                         //emitpcode(POC_CLRF,popGet(AOP(result),0));
5097                                         if(rIfx.condition)
5098                                                 emitSKPZ;
5099                                         else
5100                                                 emitSKPNZ;
5101                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5102                                 }
5103                                 if(ifx)
5104                                         ifx->generated=1;
5105                         }
5106                         emit_skip++;
5107                         offset++;
5108                 }
5109                 /*       break; */
5110                 /*     } */
5111         } else if(AOP_TYPE(right) == AOP_REG &&
5112                 AOP_TYPE(left) != AOP_DIR){
5113
5114                 offset = 0;
5115                 while(size--) {
5116                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5117                         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5118                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5119                         if(rIfx.condition)
5120                                 emitSKPNZ;
5121                         else
5122                                 emitSKPZ;
5123                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5124                         offset++;
5125                 }
5126                 
5127         }else{
5128                 /* right is a pointer reg need both a & b */
5129                 offset = 0;
5130                 while(size--) {
5131                         char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5132                         if(strcmp(l,"b"))
5133                                 pic14_emitcode("mov","b,%s",l);
5134                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5135                         pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5136                         offset++;
5137                 }
5138         }
5139         
5140         emitpcode(POC_INCF,popGet(AOP(result),0));
5141         if(!rIfx.condition)
5142                 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5143         
5144         emitpLabel(lbl->key);
5145         
5146         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5147         
5148         if(ifx)
5149                 ifx->generated = 1;
5150 #endif
5151 }
5152 #endif
5153
5154 #if 0
5155 /*-----------------------------------------------------------------*/
5156 /* gencjne - compare and jump if not equal                         */
5157 /*-----------------------------------------------------------------*/
5158 static void gencjne(operand *left, operand *right, iCode *ifx)
5159 {
5160         symbol *tlbl  = newiTempLabel(NULL);
5161         
5162         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5163         gencjneshort(left, right, lbl);
5164         
5165         pic14_emitcode("mov","a,%s",one);
5166         pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5167         pic14_emitcode("","%05d_DS_:",lbl->key+100);
5168         pic14_emitcode("clr","a");
5169         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5170         
5171         emitpLabel(lbl->key);
5172         emitpLabel(tlbl->key);
5173         
5174 }
5175 #endif
5176
5177 /*-----------------------------------------------------------------*/
5178 /* genCmpEq - generates code for equal to                          */
5179 /*-----------------------------------------------------------------*/
5180 static void genCmpEq (iCode *ic, iCode *ifx)
5181 {
5182   operand *left, *right, *result;
5183   int size;
5184   symbol *false_label;
5185
5186   FENTRY;
5187   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5188
5189   if(ifx)
5190     DEBUGpic14_emitcode ("; ifx is non-null","");
5191   else
5192     DEBUGpic14_emitcode ("; ifx is null","");
5193
5194   aopOp((left=IC_LEFT(ic)),ic,FALSE);
5195   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5196   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5197
5198   DEBUGpic14_AopType(__LINE__,left,right,result);
5199
5200   /* if literal, move literal to right */ 
5201   if (op_isLitLike (IC_LEFT(ic))) {
5202     operand *tmp = right ;
5203     right = left;
5204     left = tmp;
5205   }
5206
5207   false_label = NULL;
5208   if (ifx && !IC_TRUE(ifx))
5209   {
5210     assert (IC_FALSE(ifx));
5211     false_label = IC_FALSE(ifx);
5212   }
5213
5214   size = min(AOP_SIZE(left),AOP_SIZE(right));
5215   assert(!pic14_sameRegs(AOP(result),AOP(left)));
5216   assert(!pic14_sameRegs(AOP(result),AOP(right)));
5217
5218   /* assume left != right */
5219   {
5220     int i;
5221     for (i=0; i < AOP_SIZE(result); i++)
5222     {
5223       emitpcode(POC_CLRF, popGet(AOP(result),i));
5224     }
5225   }
5226
5227   if (AOP_TYPE(right) == AOP_LIT)
5228   {
5229     unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5230     int i;
5231     size = AOP_SIZE(left);
5232     assert(!op_isLitLike(left));
5233
5234     switch (lit)
5235     {
5236       case 0:
5237         mov2w(AOP(left), 0);
5238         for (i=1; i < size; i++)
5239           emitpcode(POC_IORFW,popGet(AOP(left),i));
5240         /* now Z is set iff `left == right' */
5241         emitSKPZ;
5242         if (!false_label) false_label = newiTempLabel(NULL);
5243         emitpcode(POC_GOTO, popGetLabel(false_label->key));
5244         break;
5245
5246       default:
5247         for (i=0; i < size; i++)
5248         {
5249           mov2w(AOP(left),i);
5250           emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5251           /* now Z is cleared if `left != right' */
5252           emitSKPZ;
5253           if (!false_label) false_label = newiTempLabel(NULL);
5254           emitpcode(POC_GOTO, popGetLabel(false_label->key));
5255         } // for i
5256         break;
5257     } // switch (lit)
5258   }
5259   else
5260   {
5261     /* right is no literal */
5262     int i;
5263
5264     for (i=0; i < size; i++)
5265     {
5266       mov2w(AOP(right),i);
5267       emitpcode(POC_XORFW,popGet(AOP(left),i));
5268       /* now Z is cleared if `left != right' */
5269       emitSKPZ;
5270       if (!false_label) false_label = newiTempLabel(NULL);
5271       emitpcode(POC_GOTO, popGetLabel(false_label->key));
5272     } // for i
5273   }
5274
5275   /* if we reach here, left == right */
5276
5277   if (AOP_SIZE(result) > 0)
5278   {
5279     emitpcode(POC_INCF, popGet(AOP(result),0));
5280   }
5281
5282   if (ifx && IC_TRUE(ifx))
5283   {
5284     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5285   }
5286
5287   if (false_label && (!ifx || IC_TRUE(ifx)))
5288     emitpLabel(false_label->key);
5289
5290   if (ifx) ifx->generated = 1;
5291
5292   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5293   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5294   freeAsmop(result,NULL,ic,TRUE);
5295 }
5296
5297 /*-----------------------------------------------------------------*/
5298 /* ifxForOp - returns the icode containing the ifx for operand     */
5299 /*-----------------------------------------------------------------*/
5300 static iCode *ifxForOp ( operand *op, iCode *ic )
5301 {
5302         FENTRY;
5303         /* if true symbol then needs to be assigned */
5304         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5305         if (IS_TRUE_SYMOP(op))
5306                 return NULL ;
5307         
5308         /* if this has register type condition and
5309         the next instruction is ifx with the same operand
5310         and live to of the operand is upto the ifx only then */
5311         if (ic->next &&
5312                 ic->next->op == IFX &&
5313                 IC_COND(ic->next)->key == op->key &&
5314                 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5315                 return ic->next;
5316         
5317         if (ic->next &&
5318                 ic->next->op == IFX &&
5319                 IC_COND(ic->next)->key == op->key) {
5320                 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5321                 return ic->next;
5322         }
5323         
5324         DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5325         if (ic->next &&
5326                 ic->next->op == IFX)
5327                 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5328         
5329         if (ic->next &&
5330                 ic->next->op == IFX &&
5331                 IC_COND(ic->next)->key == op->key) {
5332                 DEBUGpic14_emitcode ("; "," key is okay");
5333                 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5334                         OP_SYMBOL(op)->liveTo,
5335                         ic->next->seq);
5336         }
5337         
5338         
5339         return NULL;
5340 }
5341 /*-----------------------------------------------------------------*/
5342 /* genAndOp - for && operation                                     */
5343 /*-----------------------------------------------------------------*/
5344 static void genAndOp (iCode *ic)
5345 {
5346         operand *left,*right, *result;
5347         /*     symbol *tlbl; */
5348         
5349         FENTRY;
5350         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5351         /* note here that && operations that are in an
5352         if statement are taken away by backPatchLabels
5353         only those used in arthmetic operations remain */
5354         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5355         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5356         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5357         
5358         DEBUGpic14_AopType(__LINE__,left,right,result);
5359         
5360         emitpcode(POC_MOVFW,popGet(AOP(left),0));
5361         emitpcode(POC_ANDFW,popGet(AOP(right),0));
5362         emitpcode(POC_MOVWF,popGet(AOP(result),0));
5363         
5364         /* if both are bit variables */
5365         /*     if (AOP_TYPE(left) == AOP_CRY && */
5366         /*         AOP_TYPE(right) == AOP_CRY ) { */
5367         /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5368         /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5369         /*         pic14_outBitC(result); */
5370         /*     } else { */
5371         /*         tlbl = newiTempLabel(NULL); */
5372         /*         pic14_toBoolean(left);     */
5373         /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5374         /*         pic14_toBoolean(right); */
5375         /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5376         /*         pic14_outBitAcc(result); */
5377         /*     } */
5378         
5379         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5380         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5381         freeAsmop(result,NULL,ic,TRUE);
5382 }
5383
5384
5385 /*-----------------------------------------------------------------*/
5386 /* genOrOp - for || operation                                      */
5387 /*-----------------------------------------------------------------*/
5388 /*
5389 tsd pic port -
5390 modified this code, but it doesn't appear to ever get called
5391 */
5392
5393 static void genOrOp (iCode *ic)
5394 {
5395         operand *left,*right, *result;
5396         symbol *tlbl;
5397         int i;
5398         
5399         /* note here that || operations that are in an
5400         if statement are taken away by backPatchLabels
5401         only those used in arthmetic operations remain */
5402         FENTRY;
5403         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5404         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5405         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5406         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5407         
5408         DEBUGpic14_AopType(__LINE__,left,right,result);
5409
5410         for (i=0; i < AOP_SIZE(result); i++)
5411         {
5412                 emitpcode(POC_CLRF, popGet(AOP(result), i));
5413         } // for i
5414
5415         tlbl = newiTempLabel(NULL);
5416         pic14_toBoolean(left);
5417         emitSKPZ;
5418         emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5419         pic14_toBoolean(right);
5420         emitpLabel(tlbl->key);
5421         /* here Z is clear IFF `left || right' */
5422         emitSKPZ;
5423         emitpcode(POC_INCF, popGet(AOP(result), 0));
5424         
5425         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5426         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5427         freeAsmop(result,NULL,ic,TRUE);            
5428 }
5429
5430 /*-----------------------------------------------------------------*/
5431 /* isLiteralBit - test if lit == 2^n                               */
5432 /*-----------------------------------------------------------------*/
5433 static int isLiteralBit(unsigned long lit)
5434 {
5435         unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5436                 0x100L,0x200L,0x400L,0x800L,
5437                 0x1000L,0x2000L,0x4000L,0x8000L,
5438                 0x10000L,0x20000L,0x40000L,0x80000L,
5439                 0x100000L,0x200000L,0x400000L,0x800000L,
5440                 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5441                 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5442         int idx;
5443         
5444         FENTRY;
5445         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5446         for(idx = 0; idx < 32; idx++)
5447                 if(lit == pw[idx])
5448                         return idx+1;
5449                 return 0;
5450 }
5451
5452 /*-----------------------------------------------------------------*/
5453 /* continueIfTrue -                                                */
5454 /*-----------------------------------------------------------------*/
5455 static void continueIfTrue (iCode *ic)
5456 {
5457         FENTRY;
5458         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5459         if(IC_TRUE(ic))
5460                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5461         ic->generated = 1;
5462 }
5463
5464 /*-----------------------------------------------------------------*/
5465 /* jmpIfTrue -                                                     */
5466 /*-----------------------------------------------------------------*/
5467 static void jumpIfTrue (iCode *ic)
5468 {
5469         FENTRY;
5470         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5471         if(!IC_TRUE(ic))
5472                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5473         ic->generated = 1;
5474 }
5475
5476 /*-----------------------------------------------------------------*/
5477 /* jmpTrueOrFalse -                                                */
5478 /*-----------------------------------------------------------------*/
5479 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5480 {
5481         FENTRY;
5482         // ugly but optimized by peephole
5483         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5484         if(IC_TRUE(ic)){
5485                 symbol *nlbl = newiTempLabel(NULL);
5486                 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5487                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5488                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5489                 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5490         }
5491         else{
5492                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5493                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5494         }
5495         ic->generated = 1;
5496 }
5497
5498 /*-----------------------------------------------------------------*/
5499 /* genAnd  - code for and                                          */
5500 /*-----------------------------------------------------------------*/
5501 static void genAnd (iCode *ic, iCode *ifx)
5502 {
5503         operand *left, *right, *result;
5504         int size, offset=0;  
5505         unsigned long lit = 0L;
5506         int bytelit = 0;
5507         resolvedIfx rIfx;
5508         
5509         FENTRY;
5510         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5511         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5512         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5513         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5514         
5515         resolveIfx(&rIfx,ifx);
5516         
5517         /* if left is a literal & right is not then exchange them */
5518         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5519                 AOP_NEEDSACC(left)) {
5520                 operand *tmp = right ;
5521                 right = left;
5522                 left = tmp;
5523         }
5524         
5525         /* if result = right then exchange them */
5526         if(pic14_sameRegs(AOP(result),AOP(right))){
5527                 operand *tmp = right ;
5528                 right = left;
5529                 left = tmp;
5530         }
5531         
5532         /* if right is bit then exchange them */
5533         if (AOP_TYPE(right) == AOP_CRY &&
5534                 AOP_TYPE(left) != AOP_CRY){
5535                 operand *tmp = right ;
5536                 right = left;
5537                 left = tmp;
5538         }
5539         if(AOP_TYPE(right) == AOP_LIT)
5540                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5541         
5542         size = AOP_SIZE(result);
5543         
5544         DEBUGpic14_AopType(__LINE__,left,right,result);
5545         
5546         // if(bit & yy)
5547         // result = bit & yy;
5548         if (AOP_TYPE(left) == AOP_CRY){
5549                 // c = bit & literal;
5550                 if(AOP_TYPE(right) == AOP_LIT){
5551                         if(lit & 1) {
5552                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5553                                         // no change
5554                                         goto release;
5555                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5556                         } else {
5557                                 // bit(result) = 0;
5558                                 if(size && (AOP_TYPE(result) == AOP_CRY)){
5559                                         pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5560                                         goto release;
5561                                 }
5562                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5563                                         jumpIfTrue(ifx);
5564                                         goto release;
5565                                 }
5566                                 pic14_emitcode("clr","c");
5567                         }
5568                 } else {
5569                         if (AOP_TYPE(right) == AOP_CRY){
5570                                 // c = bit & bit;
5571                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5572                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5573                         } else {
5574                                 // c = bit & val;
5575                                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5576                                 // c = lsb
5577                                 pic14_emitcode("rrc","a");
5578                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5579                         }
5580                 }
5581                 // bit = c
5582                 // val = c
5583                 if(size)
5584                         pic14_outBitC(result);
5585                 // if(bit & ...)
5586                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5587                         genIfxJump(ifx, "c");           
5588                 goto release ;
5589         }
5590         
5591         // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5592         // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5593         if((AOP_TYPE(right) == AOP_LIT) &&
5594                 (AOP_TYPE(result) == AOP_CRY) &&
5595                 (AOP_TYPE(left) != AOP_CRY)){
5596                 int posbit = isLiteralBit(lit);
5597                 /* left &  2^n */
5598                 if(posbit){
5599                         posbit--;
5600                         //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5601                         // bit = left & 2^n
5602                         if(size)
5603                                 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5604                         // if(left &  2^n)
5605                         else{
5606                                 if(ifx){
5607                                         int offset = 0;
5608                                         while (posbit > 7) {
5609                                                 posbit -= 8;
5610                                                 offset++;
5611                                         }
5612                                         emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5613                                                 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5614                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5615                                         
5616                                         ifx->generated = 1;
5617                                 }
5618                                 goto release;
5619                         }
5620                 } else {
5621                         symbol *tlbl = newiTempLabel(NULL);
5622                         int sizel = AOP_SIZE(left);
5623                         if(size)
5624                                 pic14_emitcode("setb","c");
5625                         while(sizel--){
5626                                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5627                                         MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5628                                         // byte ==  2^n ?
5629                                         if((posbit = isLiteralBit(bytelit)) != 0)
5630                                                 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5631                                         else{
5632                                                 if(bytelit != 0x0FFL)
5633                                                         pic14_emitcode("anl","a,%s",
5634                                                         aopGet(AOP(right),offset,FALSE,TRUE));
5635                                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5636                                         }
5637                                 }
5638                                 offset++;
5639                         }
5640                         // bit = left & literal
5641                         if(size){
5642                                 pic14_emitcode("clr","c");
5643                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5644                         }
5645                         // if(left & literal)
5646                         else{
5647                                 if(ifx)
5648                                         jmpTrueOrFalse(ifx, tlbl);
5649                                 goto release ;
5650                         }
5651                 }
5652                 pic14_outBitC(result);
5653                 goto release ;
5654         }
5655         
5656         /* if left is same as result */
5657         if(pic14_sameRegs(AOP(result),AOP(left))){
5658                 int know_W = -1;
5659                 for(;size--; offset++,lit>>=8) {
5660                         if(AOP_TYPE(right) == AOP_LIT){
5661                                 switch(lit & 0xff) {
5662                                 case 0x00:
5663                                         /*  and'ing with 0 has clears the result */
5664                                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
5665                                         break;
5666                                 case 0xff:
5667                                         /* and'ing with 0xff is a nop when the result and left are the same */
5668                                         break;
5669                                         
5670                                 default:
5671                                         {
5672                                                 int p = my_powof2( (~lit) & 0xff );
5673                                                 if(p>=0) {
5674                                                         /* only one bit is set in the literal, so use a bcf instruction */
5675                                                         emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5676                                                         
5677                                                 } else {
5678                                                         if(know_W != (int)(lit&0xff))
5679                                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5680                                                         know_W = lit &0xff;
5681                                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5682                                                 }
5683                                         }    
5684                                 }
5685                         } else {
5686                                 if (AOP_TYPE(left) == AOP_ACC) {
5687                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5688                                 } else {        
5689                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5690                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5691                                         
5692                                 }
5693                         }
5694                 }
5695                 
5696         } else {
5697                 // left & result in different registers
5698                 if(AOP_TYPE(result) == AOP_CRY){
5699                         // result = bit
5700                         // if(size), result in bit
5701                         // if(!size && ifx), conditional oper: if(left & right)
5702                         symbol *tlbl = newiTempLabel(NULL);
5703                         int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5704                         if(size)
5705                                 pic14_emitcode("setb","c");
5706                         while(sizer--){
5707                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5708                                 pic14_emitcode("anl","a,%s",
5709                                         aopGet(AOP(left),offset,FALSE,FALSE));
5710                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5711                                 offset++;
5712                         }
5713                         if(size){
5714                                 CLRC;
5715                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5716                                 pic14_outBitC(result);
5717                         } else if(ifx)
5718                                 jmpTrueOrFalse(ifx, tlbl);
5719                 } else {
5720                         for(;(size--);offset++) {
5721                                 // normal case
5722                                 // result = left & right
5723                                 if(AOP_TYPE(right) == AOP_LIT){
5724                                         int t = (lit >> (offset*8)) & 0x0FFL;
5725                                         switch(t) { 
5726                                         case 0x00:
5727                                                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5728                                                 break;
5729                                         case 0xff:
5730                                                 if(AOP_TYPE(left) != AOP_ACC) {
5731                                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5732                                                 }
5733                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5734                                                 break;
5735                                         default:
5736                                                 if(AOP_TYPE(left) == AOP_ACC) {
5737                                                         emitpcode(POC_ANDLW, popGetLit(t));
5738                                                 } else {
5739                                                         emitpcode(POC_MOVLW, popGetLit(t));
5740                                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5741                                                 }
5742                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5743                                         }
5744                                         continue;
5745                                 }
5746                                 
5747                                 if (AOP_TYPE(left) == AOP_ACC) {
5748                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5749                                 } else {
5750                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5751                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5752                                 }
5753                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5754                         }
5755                 }
5756         }
5757         
5758 release :
5759         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5760         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5761         freeAsmop(result,NULL,ic,TRUE);     
5762 }
5763
5764 /*-----------------------------------------------------------------*/
5765 /* genOr  - code for or                                            */
5766 /*-----------------------------------------------------------------*/
5767 static void genOr (iCode *ic, iCode *ifx)
5768 {
5769         operand *left, *right, *result;
5770         int size, offset=0;
5771         unsigned long lit = 0L;
5772         
5773         FENTRY;
5774         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5775         
5776         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5777         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5778         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5779         
5780         DEBUGpic14_AopType(__LINE__,left,right,result);
5781         
5782         /* if left is a literal & right is not then exchange them */
5783         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5784                 AOP_NEEDSACC(left)) {
5785                 operand *tmp = right ;
5786                 right = left;
5787                 left = tmp;
5788         }
5789         
5790         /* if result = right then exchange them */
5791         if(pic14_sameRegs(AOP(result),AOP(right))){
5792                 operand *tmp = right ;
5793                 right = left;
5794                 left = tmp;
5795         }
5796         
5797         /* if right is bit then exchange them */
5798         if (AOP_TYPE(right) == AOP_CRY &&
5799                 AOP_TYPE(left) != AOP_CRY){
5800                 operand *tmp = right ;
5801                 right = left;
5802                 left = tmp;
5803         }
5804         
5805         DEBUGpic14_AopType(__LINE__,left,right,result);
5806         
5807         if(AOP_TYPE(right) == AOP_LIT)
5808                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5809         
5810         size = AOP_SIZE(result);
5811         
5812         // if(bit | yy)
5813         // xx = bit | yy;
5814         if (AOP_TYPE(left) == AOP_CRY){
5815                 if(AOP_TYPE(right) == AOP_LIT){
5816                         // c = bit & literal;
5817                         if(lit){
5818                                 // lit != 0 => result = 1
5819                                 if(AOP_TYPE(result) == AOP_CRY){
5820                                         if(size)
5821                                                 emitpcode(POC_BSF, popGet(AOP(result),0));
5822                                         //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5823                                         //   AOP(result)->aopu.aop_dir,
5824                                         //   AOP(result)->aopu.aop_dir);
5825                                         else if(ifx)
5826                                                 continueIfTrue(ifx);
5827                                         goto release;
5828                                 }
5829                         } else {
5830                                 // lit == 0 => result = left
5831                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5832                                         goto release;
5833                                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5834                         }
5835                 } else {
5836                         if (AOP_TYPE(right) == AOP_CRY){
5837                                 if(pic14_sameRegs(AOP(result),AOP(left))){
5838                                         // c = bit | bit;
5839                                         emitpcode(POC_BCF,   popGet(AOP(result),0));
5840                                         emitpcode(POC_BTFSC, popGet(AOP(right),0));
5841                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5842                                         
5843                                         pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5844                                                 AOP(result)->aopu.aop_dir,
5845                                                 AOP(result)->aopu.aop_dir);
5846                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5847                                                 AOP(right)->aopu.aop_dir,
5848                                                 AOP(right)->aopu.aop_dir);
5849                                         pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5850                                                 AOP(result)->aopu.aop_dir,
5851                                                 AOP(result)->aopu.aop_dir);
5852                                 } else {
5853                                         if( AOP_TYPE(result) == AOP_ACC) {
5854                                                 emitpcode(POC_MOVLW, popGetLit(0));
5855                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5856                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5857                                                 emitpcode(POC_MOVLW, popGetLit(1));
5858                                                 
5859                                         } else {
5860                                                 
5861                                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5862                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5863                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5864                                                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5865                                                 
5866                                                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5867                                                         AOP(result)->aopu.aop_dir,
5868                                                         AOP(result)->aopu.aop_dir);
5869                                                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5870                                                         AOP(right)->aopu.aop_dir,
5871                                                         AOP(right)->aopu.aop_dir);
5872                                                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5873                                                         AOP(left)->aopu.aop_dir,
5874                                                         AOP(left)->aopu.aop_dir);
5875                                                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5876                                                         AOP(result)->aopu.aop_dir,
5877                                                         AOP(result)->aopu.aop_dir);
5878                                         }
5879                                 }
5880                         } else {
5881                                 // c = bit | val;
5882                                 symbol *tlbl = newiTempLabel(NULL);
5883                                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5884                                 
5885                                 
5886                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5887                                 if( AOP_TYPE(right) == AOP_ACC) {
5888                                         emitpcode(POC_IORLW, popGetLit(0));
5889                                         emitSKPNZ;
5890                                         emitpcode(POC_BTFSC, popGet(AOP(left),0));
5891                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5892                                 }
5893                                 
5894                                 
5895                                 
5896                                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5897                                         pic14_emitcode(";XXX setb","c");
5898                                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5899                                         AOP(left)->aopu.aop_dir,tlbl->key+100);
5900                                 pic14_toBoolean(right);
5901                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5902                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5903                                         jmpTrueOrFalse(ifx, tlbl);
5904                                         goto release;
5905                                 } else {
5906                                         CLRC;
5907                                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5908                                 }
5909                         }
5910                 }
5911                 // bit = c
5912                 // val = c
5913                 if(size)
5914                         pic14_outBitC(result);
5915                 // if(bit | ...)
5916                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5917                         genIfxJump(ifx, "c");           
5918                 goto release ;
5919         }
5920
5921         // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5922         // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5923         if((AOP_TYPE(right) == AOP_LIT) &&
5924           (AOP_TYPE(result) == AOP_CRY) &&
5925           (AOP_TYPE(left) != AOP_CRY)){
5926                 if(lit){
5927                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5928                         // result = 1
5929                         if(size)
5930                                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5931                         else 
5932                                 continueIfTrue(ifx);
5933                         goto release;
5934                 } else {
5935                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5936                         // lit = 0, result = boolean(left)
5937                         if(size)
5938                                 pic14_emitcode(";XXX setb","c");
5939                         pic14_toBoolean(right);
5940                         if(size){
5941                                 symbol *tlbl = newiTempLabel(NULL);
5942                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5943                                 CLRC;
5944                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5945                         } else {
5946                                 genIfxJump (ifx,"a");
5947                                 goto release;
5948                         }
5949                 }
5950                 pic14_outBitC(result);
5951                 goto release ;
5952         }
5953
5954         /* if left is same as result */
5955         if(pic14_sameRegs(AOP(result),AOP(left))){
5956                 int know_W = -1;
5957                 for(;size--; offset++,lit>>=8) {
5958                         if(AOP_TYPE(right) == AOP_LIT){
5959                                 if((lit & 0xff) == 0)
5960                                         /*  or'ing with 0 has no effect */
5961                                         continue;
5962                                 else {
5963                                         int p = my_powof2(lit & 0xff);
5964                                         if(p>=0) {
5965                                                 /* only one bit is set in the literal, so use a bsf instruction */
5966                                                 emitpcode(POC_BSF,
5967                                                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5968                                         } else {
5969                                                 if(know_W != (int)(lit & 0xff))
5970                                                         emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5971                                                 know_W = lit & 0xff;
5972                                                 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5973                                         }
5974                                         
5975                                 }
5976                         } else {
5977                                 if (AOP_TYPE(left) == AOP_ACC) {
5978                                         emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5979                                         pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5980                                 } else {        
5981                                         emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5982                                         emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5983                                         
5984                                         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5985                                         pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5986                                         
5987                                 }
5988                         }
5989                 }
5990         } else {
5991                 // left & result in different registers
5992                 if(AOP_TYPE(result) == AOP_CRY){
5993                         // result = bit
5994                         // if(size), result in bit
5995                         // if(!size && ifx), conditional oper: if(left | right)
5996                         symbol *tlbl = newiTempLabel(NULL);
5997                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5998                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5999                         
6000                         
6001                         if(size)
6002                                 pic14_emitcode(";XXX setb","c");
6003                         while(sizer--){
6004                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6005                                 pic14_emitcode(";XXX orl","a,%s",
6006                                         aopGet(AOP(left),offset,FALSE,FALSE));
6007                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6008                                 offset++;
6009                         }
6010                         if(size){
6011                                 CLRC;
6012                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6013                                 pic14_outBitC(result);
6014                         } else if(ifx)
6015                                 jmpTrueOrFalse(ifx, tlbl);
6016                 } else for(;(size--);offset++){
6017                         // normal case
6018                         // result = left | right
6019                         if(AOP_TYPE(right) == AOP_LIT){
6020                                 int t = (lit >> (offset*8)) & 0x0FFL;
6021                                 switch(t) { 
6022                                 case 0x00:
6023                                         if (AOP_TYPE(left) != AOP_ACC) {
6024                                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
6025                                         }
6026                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6027                                         
6028                                         break;
6029                                 default:
6030                                         if (AOP_TYPE(left) == AOP_ACC) {
6031                                                 emitpcode(POC_IORLW,  popGetLit(t));
6032                                         } else {
6033                                                 emitpcode(POC_MOVLW,  popGetLit(t));
6034                                                 emitpcode(POC_IORFW,  popGet(AOP(left),offset));
6035                                         }
6036                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));        
6037                                 }
6038                                 continue;
6039                         }
6040                         
6041                         // faster than result <- left, anl result,right
6042                         // and better if result is SFR
6043                         if (AOP_TYPE(left) == AOP_ACC) {
6044                                 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6045                         } else {
6046                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6047                                 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6048                         }
6049                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6050                 }
6051         }
6052
6053 release :
6054         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6055         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6056         freeAsmop(result,NULL,ic,TRUE);     
6057 }
6058
6059 /*-----------------------------------------------------------------*/
6060 /* genXor - code for xclusive or                                   */
6061 /*-----------------------------------------------------------------*/
6062 static void genXor (iCode *ic, iCode *ifx)
6063 {
6064         operand *left, *right, *result;
6065         int size, offset=0;
6066         unsigned long lit = 0L;
6067         
6068         FENTRY;
6069         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6070         
6071         aopOp((left = IC_LEFT(ic)),ic,FALSE);
6072         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6073         aopOp((result=IC_RESULT(ic)),ic,TRUE);
6074         
6075         /* if left is a literal & right is not ||
6076         if left needs acc & right does not */
6077         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6078                 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6079                 operand *tmp = right ;
6080                 right = left;
6081                 left = tmp;
6082         }
6083         
6084         /* if result = right then exchange them */
6085         if(pic14_sameRegs(AOP(result),AOP(right))){
6086                 operand *tmp = right ;
6087                 right = left;
6088                 left = tmp;
6089         }
6090         
6091         /* if right is bit then exchange them */
6092         if (AOP_TYPE(right) == AOP_CRY &&
6093                 AOP_TYPE(left) != AOP_CRY){
6094                 operand *tmp = right ;
6095                 right = left;
6096                 left = tmp;
6097         }
6098         if(AOP_TYPE(right) == AOP_LIT)
6099                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6100         
6101         size = AOP_SIZE(result);
6102         
6103         // if(bit ^ yy)
6104         // xx = bit ^ yy;
6105         if (AOP_TYPE(left) == AOP_CRY){
6106                 if(AOP_TYPE(right) == AOP_LIT){
6107                         // c = bit & literal;
6108                         if(lit>>1){
6109                                 // lit>>1  != 0 => result = 1
6110                                 if(AOP_TYPE(result) == AOP_CRY){
6111                                         if(size)
6112                                         {emitpcode(POC_BSF,  popGet(AOP(result),offset));
6113                                         pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6114                                         else if(ifx)
6115                                                 continueIfTrue(ifx);
6116                                         goto release;
6117                                 }
6118                                 pic14_emitcode("setb","c");
6119                         } else{
6120                                 // lit == (0 or 1)
6121                                 if(lit == 0){
6122                                         // lit == 0, result = left
6123                                         if(size && pic14_sameRegs(AOP(result),AOP(left)))
6124                                                 goto release;
6125                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6126                                 } else{
6127                                         // lit == 1, result = not(left)
6128                                         if(size && pic14_sameRegs(AOP(result),AOP(left))){
6129                                                 emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
6130                                                 emitpcode(POC_XORWF,  popGet(AOP(result),offset));
6131                                                 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6132                                                 goto release;
6133                                         } else {
6134                                                 assert ( !"incomplete genXor" );
6135                                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6136                                                 pic14_emitcode("cpl","c");
6137                                         }
6138                                 }
6139                         }
6140                         
6141                 } else {
6142                         // right != literal
6143                         symbol *tlbl = newiTempLabel(NULL);
6144                         if (AOP_TYPE(right) == AOP_CRY){
6145                                 // c = bit ^ bit;
6146                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6147                         }
6148                         else{
6149                                 int sizer = AOP_SIZE(right);
6150                                 // c = bit ^ val
6151                                 // if val>>1 != 0, result = 1
6152                                 pic14_emitcode("setb","c");
6153                                 while(sizer){
6154                                         MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6155                                         if(sizer == 1)
6156                                                 // test the msb of the lsb
6157                                                 pic14_emitcode("anl","a,#0xfe");
6158                                         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6159                                         sizer--;
6160                                 }
6161                                 // val = (0,1)
6162                                 pic14_emitcode("rrc","a");
6163                         }
6164                         pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6165                         pic14_emitcode("cpl","c");
6166                         pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6167                 }
6168                 // bit = c
6169                 // val = c
6170                 if(size)
6171                         pic14_outBitC(result);
6172                 // if(bit | ...)
6173                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6174                         genIfxJump(ifx, "c");           
6175                 goto release ;
6176         }
6177         
6178         if(pic14_sameRegs(AOP(result),AOP(left))){
6179                 /* if left is same as result */
6180                 for(;size--; offset++) {
6181                         if(AOP_TYPE(right) == AOP_LIT){
6182                                 int t  = (lit >> (offset*8)) & 0x0FFL;
6183                                 if(t == 0x00L)
6184                                         continue;
6185                                 else
6186                                         if (IS_AOP_PREG(left)) {
6187                                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6188                                                 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6189                                                 aopPut(AOP(result),"a",offset);
6190                                         } else {
6191                                                 emitpcode(POC_MOVLW, popGetLit(t));
6192                                                 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6193                                                 pic14_emitcode("xrl","%s,%s",
6194                                                         aopGet(AOP(left),offset,FALSE,TRUE),
6195                                                         aopGet(AOP(right),offset,FALSE,FALSE));
6196                                         }
6197                         } else {
6198                                 if (AOP_TYPE(left) == AOP_ACC)
6199                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6200                                 else {
6201                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6202                                         emitpcode(POC_XORWF,popGet(AOP(left),offset));
6203                                         /*
6204                                         if (IS_AOP_PREG(left)) {
6205                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6206                                         aopPut(AOP(result),"a",offset);
6207                                         } else
6208                                         pic14_emitcode("xrl","%s,a",
6209                                         aopGet(AOP(left),offset,FALSE,TRUE));
6210                                         */
6211                                 }
6212                         }
6213                 }
6214         } else {
6215                 // left & result in different registers
6216                 if(AOP_TYPE(result) == AOP_CRY){
6217                         // result = bit
6218                         // if(size), result in bit
6219                         // if(!size && ifx), conditional oper: if(left ^ right)
6220                         symbol *tlbl = newiTempLabel(NULL);
6221                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6222                         if(size)
6223                                 pic14_emitcode("setb","c");
6224                         while(sizer--){
6225                                 if((AOP_TYPE(right) == AOP_LIT) &&
6226                                         (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6227                                         MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6228                                 } else {
6229                                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6230                                         pic14_emitcode("xrl","a,%s",
6231                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6232                                 }
6233                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6234                                 offset++;
6235                         }
6236                         if(size){
6237                                 CLRC;
6238                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6239                                 pic14_outBitC(result);
6240                         } else if(ifx)
6241                                 jmpTrueOrFalse(ifx, tlbl);
6242                 } else for(;(size--);offset++){
6243                         // normal case
6244                         // result = left & right
6245                         if(AOP_TYPE(right) == AOP_LIT){
6246                                 int t = (lit >> (offset*8)) & 0x0FFL;
6247                                 switch(t) { 
6248                                 case 0x00:
6249                                         if (AOP_TYPE(left) != AOP_ACC) {
6250                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6251                                         }
6252                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6253                                         pic14_emitcode("movf","%s,w",
6254                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6255                                         pic14_emitcode("movwf","%s",
6256                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6257                                         break;
6258                                 case 0xff:
6259                                         if (AOP_TYPE(left) == AOP_ACC) {
6260                                                 emitpcode(POC_XORLW, popGetLit(t));
6261                                         } else {
6262                                                 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6263                                         }
6264                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6265                                         break;
6266                                 default:
6267                                         if (AOP_TYPE(left) == AOP_ACC) {
6268                                                 emitpcode(POC_XORLW, popGetLit(t));
6269                                         } else {
6270                                                 emitpcode(POC_MOVLW, popGetLit(t));
6271                                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6272                                         }
6273                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6274                                         pic14_emitcode("movlw","0x%x",t);
6275                                         pic14_emitcode("xorwf","%s,w",
6276                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6277                                         pic14_emitcode("movwf","%s",
6278                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6279                                         
6280                                 }
6281                                 continue;
6282                         }
6283                         
6284                         // faster than result <- left, anl result,right
6285                         // and better if result is SFR
6286                         if (AOP_TYPE(left) == AOP_ACC) {
6287                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6288                         } else {
6289                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6290                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6291                         }
6292                         if ( AOP_TYPE(result) != AOP_ACC){
6293                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6294                         }
6295                 }
6296         }
6297         
6298 release :
6299         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6300         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6301         freeAsmop(result,NULL,ic,TRUE);     
6302 }
6303
6304 /*-----------------------------------------------------------------*/
6305 /* genInline - write the inline code out                           */
6306 /*-----------------------------------------------------------------*/
6307 static void genInline (iCode *ic)
6308 {
6309   char *buffer, *bp, *bp1;
6310
6311   FENTRY;
6312   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6313
6314   _G.inLine += (!options.asmpeep);
6315
6316   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6317   strcpy(buffer,IC_INLINE(ic));
6318
6319   /* emit each line as a code */
6320   while (*bp) {
6321     if (*bp == '\n') {
6322       *bp++ = '\0';
6323       
6324       if(*bp1)
6325         addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6326       bp1 = bp;
6327     } else {
6328       if (*bp == ':') {
6329         bp++;
6330         *bp = '\0';
6331         bp++;
6332
6333         /* print label, use this special format with NULL directive
6334          * to denote that the argument should not be indented with tab */
6335         addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6336
6337         bp1 = bp;
6338       } else
6339         bp++;
6340     }
6341   }
6342   if ((bp1 != bp) && *bp1)
6343     addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6344
6345   Safe_free(buffer);
6346
6347   _G.inLine -= (!options.asmpeep);
6348 }
6349
6350 /*-----------------------------------------------------------------*/
6351 /* genRRC - rotate right with carry                                */
6352 /*-----------------------------------------------------------------*/
6353 static void genRRC (iCode *ic)
6354 {
6355         operand *left , *result ;
6356         int size, offset = 0, same;
6357         
6358         FENTRY;
6359         /* rotate right with carry */
6360         left = IC_LEFT(ic);
6361         result=IC_RESULT(ic);
6362         aopOp (left,ic,FALSE);
6363         aopOp (result,ic,FALSE);
6364         
6365         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6366         
6367         same = pic14_sameRegs(AOP(result),AOP(left));
6368         
6369         size = AOP_SIZE(result);    
6370         
6371         /* get the lsb and put it into the carry */
6372         emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6373         
6374         offset = 0 ;
6375         
6376         while(size--) {
6377                 
6378                 if(same) {
6379                         emitpcode(POC_RRF, popGet(AOP(left),offset));
6380                 } else {
6381                         emitpcode(POC_RRFW, popGet(AOP(left),offset));
6382                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6383                 }
6384                 
6385                 offset++;
6386         }
6387         
6388         freeAsmop(left,NULL,ic,TRUE);
6389         freeAsmop(result,NULL,ic,TRUE);
6390 }
6391
6392 /*-----------------------------------------------------------------*/
6393 /* genRLC - generate code for rotate left with carry               */
6394 /*-----------------------------------------------------------------*/
6395 static void genRLC (iCode *ic)
6396 {    
6397         operand *left , *result ;
6398         int size, offset = 0;
6399         int same;
6400         
6401         FENTRY;
6402         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6403         /* rotate right with carry */
6404         left = IC_LEFT(ic);
6405         result=IC_RESULT(ic);
6406         aopOp (left,ic,FALSE);
6407         aopOp (result,ic,FALSE);
6408         
6409         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6410         
6411         same = pic14_sameRegs(AOP(result),AOP(left));
6412         
6413         /* move it to the result */
6414         size = AOP_SIZE(result);    
6415         
6416         /* get the msb and put it into the carry */
6417         emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6418         
6419         offset = 0 ;
6420         
6421         while(size--) {
6422                 
6423                 if(same) {
6424                         emitpcode(POC_RLF, popGet(AOP(left),offset));
6425                 } else {
6426                         emitpcode(POC_RLFW, popGet(AOP(left),offset));
6427                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6428                 }
6429                 
6430                 offset++;
6431         }
6432         
6433         
6434         freeAsmop(left,NULL,ic,TRUE);
6435         freeAsmop(result,NULL,ic,TRUE);
6436 }
6437
6438 /*-----------------------------------------------------------------*/
6439 /* genGetHbit - generates code get highest order bit               */
6440 /*-----------------------------------------------------------------*/
6441 static void genGetHbit (iCode *ic)
6442 {
6443         operand *left, *result;
6444         left = IC_LEFT(ic);
6445         result=IC_RESULT(ic);
6446         aopOp (left,ic,FALSE);
6447         aopOp (result,ic,FALSE);
6448         
6449         FENTRY;
6450         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6451         /* get the highest order byte into a */
6452         MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6453         if(AOP_TYPE(result) == AOP_CRY){
6454                 pic14_emitcode("rlc","a");
6455                 pic14_outBitC(result);
6456         }
6457         else{
6458                 pic14_emitcode("rl","a");
6459                 pic14_emitcode("anl","a,#0x01");
6460                 pic14_outAcc(result);
6461         }
6462         
6463         
6464         freeAsmop(left,NULL,ic,TRUE);
6465         freeAsmop(result,NULL,ic,TRUE);
6466 }
6467
6468 /*-----------------------------------------------------------------*/
6469 /* AccLsh - shift left accumulator by known count                  */
6470 /* MARK: pic14 always rotates through CARRY!                       */
6471 /*-----------------------------------------------------------------*/
6472 static void AccLsh (pCodeOp *pcop,int shCount)
6473 {
6474         FENTRY;
6475         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6476         shCount &= 0x0007;              // shCount : 0..7
6477         switch(shCount){
6478         case 0 :
6479                 return;
6480                 break;
6481         case 1 :
6482                 emitCLRC;
6483                 emitpcode(POC_RLF,pcop);
6484                 return;
6485                 break;
6486         case 2 :
6487                 emitpcode(POC_RLF,pcop);
6488                 emitpcode(POC_RLF,pcop);
6489                 break;
6490         case 3 :
6491                 emitpcode(POC_RLF,pcop);
6492                 emitpcode(POC_RLF,pcop);
6493                 emitpcode(POC_RLF,pcop);
6494                 break;
6495         case 4 :
6496                 emitpcode(POC_SWAPF,pcop);
6497                 break;
6498         case 5 :
6499                 emitpcode(POC_SWAPF,pcop);
6500                 emitpcode(POC_RLF,pcop);
6501                 break;
6502         case 6 :
6503                 emitpcode(POC_SWAPF,pcop);
6504                 emitpcode(POC_RLF,pcop);
6505                 emitpcode(POC_RLF,pcop);
6506                 break;
6507         case 7 :
6508                 emitpcode(POC_RRFW,pcop);
6509                 emitpcode(POC_RRF,pcop);
6510                 break;
6511         }
6512         /* clear invalid bits */
6513         emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6514         emitpcode(POC_ANDWF, pcop);
6515 }
6516
6517 /*-----------------------------------------------------------------*/
6518 /* AccRsh - shift right accumulator by known count                 */
6519 /* MARK: pic14 always rotates through CARRY!                       */
6520 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6521 /*            1: mask out invalid bits (zero-extend)               */
6522 /*            2: sign-extend result (pretty slow)                  */
6523 /*-----------------------------------------------------------------*/
6524 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6525 {
6526         FENTRY;
6527         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6528         shCount &= 0x0007;              // shCount : 0..7
6529         switch(shCount){
6530         case 0 :
6531                 return;
6532                 break;
6533         case 1 :
6534                 /* load sign if needed */
6535                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6536                 else if (mask_mode == 1) emitCLRC;
6537                 emitpcode(POC_RRF,pcop);
6538                 return;
6539                 break;
6540         case 2 :
6541                 /* load sign if needed */
6542                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6543                 emitpcode(POC_RRF,pcop);
6544                 /* load sign if needed */
6545                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6546                 emitpcode(POC_RRF,pcop);
6547                 if (mask_mode == 2) return;
6548                 break;
6549         case 3 :
6550                 /* load sign if needed */
6551                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6552                 emitpcode(POC_RRF,pcop);
6553                 /* load sign if needed */
6554                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6555                 emitpcode(POC_RRF,pcop);
6556                 /* load sign if needed */
6557                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6558                 emitpcode(POC_RRF,pcop);
6559                 if (mask_mode == 2) return;
6560                 break;
6561         case 4 :
6562                 emitpcode(POC_SWAPF,pcop);
6563                 break;
6564         case 5 :
6565                 emitpcode(POC_SWAPF,pcop);
6566                 emitpcode(POC_RRF,pcop);
6567                 break;
6568         case 6 :
6569                 emitpcode(POC_SWAPF,pcop);
6570                 emitpcode(POC_RRF,pcop);
6571                 emitpcode(POC_RRF,pcop);
6572                 break;
6573         case 7 :
6574                 if (mask_mode == 2)
6575                 {
6576                         /* load sign */
6577                         emitpcode(POC_RLFW,pcop);
6578                         emitpcode(POC_CLRF,pcop);
6579                         emitSKPNC;
6580                         emitpcode(POC_COMF,pcop);
6581                         return;
6582                 } else {
6583                         emitpcode(POC_RLFW,pcop);
6584                         emitpcode(POC_RLF,pcop);
6585                 }
6586                 break;
6587         }
6588
6589         if (mask_mode == 0)
6590         {
6591                 /* leave invalid bits undefined */
6592                 return;
6593         }
6594         
6595         /* clear invalid bits -- zero-extend */
6596         emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6597         emitpcode(POC_ANDWF, pcop);
6598
6599         if (mask_mode == 2) {
6600           /* sign-extend */
6601           emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6602           emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6603           emitpcode(POC_IORWF, pcop);
6604         }
6605 }
6606
6607 #if 0
6608 /*-----------------------------------------------------------------*/
6609 /* AccSRsh - signed right shift accumulator by known count                 */
6610 /*-----------------------------------------------------------------*/
6611 static void AccSRsh (int shCount)
6612 {
6613         symbol *tlbl ;
6614         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6615         if(shCount != 0){
6616                 if(shCount == 1){
6617                         pic14_emitcode("mov","c,acc.7");
6618                         pic14_emitcode("rrc","a");
6619                 } else if(shCount == 2){
6620                         pic14_emitcode("mov","c,acc.7");
6621                         pic14_emitcode("rrc","a");
6622                         pic14_emitcode("mov","c,acc.7");
6623                         pic14_emitcode("rrc","a");
6624                 } else {
6625                         tlbl = newiTempLabel(NULL);
6626                         /* rotate right accumulator */
6627                         AccRol(8 - shCount);
6628                         /* and kill the higher order bits */
6629                         pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6630                         pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6631                         pic14_emitcode("orl","a,#0x%02x",
6632                                 (unsigned char)~SRMask[shCount]);
6633                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6634                 }
6635         }
6636 }
6637
6638 /*-----------------------------------------------------------------*/
6639 /* shiftR1Left2Result - shift right one byte from left to result   */
6640 /*-----------------------------------------------------------------*/
6641 static void shiftR1Left2ResultSigned (operand *left, int offl,
6642                                                                           operand *result, int offr,
6643                                                                           int shCount)
6644 {
6645         int same;
6646         
6647         FENTRY;
6648         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6649         
6650         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6651         
6652         switch(shCount) {
6653         case 1:
6654                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6655                 if(same) 
6656                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6657                 else {
6658                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6659                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6660                 }
6661                 
6662                 break;
6663         case 2:
6664                 
6665                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6666                 if(same) 
6667                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6668                 else {
6669                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6670                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6671                 }
6672                 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6673                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6674                 
6675                 break;
6676                 
6677         case 3:
6678                 if(same)
6679                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6680                 else {
6681                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6682                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6683                 }
6684                 
6685                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6686                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6687                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6688                 
6689                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6690                 emitpcode(POC_IORLW, popGetLit(0xe0));
6691                 
6692                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6693                 break;
6694                 
6695         case 4:
6696                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6697                 emitpcode(POC_ANDLW,  popGetLit(0x0f));
6698                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6699                 emitpcode(POC_IORLW,  popGetLit(0xf0));
6700                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6701                 break;
6702         case 5:
6703                 if(same) {
6704                         emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6705                 } else {
6706                         emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6707                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6708                 }
6709                 emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6710                 emitpcode(POC_ANDLW,  popGetLit(0x07));
6711                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6712                 emitpcode(POC_IORLW,  popGetLit(0xf8));
6713                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6714                 break;
6715                 
6716         case 6:
6717                 if(same) {
6718                         emitpcode(POC_MOVLW, popGetLit(0x00));
6719                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6720                         emitpcode(POC_MOVLW, popGetLit(0xfe));
6721                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6722                         emitpcode(POC_IORLW, popGetLit(0x01));
6723                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6724                 } else {
6725                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6726                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6727                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6728                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6729                         emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6730                 }
6731                 break;
6732                 
6733         case 7:
6734                 if(same) {
6735                         emitpcode(POC_MOVLW, popGetLit(0x00));
6736                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6737                         emitpcode(POC_MOVLW, popGetLit(0xff));
6738                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6739                 } else {
6740                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6741                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6742                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6743                 }
6744                 
6745         default:
6746                 break;
6747         }
6748 }
6749
6750 /*-----------------------------------------------------------------*/
6751 /* shiftR1Left2Result - shift right one byte from left to result   */
6752 /*-----------------------------------------------------------------*/
6753 static void shiftR1Left2Result (operand *left, int offl,
6754                                                                 operand *result, int offr,
6755                                                                 int shCount, int sign)
6756 {
6757         int same;
6758         
6759         FENTRY;
6760         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6761         
6762         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6763         
6764         /* Copy the msb into the carry if signed. */
6765         if(sign) {
6766                 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6767                 return;
6768         }
6769         
6770         
6771         
6772         switch(shCount) {
6773         case 1:
6774                 emitCLRC;
6775                 if(same) 
6776                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6777                 else {
6778                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6779                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6780                 }
6781                 break;
6782         case 2:
6783                 emitCLRC;
6784                 if(same) {
6785                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6786                 } else {
6787                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6788                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6789                 }
6790                 emitCLRC;
6791                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6792                 
6793                 break;
6794         case 3:
6795                 if(same)
6796                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6797                 else {
6798                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6799                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6800                 }
6801                 
6802                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6803                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6804                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6805                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6806                 break;
6807                 
6808         case 4:
6809                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6810                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6811                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6812                 break;
6813                 
6814         case 5:
6815                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6816                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6817                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6818                 emitCLRC;
6819                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6820                 
6821                 break;
6822         case 6:
6823                 
6824                 emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6825                 emitpcode(POC_ANDLW, popGetLit(0x80));
6826                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6827                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6828                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6829                 break;
6830                 
6831         case 7:
6832                 
6833                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6834                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6835                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6836                 
6837                 break;
6838                 
6839         default:
6840                 break;
6841         }
6842 }
6843
6844 /*-----------------------------------------------------------------*/
6845 /* shiftL1Left2Result - shift left one byte from left to result    */
6846 /*-----------------------------------------------------------------*/
6847 static void shiftL1Left2Result (operand *left, int offl,
6848                                                                 operand *result, int offr, int shCount)
6849 {
6850         int same;
6851         
6852         //    char *l;
6853         FENTRY;
6854         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6855         
6856         same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6857         DEBUGpic14_emitcode ("; ***","same =  %d",same);
6858         //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6859         //    MOVA(l);
6860         /* shift left accumulator */
6861         //AccLsh(shCount); // don't comment out just yet...
6862         //    aopPut(AOP(result),"a",offr);
6863         
6864         switch(shCount) {
6865         case 1:
6866                 /* Shift left 1 bit position */
6867                 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6868                 if(same) {
6869                         emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6870                 } else {
6871                         emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6872                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6873                 }
6874                 break;
6875         case 2:
6876                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6877                 emitpcode(POC_ANDLW,popGetLit(0x7e));
6878                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6879                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6880                 break;
6881         case 3:
6882                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6883                 emitpcode(POC_ANDLW,popGetLit(0x3e));
6884                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6885                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6886                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6887                 break;
6888         case 4:
6889                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6890                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6891                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6892                 break;
6893         case 5:
6894                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6895                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6896                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6897                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6898                 break;
6899         case 6:
6900                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6901                 emitpcode(POC_ANDLW, popGetLit(0x30));
6902                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6903                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6904                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6905                 break;
6906         case 7:
6907                 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6908                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6909                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6910                 break;
6911                 
6912         default:
6913                 DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6914         }
6915         
6916 }
6917 #endif
6918
6919 /*-----------------------------------------------------------------*/
6920 /* movLeft2Result - move byte from left to result                  */
6921 /*-----------------------------------------------------------------*/
6922 static void movLeft2Result (operand *left, int offl,
6923                                                         operand *result, int offr)
6924 {
6925         char *l;
6926         FENTRY;
6927         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6928         if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6929                 l = aopGet(AOP(left),offl,FALSE,FALSE);
6930                 
6931                 if (*l == '@' && (IS_AOP_PREG(result))) {
6932                         pic14_emitcode("mov","a,%s",l);
6933                         aopPut(AOP(result),"a",offr);
6934                 } else {
6935                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6936                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6937                 }
6938         }
6939 }
6940
6941 /*-----------------------------------------------------------------*/
6942 /* shiftLeft_Left2ResultLit - shift left by known count            */
6943 /*-----------------------------------------------------------------*/
6944
6945 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6946 {
6947         int size, same, offr, i;
6948
6949         size = AOP_SIZE(left);
6950         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6951         
6952         same = pic14_sameRegs (AOP(left), AOP(result));
6953         
6954         offr = shCount / 8;
6955         shCount = shCount & 0x07;
6956
6957         size -= offr;
6958
6959         switch (shCount)
6960         {
6961         case 0: /* takes 0 or 2N cycles (for offr==0) */
6962                 if (!same || offr) {
6963                         for (i=size-1; i >= 0; i--)
6964                                 movLeft2Result (left, i, result, offr + i);
6965                 } // if
6966                 break;
6967                 
6968         case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6969                 if (same && offr) {
6970                         shiftLeft_Left2ResultLit (left, result, 8 * offr);
6971                         shiftLeft_Left2ResultLit (result, result, shCount);
6972                         return; /* prevent clearing result again */
6973                 } else {
6974                         emitCLRC;
6975                         for (i=0; i < size; i++) {
6976                                 if (same && !offr) {
6977                                         emitpcode (POC_RLF, popGet (AOP(left), i));
6978                                 } else {
6979                                         emitpcode (POC_RLFW, popGet (AOP(left), i));
6980                                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6981                                 } // if
6982                         } // for
6983                 } // if (offr)
6984                 break;
6985                 
6986         case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6987                 /* works in-place/with offr as well */
6988                 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6989                 emitpcode (POC_ANDLW, popGetLit (0xF0));
6990                 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6991
6992                 for (i = size - 2; i >= 0; i--)
6993                 {
6994                         emitpcode (POC_SWAPFW, popGet (AOP(left), i));
6995                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6996                         emitpcode (POC_ANDLW, popGetLit (0x0F));
6997                         emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
6998                         emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
6999                 } // for i
7000                 break;
7001                 
7002         case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7003                 /* works in-place/with offr as well */
7004                 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7005                 for (i = size-2; i >= 0; i--) {
7006                         emitpcode (POC_RRFW, popGet (AOP(left), i));
7007                         emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7008                 } // for i
7009                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7010                 emitpcode (POC_RRF, popGet (AOP(result), offr));
7011                 break;
7012         
7013         default:
7014                 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7015                 shiftLeft_Left2ResultLit (result, result, 1);
7016                 return; /* prevent clearing result again */
7017                 break;
7018         } // switch
7019
7020         while (0 < offr--)
7021         {
7022                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7023         } // while
7024 }
7025
7026 /*-----------------------------------------------------------------*/
7027 /* shiftRight_Left2ResultLit - shift right by known count          */
7028 /*-----------------------------------------------------------------*/
7029
7030 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7031 {
7032         int size, same, offr, i;
7033
7034         size = AOP_SIZE(left);
7035         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7036         
7037         same = pic14_sameRegs (AOP(left), AOP(result));
7038         
7039         offr = shCount / 8;
7040         shCount = shCount & 0x07;
7041
7042         size -= offr;
7043
7044         if (size)
7045         {
7046                 switch (shCount)
7047                 {
7048                 case 0: /* takes 0 or 2N cycles (for offr==0) */
7049                         if (!same || offr) {
7050                                 for (i=0; i < size; i++)
7051                                         movLeft2Result (left, i + offr, result, i);
7052                         } // if
7053                         break;
7054                         
7055                 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7056                         emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7057                         if (same && offr) {
7058                                 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7059                                 shiftRight_Left2ResultLit (result, result, shCount, sign);
7060                                 return; /* prevent sign-extending result again */
7061                         } else {
7062                                 emitCLRC;
7063                                 if (sign) {
7064                                         emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7065                                         emitSETC;
7066                                 }
7067                                 for (i = size-1; i >= 0; i--) {
7068                                         if (same && !offr) {
7069                                                 emitpcode (POC_RRF, popGet (AOP(left), i));
7070                                         } else {
7071                                                 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7072                                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7073                                         }
7074                                 } // for i
7075                         } // if (offr)
7076                         break;
7077                         
7078                 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7079                         /* works in-place/with offr as well */
7080                         emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7081                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7082                         emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7083
7084                         for (i = 1; i < size; i++)
7085                         {
7086                                 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7087                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7088                                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7089                                 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7090                                 emitpcode (POC_XORWF, popGet (AOP(result), i));
7091                         } // for i
7092
7093                         if (sign)
7094                         {
7095                                 emitpcode (POC_MOVLW, popGetLit (0xF0));
7096                                 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7097                                 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7098                         } // if
7099                         break;
7100                         
7101                 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7102                         /* works in-place/with offr as well */
7103                         emitpcode (POC_RLFW, popGet (AOP(left), offr));
7104                         for (i = 0; i < size-1; i++) {
7105                                 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7106                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7107                         } // for i
7108                         emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7109                         if (!sign) {
7110                                 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7111                         } else {
7112                                 emitSKPNC;
7113                                 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7114                         }
7115                         break;
7116                 
7117                 default:
7118                         shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7119                         shiftRight_Left2ResultLit (result, result, 1, sign);
7120                         return; /* prevent sign extending result again */
7121                         break;
7122                 } // switch
7123         } // if
7124
7125         addSign (result, size, sign);
7126 }
7127
7128 #if 0
7129 /*-----------------------------------------------------------------*/
7130 /* shiftL2Left2Result - shift left two bytes from left to result   */
7131 /*-----------------------------------------------------------------*/
7132 static void shiftL2Left2Result (operand *left, int offl,
7133                                                                 operand *result, int offr, int shCount)
7134 {
7135         FENTRY;
7136         
7137         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7138         
7139         if(pic14_sameRegs(AOP(result), AOP(left))) {
7140                 switch(shCount) {
7141                 case 0:
7142                         break;
7143                 case 1:
7144                 case 2:
7145                 case 3:
7146                         
7147                         emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7148                         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7149                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7150                         
7151                         while(--shCount) {
7152                                 emitCLRC;
7153                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7154                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7155                         }
7156                         
7157                         break;
7158                 case 4:
7159                 case 5:
7160                         emitpcode(POC_MOVLW, popGetLit(0x0f));
7161                         emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7162                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7163                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7164                         emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7165                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7166                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7167                         if(shCount >=5) {
7168                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7169                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7170                         }
7171                         break;
7172                 case 6:
7173                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7174                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7175                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7176                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7177                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7178                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7179                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7180                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7181                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7182                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7183                         break;
7184                 case 7:
7185                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7186                         emitpcode(POC_RRFW, popGet(AOP(result),offr));
7187                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7188                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7189                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7190                 }
7191                 
7192         } else {
7193                 switch(shCount) {
7194                 case 0:
7195                         break;
7196                 case 1:
7197                 case 2:
7198                 case 3:
7199                 /* note, use a mov/add for the shift since the mov has a
7200                         chance of getting optimized out */
7201                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7202                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7203                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7204                         emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
7205                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7206                         
7207                         while(--shCount) {
7208                                 emitCLRC;
7209                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7210                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7211                         }
7212                         break;
7213                         
7214                 case 4:
7215                 case 5:
7216                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7217                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7218                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7219                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7220                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7221                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7222                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7223                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7224                         
7225                         
7226                         if(shCount == 5) {
7227                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7228                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7229                         }
7230                         break;
7231                 case 6:
7232                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7233                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7234                         emitpcode(POC_RRFW, popGet(AOP(result),offl));
7235                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
7236                         
7237                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7238                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7239                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7240                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7241                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7242                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7243                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7244                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7245                         break;
7246                 case 7:
7247                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7248                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7249                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7250                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7251                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7252                 }
7253         }
7254         
7255 }
7256
7257 /*-----------------------------------------------------------------*/
7258 /* shiftR2Left2Result - shift right two bytes from left to result  */
7259 /*-----------------------------------------------------------------*/
7260 static void shiftR2Left2Result (operand *left, int offl,
7261                                                                 operand *result, int offr,
7262                                                                 int shCount, int sign)
7263 {
7264         int same=0;
7265         
7266         FENTRY;
7267         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7268         same = pic14_sameRegs(AOP(result), AOP(left));
7269         
7270         if(same && ((offl + MSB16) == offr)){
7271                 same=1;
7272                 /* don't crash result[offr] */
7273                 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7274                 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7275         }
7276         /* else {
7277         movLeft2Result(left,offl, result, offr);
7278         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7279         }
7280         */
7281         /* a:x >> shCount (x = lsb(result))*/
7282         /*
7283         if(sign)
7284         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7285         else {
7286         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7287         */
7288         switch(shCount) {
7289         case 0:
7290                 break;
7291         case 1:
7292         case 2:
7293         case 3:
7294                 if(sign)
7295                         emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7296                 else
7297                         emitCLRC;
7298                 
7299                 if(same) {
7300                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7301                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7302                 } else {
7303                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7304                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7305                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7306                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7307                 }
7308                 
7309                 while(--shCount) {
7310                         if(sign)
7311                                 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7312                         else
7313                                 emitCLRC;
7314                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7315                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7316                 }
7317                 break;
7318         case 4:
7319         case 5:
7320                 if(same) {
7321                         
7322                         emitpcode(POC_MOVLW, popGetLit(0xf0));
7323                         emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7324                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7325                         
7326                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7327                         emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7328                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7329                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7330                 } else {
7331                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7332                         emitpcode(POC_ANDLW, popGetLit(0x0f));
7333                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7334                         
7335                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7336                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7337                         emitpcode(POC_ANDLW, popGetLit(0xf0));
7338                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7339                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7340                 }
7341                 
7342                 if(shCount >=5) {
7343                         emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7344                         emitpcode(POC_RRF, popGet(AOP(result),offr));
7345                 }
7346                 
7347                 if(sign) {
7348                         emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7349                         emitpcode(POC_BTFSC, 
7350                                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7351                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7352                 }
7353                 
7354                 break;
7355                 
7356         case 6:
7357                 if(same) {
7358                         
7359                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7360                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7361                         
7362                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7363                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7364                         emitpcode(POC_RLFW, popGet(AOP(result),offr));
7365                         emitpcode(POC_ANDLW,popGetLit(0x03));
7366                         if(sign) {
7367                                 emitpcode(POC_BTFSC, 
7368                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7369                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7370                         }
7371                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7372                         emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7373                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7374                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7375                 } else {
7376                         emitpcode(POC_RLFW, popGet(AOP(left),offl));
7377                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7378                         emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7379                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7380                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7381                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7382                         emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7383                         emitpcode(POC_ANDLW,popGetLit(0x03));
7384                         if(sign) {
7385                                 emitpcode(POC_BTFSC, 
7386                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7387                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7388                         }
7389                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7390                         //emitpcode(POC_RLF,  popGet(AOP(result),offr));
7391                         
7392                         
7393                 }
7394                 
7395                 break;
7396         case 7:
7397                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7398                 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7399                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7400                 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7401                 if(sign) {
7402                         emitSKPNC;
7403                         emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7404                 } else 
7405                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7406   }
7407 }
7408
7409 /*-----------------------------------------------------------------*/
7410 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7411 /*-----------------------------------------------------------------*/
7412 static void shiftLLeftOrResult (operand *left, int offl,
7413                                                                 operand *result, int offr, int shCount)
7414 {
7415         FENTRY;
7416         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7417         
7418         /* shift left accumulator */
7419         AccLsh(left,offl,shCount);
7420         /* or with result */
7421         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7422         assert ( !"broken (modifies left, fails for left==result))" );
7423 }
7424
7425 /*-----------------------------------------------------------------*/
7426 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7427 /*-----------------------------------------------------------------*/
7428 static void shiftRLeftOrResult (operand *left, int offl,
7429                                                                 operand *result, int offr, int shCount)
7430 {
7431         FENTRY;
7432         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7433         
7434         /* shift right accumulator */
7435         AccRsh(left,offl,shCount);
7436         /* or with result */
7437         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7438         assert ( !"broken (modifies left, fails for left==result))" );
7439 }
7440
7441 /*-----------------------------------------------------------------*/
7442 /* genlshOne - left shift a one byte quantity by known count       */
7443 /*-----------------------------------------------------------------*/
7444 static void genlshOne (operand *result, operand *left, int shCount)
7445 {       
7446         FENTRY;
7447         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7448         shiftL1Left2Result(left, LSB, result, LSB, shCount);
7449 }
7450
7451 /*-----------------------------------------------------------------*/
7452 /* genlshTwo - left shift two bytes by known amount != 0           */
7453 /*-----------------------------------------------------------------*/
7454 static void genlshTwo (operand *result,operand *left, int shCount)
7455 {
7456         int size;
7457         
7458         FENTRY;
7459         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7460         size = pic14_getDataSize(result);
7461         
7462         /* if shCount >= 8 */
7463         if (shCount >= 8) {
7464                 shCount -= 8 ;
7465                 
7466                 if (size > 1){
7467                         if (shCount)
7468                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7469                         else 
7470                                 movLeft2Result(left, LSB, result, MSB16);
7471                 }
7472                 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7473         }
7474         
7475         /*  1 <= shCount <= 7 */
7476         else {  
7477                 if(size == 1)
7478                         shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7479                 else 
7480                         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7481         }
7482 }
7483
7484 /*-----------------------------------------------------------------*/
7485 /* shiftLLong - shift left one long from left to result            */
7486 /* offl = LSB or MSB16                                             */
7487 /*-----------------------------------------------------------------*/
7488 static void shiftLLong (operand *left, operand *result, int offr )
7489 {
7490         char *l;
7491         int size = AOP_SIZE(result);
7492         
7493         FENTRY;
7494         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7495         if(size >= LSB+offr){
7496                 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7497                 MOVA(l);
7498                 pic14_emitcode("add","a,acc");
7499                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7500                         size >= MSB16+offr && offr != LSB )
7501                         pic14_emitcode("xch","a,%s",
7502                         aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7503                 else      
7504                         aopPut(AOP(result),"a",LSB+offr);
7505         }
7506         
7507         if(size >= MSB16+offr){
7508                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7509                         l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7510                         MOVA(l);
7511                 }
7512                 pic14_emitcode("rlc","a");
7513                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7514                         size >= MSB24+offr && offr != LSB)
7515                         pic14_emitcode("xch","a,%s",
7516                         aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7517                 else      
7518                         aopPut(AOP(result),"a",MSB16+offr);
7519         }
7520         
7521         if(size >= MSB24+offr){
7522                 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7523                         l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7524                         MOVA(l);
7525                 }
7526                 pic14_emitcode("rlc","a");
7527                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7528                         size >= MSB32+offr && offr != LSB )
7529                         pic14_emitcode("xch","a,%s",
7530                         aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7531                 else      
7532                         aopPut(AOP(result),"a",MSB24+offr);
7533         }
7534         
7535         if(size > MSB32+offr){
7536                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7537                         l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7538                         MOVA(l);  
7539                 }
7540                 pic14_emitcode("rlc","a");
7541                 aopPut(AOP(result),"a",MSB32+offr);
7542         }
7543         if(offr != LSB)
7544                 aopPut(AOP(result),zero,LSB);       
7545 }
7546
7547 /*-----------------------------------------------------------------*/
7548 /* genlshFour - shift four byte by a known amount != 0             */
7549 /*-----------------------------------------------------------------*/
7550 static void genlshFour (operand *result, operand *left, int shCount)
7551 {
7552         int size;
7553         
7554         FENTRY;
7555         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7556         size = AOP_SIZE(result);
7557         
7558         /* if shifting more that 3 bytes */
7559         if (shCount >= 24 ) {
7560                 shCount -= 24;
7561                 if (shCount)
7562                 /* lowest order of left goes to the highest
7563                 order of the destination */
7564                 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7565                 else
7566                         movLeft2Result(left, LSB, result, MSB32);
7567                 aopPut(AOP(result),zero,LSB);
7568                 aopPut(AOP(result),zero,MSB16);
7569                 aopPut(AOP(result),zero,MSB32);
7570                 return;
7571         }
7572         
7573         /* more than two bytes */
7574         else if ( shCount >= 16 ) {
7575                 /* lower order two bytes goes to higher order two bytes */
7576                 shCount -= 16;
7577                 /* if some more remaining */
7578                 if (shCount)
7579                         shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7580                 else {
7581                         movLeft2Result(left, MSB16, result, MSB32);
7582                         movLeft2Result(left, LSB, result, MSB24);
7583                 }
7584                 aopPut(AOP(result),zero,MSB16);
7585                 aopPut(AOP(result),zero,LSB);
7586                 return;
7587         }    
7588         
7589         /* if more than 1 byte */
7590         else if ( shCount >= 8 ) {
7591                 /* lower order three bytes goes to higher order  three bytes */
7592                 shCount -= 8;
7593                 if(size == 2){
7594                         if(shCount)
7595                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7596                         else
7597                                 movLeft2Result(left, LSB, result, MSB16);
7598                 }
7599                 else{   /* size = 4 */
7600                         if(shCount == 0){
7601                                 movLeft2Result(left, MSB24, result, MSB32);
7602                                 movLeft2Result(left, MSB16, result, MSB24);
7603                                 movLeft2Result(left, LSB, result, MSB16);
7604                                 aopPut(AOP(result),zero,LSB);
7605                         }
7606                         else if(shCount == 1)
7607                                 shiftLLong(left, result, MSB16);
7608                         else{
7609                                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7610                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7611                                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7612                                 aopPut(AOP(result),zero,LSB);
7613                         }
7614                 }
7615         }
7616         
7617         /* 1 <= shCount <= 7 */
7618         else if(shCount <= 2){
7619                 shiftLLong(left, result, LSB);
7620                 if(shCount == 2)
7621                         shiftLLong(result, result, LSB);
7622         }
7623         /* 3 <= shCount <= 7, optimize */
7624         else{
7625                 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7626                 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7627                 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7628         }
7629 }
7630 #endif
7631
7632 #if 0
7633 /*-----------------------------------------------------------------*/
7634 /* genLeftShiftLiteral - left shifting by known count              */
7635 /*-----------------------------------------------------------------*/
7636 static void genLeftShiftLiteral (operand *left,
7637                                                                  operand *right,
7638                                                                  operand *result,
7639                                                                  iCode *ic)
7640 {    
7641         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7642         //int size;
7643         
7644         FENTRY;
7645         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7646         freeAsmop(right,NULL,ic,TRUE);
7647         
7648         aopOp(left,ic,FALSE);
7649         aopOp(result,ic,FALSE);
7650
7651         size = getSize(operandType(result));
7652         
7653 #if VIEW_SIZE
7654         pic14_emitcode("; shift left ","result %d, left %d",size,
7655                 AOP_SIZE(left));
7656 #endif
7657         
7658         /* I suppose that the left size >= result size */
7659         if(shCount == 0){
7660                 while(size--){
7661                         movLeft2Result(left, size, result, size);
7662                 }
7663         }
7664         
7665         else if(shCount >= (size * 8))
7666                 while(size--)
7667                         aopPut(AOP(result),zero,size);
7668                 else{
7669                         switch (size) {
7670                         case 1:
7671                                 genlshOne (result,left,shCount);
7672                                 break;
7673                                 
7674                         case 2:
7675                         case 3:
7676                                 genlshTwo (result,left,shCount);
7677                                 break;
7678                                 
7679                         case 4:
7680                                 genlshFour (result,left,shCount);
7681                                 break;
7682                         }
7683                 }
7684                 freeAsmop(left,NULL,ic,TRUE);
7685                 freeAsmop(result,NULL,ic,TRUE);
7686 }
7687 #endif
7688
7689 /*-----------------------------------------------------------------*
7690 * genMultiAsm - repeat assembly instruction for size of register.
7691 * if endian == 1, then the high byte (i.e base address + size of 
7692 * register) is used first else the low byte is used first;
7693 *-----------------------------------------------------------------*/
7694 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7695 {
7696         
7697         int offset = 0;
7698         
7699         FENTRY;
7700         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7701         
7702         if(!reg)
7703                 return;
7704         
7705         if(!endian) {
7706                 endian = 1;
7707         } else {
7708                 endian = -1;
7709                 offset = size-1;
7710         }
7711         
7712         while(size--) {
7713                 emitpcode(poc,    popGet(AOP(reg),offset));
7714                 offset += endian;
7715         }
7716         
7717 }
7718
7719 #if 0
7720 /*-----------------------------------------------------------------*/
7721 /* genLeftShift - generates code for left shifting                 */
7722 /*-----------------------------------------------------------------*/
7723 static void genLeftShift (iCode *ic)
7724 {
7725         operand *left,*right, *result;
7726         int size, offset;
7727         unsigned long lit = 0L;
7728         char *l;
7729         symbol *tlbl , *tlbl1;
7730         pCodeOp *pctemp;
7731         
7732         FENTRY;
7733         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7734         
7735         right = IC_RIGHT(ic);
7736         left  = IC_LEFT(ic);
7737         result = IC_RESULT(ic);
7738         
7739         aopOp(right,ic,FALSE);
7740         aopOp(left,ic,FALSE);
7741         aopOp(result,ic,FALSE);
7742         
7743         
7744         /* if the shift count is known then do it 
7745         as efficiently as possible */
7746         if (AOP_TYPE(right) == AOP_LIT) {
7747                 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7748                 return ;
7749         }
7750         
7751         /* shift count is unknown then we have to form 
7752         a loop get the loop count in B : Note: we take
7753         only the lower order byte since shifting
7754         more that 32 bits make no sense anyway, ( the
7755         largest size of an object can be only 32 bits ) */  
7756         
7757         /* this code fails for RIGHT == RESULT */
7758         assert (!pic14_sameRegs (AOP(right), AOP(result)));
7759         
7760         /* now move the left to the result if they are not the
7761         same */
7762         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7763                 AOP_SIZE(result) > 1) {
7764                 
7765                 size = AOP_SIZE(result);
7766                 offset=0;
7767                 while (size--) {
7768                         l = aopGet(AOP(left),offset,FALSE,TRUE);
7769                         if (*l == '@' && (IS_AOP_PREG(result))) {
7770                                 
7771                                 pic14_emitcode("mov","a,%s",l);
7772                                 aopPut(AOP(result),"a",offset);
7773                         } else {
7774                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7775                                 emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7776                                 //aopPut(AOP(result),l,offset);
7777                         }
7778                         offset++;
7779                 }
7780         }
7781         
7782         if(AOP_TYPE(left) == AOP_LIT)
7783                 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7784
7785         size = AOP_SIZE(result);
7786         
7787         /* if it is only one byte then */
7788         if (size == 1) {
7789                 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7790                         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7791                         emitpcode(POC_ANDLW,  popGetLit(0xf0));
7792                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7793                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7794                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7795                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7796                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7797                         emitpcode(POC_RLFW,   popGet(AOP(result),0));
7798                         emitpcode(POC_ANDLW,  popGetLit(0xfe));
7799                         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7800                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7801                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7802                 } else {
7803                         
7804                         tlbl = newiTempLabel(NULL);
7805                         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7806                                 mov2w (AOP(left), 0);
7807                                 emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7808                         }
7809                         
7810                         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7811                         emitpcode(POC_RRF,    popGet(AOP(result),0));
7812                         emitpLabel(tlbl->key);
7813                         emitpcode(POC_RLF,    popGet(AOP(result),0));
7814                         emitpcode(POC_ADDLW,  popGetLit(1));
7815                         emitSKPC;
7816                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7817                 }
7818                 goto release ;
7819         }
7820         
7821         if (pic14_sameRegs(AOP(left),AOP(result))) {
7822                 
7823                 tlbl = newiTempLabel(NULL);
7824                 emitpcode(POC_COMFW,  popGet(AOP(right),0));
7825                 genMultiAsm(POC_RRF, result, size,1);
7826                 emitpLabel(tlbl->key);
7827                 genMultiAsm(POC_RLF, result, size,0);
7828                 emitpcode(POC_ADDLW,  popGetLit(1));
7829                 emitSKPC;
7830                 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7831                 goto release;
7832         }
7833         
7834         //tlbl = newiTempLabel(NULL);
7835         //offset = 0 ;   
7836         //tlbl1 = newiTempLabel(NULL);
7837         
7838         //reAdjustPreg(AOP(result));    
7839         
7840         //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7841         //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7842         //l = aopGet(AOP(result),offset,FALSE,FALSE);
7843         //MOVA(l);
7844         //pic14_emitcode("add","a,acc");         
7845         //aopPut(AOP(result),"a",offset++);
7846         //while (--size) {
7847         //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7848         //  MOVA(l);
7849         //  pic14_emitcode("rlc","a");         
7850         //  aopPut(AOP(result),"a",offset++);
7851         //}
7852         //reAdjustPreg(AOP(result));
7853         
7854         //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7855         //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7856         
7857         
7858         tlbl = newiTempLabel(NULL);
7859         tlbl1= newiTempLabel(NULL);
7860         
7861         size = AOP_SIZE(result);
7862         offset = 1;
7863         
7864         pctemp = popGetTempReg();  /* grab a temporary working register. */
7865         
7866         emitpcode(POC_MOVFW, popGet(AOP(right),0));
7867         
7868         /* offset should be 0, 1 or 3 */
7869         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7870         emitSKPNZ;
7871         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7872         
7873         emitpcode(POC_MOVWF, pctemp);
7874         
7875         
7876         emitpLabel(tlbl->key);
7877         
7878         emitCLRC;
7879         emitpcode(POC_RLF,  popGet(AOP(result),0));
7880         while(--size)
7881                 emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7882         
7883         emitpcode(POC_DECFSZ,  pctemp);
7884         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7885         emitpLabel(tlbl1->key);
7886         
7887         popReleaseTempReg(pctemp);
7888         
7889         
7890 release:
7891         freeAsmop (right,NULL,ic,TRUE);
7892         freeAsmop(left,NULL,ic,TRUE);
7893         freeAsmop(result,NULL,ic,TRUE);
7894 }
7895 #endif
7896
7897 #if 0
7898 /*-----------------------------------------------------------------*/
7899 /* genrshOne - right shift a one byte quantity by known count      */
7900 /*-----------------------------------------------------------------*/
7901 static void genrshOne (operand *result, operand *left,
7902                                            int shCount, int sign)
7903 {
7904         FENTRY;
7905         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7906         shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7907 }
7908
7909 /*-----------------------------------------------------------------*/
7910 /* genrshTwo - right shift two bytes by known amount != 0          */
7911 /*-----------------------------------------------------------------*/
7912 static void genrshTwo (operand *result,operand *left,
7913                                            int shCount, int sign)
7914 {
7915         FENTRY;
7916         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7917         /* if shCount >= 8 */
7918         if (shCount >= 8) {
7919                 shCount -= 8 ;
7920                 if (shCount)
7921                         shiftR1Left2Result(left, MSB16, result, LSB,
7922                         shCount, sign);
7923                 else
7924                         movLeft2Result(left, MSB16, result, LSB);
7925                 
7926                 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7927                 
7928                 if(sign) {
7929                         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7930                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7931                 }
7932         }
7933         
7934         /*  1 <= shCount <= 7 */
7935         else
7936                 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7937 }
7938
7939 /*-----------------------------------------------------------------*/
7940 /* shiftRLong - shift right one long from left to result           */
7941 /* offl = LSB or MSB16                                             */
7942 /*-----------------------------------------------------------------*/
7943 static void shiftRLong (operand *left, int offl,
7944                                                 operand *result, int sign)
7945 {
7946         int size, same;
7947         
7948         FENTRY;
7949         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7950         
7951         size = AOP_SIZE(left);
7952         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7953         
7954         if (sign)
7955                 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7956         else
7957                 emitCLRC;
7958
7959         assert (offl >= 0 && offl < size);
7960
7961         same = pic14_sameRegs (AOP(left), AOP(result));
7962
7963         /* perform the shift */
7964         while (size--)
7965         {
7966                 if (same && !offl) {
7967                         emitpcode (POC_RRF, popGet (AOP(result), size));
7968                 } else {
7969                         emitpcode (POC_RRFW, popGet (AOP(left), size));
7970                         emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7971                 }
7972         } // while
7973
7974         addSign (result, AOP_SIZE(left) - offl, sign);
7975 }
7976
7977 /*-----------------------------------------------------------------*/
7978 /* genrshFour - shift four byte by a known amount != 0             */
7979 /*-----------------------------------------------------------------*/
7980 static void genrshFour (operand *result, operand *left,
7981                                                 int shCount, int sign)
7982 {
7983         FENTRY;
7984         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7985         /* if shifting more that 3 bytes */
7986         if(shCount >= 24 ) {
7987                 shCount -= 24;
7988                 if(shCount)
7989                         shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7990                 else
7991                         movLeft2Result(left, MSB32, result, LSB);
7992                 
7993                 addSign(result, MSB16, sign);
7994         }
7995         else if(shCount >= 16){
7996                 shCount -= 16;
7997                 if(shCount)
7998                         shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7999                 else{
8000                         movLeft2Result(left, MSB24, result, LSB);
8001                         movLeft2Result(left, MSB32, result, MSB16);
8002                 }
8003                 addSign(result, MSB24, sign);
8004         }
8005         else if(shCount >= 8){
8006                 shCount -= 8;
8007                 if(shCount == 1)
8008                         shiftRLong(left, MSB16, result, sign);
8009                 else if(shCount == 0){
8010                         movLeft2Result(left, MSB16, result, LSB);
8011                         movLeft2Result(left, MSB24, result, MSB16);
8012                         movLeft2Result(left, MSB32, result, MSB24);
8013                         addSign(result, MSB32, sign);
8014                 }
8015                 else{
8016                         shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8017                         shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8018                         /* the last shift is signed */
8019                         shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8020                         addSign(result, MSB32, sign);
8021                 }
8022         }
8023         else{   /* 1 <= shCount <= 7 */
8024                 if(shCount <= 2){
8025                         shiftRLong(left, LSB, result, sign);
8026                         if(shCount == 2)
8027                                 shiftRLong(result, LSB, result, sign);
8028                 }
8029                 else{
8030                         shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8031                         shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8032                         shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8033                 }
8034         }
8035 }
8036
8037 /*-----------------------------------------------------------------*/
8038 /* genRightShiftLiteral - right shifting by known count            */
8039 /*-----------------------------------------------------------------*/
8040 static void genRightShiftLiteral (operand *left,
8041                                                                   operand *right,
8042                                                                   operand *result,
8043                                                                   iCode *ic,
8044                                                                   int sign)
8045 {    
8046         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8047         int lsize,res_size;
8048         
8049         FENTRY;
8050         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8051         freeAsmop(right,NULL,ic,TRUE);
8052         
8053         aopOp(left,ic,FALSE);
8054         aopOp(result,ic,FALSE);
8055         
8056 #if VIEW_SIZE
8057         pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8058                 AOP_SIZE(left));
8059 #endif
8060         
8061         lsize = pic14_getDataSize(left);
8062         res_size = pic14_getDataSize(result);
8063         /* test the LEFT size !!! */
8064         
8065         /* I suppose that the left size >= result size */
8066         if(shCount == 0){
8067                 while(res_size--)
8068                         movLeft2Result(left, res_size, result, res_size);
8069         }
8070         
8071         else if(shCount >= (lsize * 8)){
8072                 
8073                 if(res_size == 1) {
8074                         emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8075                         if(sign) {
8076                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8077                                 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8078                         }
8079                 } else {
8080                         
8081                         if(sign) {
8082                                 emitpcode(POC_MOVLW, popGetLit(0));
8083                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8084                                 emitpcode(POC_MOVLW, popGetLit(0xff));
8085                                 while(res_size--)
8086                                         emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8087                                 
8088                         } else {
8089                                 
8090                                 while(res_size--)
8091                                         emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8092                         }
8093                 }
8094         } else {
8095                 
8096                 switch (res_size) {
8097                 case 1:
8098                         genrshOne (result,left,shCount,sign);
8099                         break;
8100                         
8101                 case 2:
8102                         genrshTwo (result,left,shCount,sign);
8103                         break;
8104                         
8105                 case 4:
8106                         genrshFour (result,left,shCount,sign);
8107                         break;
8108                 default :
8109                         break;
8110                 }
8111                 
8112         }
8113
8114         freeAsmop(left,NULL,ic,TRUE);
8115         freeAsmop(result,NULL,ic,TRUE);
8116 }
8117 #endif
8118
8119 #if 0
8120 /*-----------------------------------------------------------------*/
8121 /* genSignedRightShift - right shift of signed number              */
8122 /*-----------------------------------------------------------------*/
8123 static void genSignedRightShift (iCode *ic)
8124 {
8125         operand *right, *left, *result;
8126         int size, offset;
8127         //  char *l;
8128         symbol *tlbl, *tlbl1 ;
8129         pCodeOp *pctemp;
8130         
8131         //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8132         
8133         /* we do it the hard way put the shift count in b
8134         and loop thru preserving the sign */
8135         FENTRY;
8136         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8137         
8138         right = IC_RIGHT(ic);
8139         left  = IC_LEFT(ic);
8140         result = IC_RESULT(ic);
8141         
8142         aopOp(right,ic,FALSE);  
8143         aopOp(left,ic,FALSE);
8144         aopOp(result,ic,FALSE);
8145         
8146         
8147         if ( AOP_TYPE(right) == AOP_LIT) {
8148                 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8149                 //genRightShiftLiteral (left,right,result,ic,1);
8150                 return ;
8151         }
8152         /* shift count is unknown then we have to form 
8153         a loop get the loop count in B : Note: we take
8154         only the lower order byte since shifting
8155         more that 32 bits make no sense anyway, ( the
8156         largest size of an object can be only 32 bits ) */  
8157         
8158         //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8159         //pic14_emitcode("inc","b");
8160         //freeAsmop (right,NULL,ic,TRUE);
8161         //aopOp(left,ic,FALSE);
8162         //aopOp(result,ic,FALSE);
8163         
8164         /* now move the left to the result if they are not the
8165         same */
8166         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
8167                 AOP_SIZE(result) > 1) {
8168                 
8169                 size = AOP_SIZE(result);
8170                 offset=0;
8171                 while (size--) { 
8172                         /*
8173                         l = aopGet(AOP(left),offset,FALSE,TRUE);
8174                         if (*l == '@' && IS_AOP_PREG(result)) {
8175                                 pic14_emitcode("mov","a,%s",l);
8176                                 aopPut(AOP(result),"a",offset);
8177                         } else
8178                         aopPut(AOP(result),l,offset);
8179                         */
8180                         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
8181                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
8182                         
8183                         offset++;
8184                 }
8185         }
8186         
8187         /* mov the highest order bit to OVR */    
8188         tlbl = newiTempLabel(NULL);
8189         tlbl1= newiTempLabel(NULL);
8190         
8191         size = AOP_SIZE(result);
8192         offset = size - 1;
8193         
8194         pctemp = popGetTempReg();  /* grab a temporary working register. */
8195         
8196         emitpcode(POC_MOVFW, popGet(AOP(right),0));
8197         
8198         /* offset should be 0, 1 or 3 */
8199         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8200         emitSKPNZ;
8201         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
8202         
8203         emitpcode(POC_MOVWF, pctemp);
8204         
8205         
8206         emitpLabel(tlbl->key);
8207         
8208         emitpcode(POC_RLFW,  popGet(AOP(result),offset));
8209         emitpcode(POC_RRF,   popGet(AOP(result),offset));
8210         
8211         while(--size) {
8212                 emitpcode(POC_RRF,   popGet(AOP(result),--offset));
8213         }
8214         
8215         emitpcode(POC_DECFSZ,  pctemp);
8216         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8217         emitpLabel(tlbl1->key);
8218         
8219         popReleaseTempReg(pctemp);
8220 #if 0
8221         size = AOP_SIZE(result);
8222         offset = size - 1;
8223         pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8224         pic14_emitcode("rlc","a");
8225         pic14_emitcode("mov","ov,c");
8226         /* if it is only one byte then */
8227         if (size == 1) {
8228                 l = aopGet(AOP(left),0,FALSE,FALSE);
8229                 MOVA(l);
8230                 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8231                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8232                 pic14_emitcode("mov","c,ov");
8233                 pic14_emitcode("rrc","a");
8234                 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8235                 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8236                 aopPut(AOP(result),"a",0);
8237                 goto release ;
8238         }
8239         
8240         reAdjustPreg(AOP(result));
8241         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8242         pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
8243         pic14_emitcode("mov","c,ov");
8244         while (size--) {
8245                 l = aopGet(AOP(result),offset,FALSE,FALSE);
8246                 MOVA(l);
8247                 pic14_emitcode("rrc","a");         
8248                 aopPut(AOP(result),"a",offset--);
8249         }
8250         reAdjustPreg(AOP(result));
8251         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8252         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8253         
8254 release:
8255 #endif
8256         
8257         freeAsmop(left,NULL,ic,TRUE);
8258         freeAsmop(result,NULL,ic,TRUE);
8259         freeAsmop(right,NULL,ic,TRUE);
8260 }
8261 #endif
8262
8263 /*-----------------------------------------------------------------*/
8264 /* loadSignToC - load the operand's sign bit into CARRY            */
8265 /*-----------------------------------------------------------------*/
8266
8267 static void loadSignToC (operand *op)
8268 {
8269         FENTRY;
8270         assert (op && AOP(op) && AOP_SIZE(op));
8271
8272         emitCLRC;
8273         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8274         emitSETC;
8275 }
8276
8277 /*-----------------------------------------------------------------*/
8278 /* genRightShift - generate code for right shifting                */
8279 /*-----------------------------------------------------------------*/
8280 static void genGenericShift (iCode *ic, int shiftRight)
8281 {
8282         operand *right, *left, *result;
8283         sym_link *retype ;
8284         int size;
8285         symbol *tlbl, *tlbl1, *inverselbl;
8286         
8287         FENTRY;
8288         /* if signed then we do it the hard way preserve the
8289         sign bit moving it inwards */
8290         retype = getSpec(operandType(IC_RESULT(ic)));
8291         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8292         
8293         /* signed & unsigned types are treated the same : i.e. the
8294         signed is NOT propagated inwards : quoting from the
8295         ANSI - standard : "for E1 >> E2, is equivalent to division
8296         by 2**E2 if unsigned or if it has a non-negative value,
8297         otherwise the result is implementation defined ", MY definition
8298         is that the sign does not get propagated */
8299         
8300         right = IC_RIGHT(ic);
8301         left  = IC_LEFT(ic);
8302         result = IC_RESULT(ic);
8303         
8304         aopOp(right,ic,FALSE);
8305         aopOp(left,ic,FALSE);
8306         aopOp(result,ic,FALSE);
8307         
8308         /* if the shift count is known then do it 
8309         as efficiently as possible */
8310         if (AOP_TYPE(right) == AOP_LIT) {
8311                 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8312                 if (lit < 0)
8313                 {
8314                         lit = -lit;
8315                         shiftRight = !shiftRight;
8316                 }
8317                 
8318                 if (shiftRight)
8319                         shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8320                 else
8321                         shiftLeft_Left2ResultLit (left, result, lit);
8322                 //genRightShiftLiteral (left,right,result,ic, 0);
8323                 return ;
8324         }
8325         
8326         /* shift count is unknown then we have to form 
8327         a loop get the loop count in B : Note: we take
8328         only the lower order byte since shifting
8329         more that 32 bits make no sense anyway, ( the
8330         largest size of an object can be only 32 bits ) */  
8331
8332         /* we must not overwrite the shift counter */
8333         assert (!pic14_sameRegs(AOP(right),AOP(result)));
8334         
8335         /* now move the left to the result if they are not the
8336         same */
8337         if (!pic14_sameRegs(AOP(left),AOP(result)))
8338         {
8339                 size = min(AOP_SIZE(result), AOP_SIZE(left));
8340                 while (size--) {
8341                         mov2w(AOP(left), size);
8342                         movwf(AOP(result), size);
8343                 }
8344                 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8345         }
8346         
8347         tlbl = newiTempLabel(NULL);
8348         tlbl1= newiTempLabel(NULL);
8349         inverselbl = NULL;
8350         size = AOP_SIZE(result);
8351
8352         mov2w(AOP(right),0);
8353         if (!SPEC_USIGN(operandType(right)))
8354         {
8355                 inverselbl = newiTempLabel(NULL);
8356                 /* signed shift count -- invert shift direction for c<0 */
8357                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8358                 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8359         } // if
8360         emitpcode(POC_SUBLW, popGetLit(0));     /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8361         /* check for `a = b >> c' with `-c == 0' */
8362         emitSKPNZ;
8363         emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8364         emitpLabel(tlbl->key);
8365         /* propagate the sign bit inwards for SIGNED result */
8366         if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8367         genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8368         emitpcode(POC_ADDLW,  popGetLit(1));    /* clears CARRY (unless W==0 afterwards) */
8369         emitSKPC;
8370         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8371
8372         if (!SPEC_USIGN(operandType(right)))
8373         {
8374                 symbol *inv_loop = newiTempLabel(NULL);
8375
8376                 shiftRight = !shiftRight;       /* invert shift direction */
8377                 
8378                 /* we came here from the code above -- we are done */
8379                 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8380                 
8381                 /* emit code for shifting N<0 steps, count is already in W */
8382                 emitpLabel(inverselbl->key);
8383                 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8384                 emitpLabel(inv_loop->key);
8385                 /* propagate the sign bit inwards for SIGNED result */
8386                 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8387                 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8388                 emitpcode(POC_ADDLW, popGetLit(1));
8389                 emitSKPC;
8390                 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8391         } // if
8392         
8393         emitpLabel(tlbl1->key);
8394         
8395         freeAsmop(left,NULL,ic,TRUE);
8396         freeAsmop (right,NULL,ic,TRUE);
8397         freeAsmop(result,NULL,ic,TRUE);
8398 }
8399
8400 static void genRightShift (iCode *ic)
8401 {
8402         genGenericShift(ic, 1);
8403 }
8404
8405 static void genLeftShift (iCode *ic)
8406 {
8407         genGenericShift(ic, 0);
8408 }
8409
8410 /*-----------------------------------------------------------------*/
8411 /* SetIrp - Set IRP bit                                            */
8412 /*-----------------------------------------------------------------*/
8413 void SetIrp(operand *result) {
8414         FENTRY;
8415         if (AOP_TYPE(result) == AOP_LIT) {
8416                 unsigned lit = (unsigned)operandLitValue(result);
8417                 if (lit&0x100)
8418                         emitSETIRP;
8419                 else
8420                         emitCLRIRP;
8421         } else {
8422                 if (PCOP(AOP(result))->type == PO_LITERAL) {
8423                         int addrs = PCOL(AOP(result))->lit;
8424                         if (addrs & 0x100)
8425                                 emitSETIRP;
8426                         else
8427                                 emitCLRIRP;
8428                 } else {
8429                         emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8430                         if(AOP_SIZE(result) > 1) {
8431                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8432                                 emitSETIRP;
8433                         }
8434                 }
8435         }
8436 }
8437
8438 static void
8439 setup_fsr (operand *ptr)
8440 {
8441   mov2w_op(ptr, 0);
8442   emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8443
8444   /* also setup-up IRP */
8445   SetIrp (ptr);
8446 }
8447
8448 /*-----------------------------------------------------------------*/
8449 /* emitPtrByteGet - emits code to get a byte into WREG from an     */
8450 /*                  arbitrary pointer (__code, __data, generic)    */
8451 /*-----------------------------------------------------------------*/
8452 static void
8453 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8454 {
8455     FENTRY;
8456     switch (p_type)
8457     {
8458     case POINTER:
8459     case FPOINTER:
8460       if (!alreadyAddressed) setup_fsr (src);
8461       emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8462       break;
8463     
8464     case CPOINTER:
8465       assert( AOP_SIZE(src) == 2 );
8466       mov2w_op(src, 0);
8467       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8468       mov2w_op(src, 1);
8469       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8470       emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE));   /* GPOINTER tag for __code space */
8471       call_libraryfunc ("__gptrget1");
8472       break;
8473     
8474     case GPOINTER:
8475       assert( AOP_SIZE(src) == 3 );
8476       mov2w_op(src, 0);
8477       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8478       mov2w_op(src, 1);
8479       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8480       mov2w_op(src, 2);
8481       call_libraryfunc ("__gptrget1");
8482       break;
8483     
8484     default:
8485       assert( !"unhandled pointer type" );
8486       break;
8487     }
8488 }
8489
8490 /*-----------------------------------------------------------------*/
8491 /* emitPtrByteSet - emits code to set a byte from src through a    */
8492 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR).       */
8493 /*-----------------------------------------------------------------*/
8494 static void
8495 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8496 {
8497     FENTRY;
8498     switch (p_type)
8499     {
8500     case POINTER:
8501     case FPOINTER:
8502       if (!alreadyAddressed) setup_fsr (dst);
8503       emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8504       break;
8505     
8506     case CPOINTER:
8507       assert( !"trying to assign to __code pointer" );
8508       break;
8509     
8510     case GPOINTER:
8511       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8512       mov2w_op(dst, 0);
8513       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8514       mov2w_op(dst, 1);
8515       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8516       mov2w_op(dst, 2);
8517       call_libraryfunc ("__gptrput1");
8518       break;
8519
8520     default:
8521       assert( !"unhandled pointer type" );
8522       break;
8523     }
8524 }
8525
8526 /*-----------------------------------------------------------------*/
8527 /* genUnpackBits - generates code for unpacking bits               */
8528 /*-----------------------------------------------------------------*/
8529 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8530 {    
8531   int rsize;            /* result size */
8532   sym_link *etype;      /* bitfield type information */
8533   int blen;             /* bitfield length */
8534   int bstr;             /* bitfield starting bit within byte */
8535
8536   FENTRY;
8537   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8538   etype = getSpec(operandType(result));
8539   rsize = getSize (operandType (result));
8540   blen = SPEC_BLEN (etype);
8541   bstr = SPEC_BSTR (etype);
8542
8543   /* single bit field case */
8544   if (blen == 1) {
8545     if (ifx) { /* that is for an if statement */
8546       pCodeOp *pcop;
8547       resolvedIfx rIfx;
8548       resolveIfx(&rIfx,ifx);
8549       if (ptype == -1) /* direct */
8550         pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8551       else
8552         pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8553       emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8554       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8555       ifx->generated=1;
8556     } else {
8557       int i;
8558       assert (!pic14_sameRegs (AOP(result), AOP(left)));
8559       for (i=0; i < AOP_SIZE(result); i++)
8560         emitpcode (POC_CLRF, popGet (AOP(result), i));
8561
8562       switch (ptype)
8563       {
8564       case -1:
8565         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8566         /* adjust result below */
8567         break;
8568         
8569       case POINTER:
8570       case FPOINTER:
8571       case GPOINTER:
8572       case CPOINTER:
8573         emitPtrByteGet (left, ptype, FALSE);
8574         emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8575         emitSKPZ;
8576         /* adjust result below */
8577         break;
8578         
8579       default:
8580         assert( !"unhandled pointer type" );
8581       } // switch
8582
8583       /* move sign-/zero extended bit to result */
8584       if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8585         emitpcode (POC_INCF, popGet (AOP(result), 0));
8586       } else {
8587         emitpcode (POC_DECF, popGet (AOP(result), 0));
8588       }
8589       addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8590     }
8591     return;
8592   }
8593   else if (blen <= 8 && ((blen + bstr) <= 8))
8594   {
8595     /* blen > 1 */
8596     int i;
8597
8598     for (i=0; i < AOP_SIZE(result); i++)
8599       emitpcode (POC_CLRF, popGet (AOP(result), i));
8600
8601     switch (ptype)
8602     {
8603     case -1:
8604       mov2w(AOP(left), 0);
8605       break;
8606       
8607     case POINTER:
8608     case FPOINTER:
8609     case GPOINTER:
8610     case CPOINTER:
8611       emitPtrByteGet (left, ptype, FALSE);
8612       break;
8613       
8614     default:
8615       assert( !"unhandled pointer type" );
8616     } // switch
8617
8618     if (blen < 8)
8619       emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8620     movwf(AOP(result), 0);
8621     AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8622
8623     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8624     {
8625       /* signed bitfield */
8626       assert (bstr + blen > 0);
8627       emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8628       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8629       emitpcode(POC_IORWF, popGet(AOP(result),0));
8630     }
8631     addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8632     return;
8633   }
8634
8635   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8636 }
8637
8638 #if 1
8639 /*-----------------------------------------------------------------*/
8640 /* genDataPointerGet - generates code when ptr offset is known     */
8641 /*-----------------------------------------------------------------*/
8642 static void genDataPointerGet (operand *left, 
8643         operand *result, 
8644         iCode *ic)
8645 {
8646         int size , offset = 0;
8647                 
8648         FENTRY;
8649         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8650         
8651         
8652         /* optimization - most of the time, left and result are the same
8653         * address, but different types. for the pic code, we could omit
8654         * the following
8655         */
8656         aopOp(result,ic,TRUE);
8657         
8658         if (pic14_sameRegs (AOP(left), AOP(result)))
8659                 return;
8660         
8661         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8662         
8663         //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8664         
8665         size = AOP_SIZE(result);
8666         if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8667         
8668         offset = 0;
8669         while (size--) {
8670                 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8671                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8672                 offset++;
8673         }
8674         
8675         freeAsmop(left,NULL,ic,TRUE);
8676         freeAsmop(result,NULL,ic,TRUE);
8677 }
8678 #endif
8679
8680 /*-----------------------------------------------------------------*/
8681 /* genNearPointerGet - pic14_emitcode for near pointer fetch       */
8682 /*-----------------------------------------------------------------*/
8683 static void genNearPointerGet (operand *left, 
8684                                                            operand *result, 
8685                                                            iCode *ic)
8686 {
8687         asmop *aop = NULL;
8688         sym_link *ltype = operandType(left);
8689         sym_link *rtype = operandType(result);
8690         sym_link *retype= getSpec(rtype);      /* bitfield type information */
8691         int direct = 0;
8692
8693         FENTRY;
8694         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8695         
8696         
8697         aopOp(left,ic,FALSE);
8698         
8699         /* if left is rematerialisable and
8700         result is not bit variable type and
8701         the left is pointer to data space i.e
8702         lower 128 bytes of space */
8703         if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8704                 !IS_BITVAR(retype)         &&
8705                 PIC_IS_DATA_PTR(ltype)) {
8706                 genDataPointerGet (left,result,ic);
8707                 return ;
8708         }
8709         
8710         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8711         aopOp (result,ic,FALSE);
8712         
8713         /* Check if can access directly instead of via a pointer */
8714         if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8715                 && AOP_SIZE(result) == 1)
8716         {
8717                 direct = 1;
8718         }
8719
8720         if (IS_BITFIELD(getSpec(operandType(result)))) 
8721         {
8722                 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8723                 goto release;
8724         }
8725         
8726         /* If the pointer value is not in a the FSR then need to put it in */
8727         /* Must set/reset IRP bit for use with FSR. */
8728         if (!direct)
8729           setup_fsr (left);
8730         
8731 //      sym_link *etype;
8732         /* if bitfield then unpack the bits */
8733         {
8734                 /* we have can just get the values */
8735                 int size = AOP_SIZE(result);
8736                 int offset = 0 ;  
8737                 
8738                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8739                 
8740                 while(size--) {
8741                         if (direct)
8742                                 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8743                         else
8744                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8745                         if (AOP_TYPE(result) == AOP_LIT) {
8746                                 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8747                         } else {
8748                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8749                         }
8750                         if (size && !direct)
8751                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8752                         offset++;
8753                 }
8754         }
8755         
8756         /* now some housekeeping stuff */
8757         if (aop) {
8758                 /* we had to allocate for this iCode */
8759                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8760                 freeAsmop(NULL,aop,ic,TRUE);
8761         } else { 
8762                 /* we did not allocate which means left
8763                 already in a pointer register, then
8764                 if size > 0 && this could be used again
8765                 we have to point it back to where it 
8766                 belongs */
8767                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8768                 if (AOP_SIZE(result) > 1 &&
8769                         !OP_SYMBOL(left)->remat &&
8770                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8771                         ic->depth )) {
8772                         int size = AOP_SIZE(result) - 1;
8773                         while (size--)
8774                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8775                 }
8776         }
8777         
8778 release:
8779         /* done */
8780         freeAsmop(left,NULL,ic,TRUE);
8781         freeAsmop(result,NULL,ic,TRUE);
8782
8783 }
8784
8785 #if 0
8786 /*-----------------------------------------------------------------*/
8787 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8788 /*-----------------------------------------------------------------*/
8789 static void genPagedPointerGet (operand *left, 
8790                                                                 operand *result, 
8791                                                                 iCode *ic)
8792 {
8793         asmop *aop = NULL;
8794         regs *preg = NULL ;
8795         char *rname ;
8796         sym_link *rtype, *retype;    
8797         
8798         FENTRY;
8799         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8800         
8801         rtype = operandType(result);
8802         retype= getSpec(rtype);
8803         
8804         aopOp(left,ic,FALSE);
8805         
8806         /* if the value is already in a pointer register
8807         then don't need anything more */
8808         if (!AOP_INPREG(AOP(left))) {
8809                 /* otherwise get a free pointer register */
8810                 aop = newAsmop(0);
8811                 preg = getFreePtr(ic,&aop,FALSE);
8812                 pic14_emitcode("mov","%s,%s",
8813                         preg->name,
8814                         aopGet(AOP(left),0,FALSE,TRUE));
8815                 rname = preg->name ;
8816         } else
8817                 rname = aopGet(AOP(left),0,FALSE,FALSE);
8818         
8819         freeAsmop(left,NULL,ic,TRUE);
8820         aopOp (result,ic,FALSE);
8821         
8822         /* if bitfield then unpack the bits */
8823         if (IS_BITFIELD(retype)) 
8824                 genUnpackBits (result,left,rname,PPOINTER,0);
8825         else {
8826                 /* we have can just get the values */
8827                 int size = AOP_SIZE(result);
8828                 int offset = 0 ;  
8829                 
8830                 while (size--) {
8831                         
8832                         pic14_emitcode("movx","a,@%s",rname);
8833                         aopPut(AOP(result),"a",offset);
8834                         
8835                         offset++ ;
8836                         
8837                         if (size)
8838                                 pic14_emitcode("inc","%s",rname);
8839                 }
8840         }
8841         
8842         /* now some housekeeping stuff */
8843         if (aop) {
8844                 /* we had to allocate for this iCode */
8845                 freeAsmop(NULL,aop,ic,TRUE);
8846         } else { 
8847         /* we did not allocate which means left
8848         already in a pointer register, then
8849         if size > 0 && this could be used again
8850         we have to point it back to where it 
8851                 belongs */
8852                 if (AOP_SIZE(result) > 1 &&
8853                         !OP_SYMBOL(left)->remat &&
8854                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8855                         ic->depth )) {
8856                         int size = AOP_SIZE(result) - 1;
8857                         while (size--)
8858                                 pic14_emitcode("dec","%s",rname);
8859                 }
8860         }
8861         
8862         /* done */
8863         freeAsmop(result,NULL,ic,TRUE);
8864         
8865         
8866 }
8867
8868 /*-----------------------------------------------------------------*/
8869 /* genFarPointerGet - gget value from far space                    */
8870 /*-----------------------------------------------------------------*/
8871 static void genFarPointerGet (operand *left,
8872                                                           operand *result, iCode *ic)
8873 {
8874         int size, offset ;
8875         sym_link *retype = getSpec(operandType(result));
8876         
8877         FENTRY;
8878         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8879         
8880         aopOp(left,ic,FALSE);
8881         
8882         /* if the operand is already in dptr 
8883         then we do nothing else we move the value to dptr */
8884         if (AOP_TYPE(left) != AOP_STR) {
8885                 /* if this is remateriazable */
8886                 if (AOP_TYPE(left) == AOP_IMMD)
8887                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8888                 else { /* we need to get it byte by byte */
8889                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8890                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8891                         if (options.model == MODEL_FLAT24)
8892                         {
8893                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8894                         }
8895                 }
8896         }
8897         /* so dptr know contains the address */
8898         freeAsmop(left,NULL,ic,TRUE);
8899         aopOp(result,ic,FALSE);
8900         
8901         /* if bit then unpack */
8902         if (IS_BITFIELD(retype)) 
8903                 genUnpackBits(result,left,"dptr",FPOINTER,0);
8904         else {
8905                 size = AOP_SIZE(result);
8906                 offset = 0 ;
8907                 
8908                 while (size--) {
8909                         pic14_emitcode("movx","a,@dptr");
8910                         aopPut(AOP(result),"a",offset++);
8911                         if (size)
8912                                 pic14_emitcode("inc","dptr");
8913                 }
8914         }
8915         
8916         freeAsmop(result,NULL,ic,TRUE);
8917 }
8918 #endif
8919
8920 #if 0
8921 /*-----------------------------------------------------------------*/
8922 /* genCodePointerGet - get value from code space                  */
8923 /*-----------------------------------------------------------------*/
8924 static void genCodePointerGet (operand *left,
8925                                                            operand *result, iCode *ic)
8926 {
8927         int size, offset ;
8928         sym_link *retype = getSpec(operandType(result));
8929         
8930         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8931         
8932         aopOp(left,ic,FALSE);
8933         
8934         /* if the operand is already in dptr 
8935         then we do nothing else we move the value to dptr */
8936         if (AOP_TYPE(left) != AOP_STR) {
8937                 /* if this is remateriazable */
8938                 if (AOP_TYPE(left) == AOP_IMMD)
8939                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8940                 else { /* we need to get it byte by byte */
8941                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8942                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8943                         if (options.model == MODEL_FLAT24)
8944                         {
8945                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8946                         }
8947                 }
8948         }
8949         /* so dptr know contains the address */
8950         freeAsmop(left,NULL,ic,TRUE);
8951         aopOp(result,ic,FALSE);
8952         
8953         /* if bit then unpack */
8954         if (IS_BITFIELD(retype)) 
8955                 genUnpackBits(result,left,"dptr",CPOINTER,0);
8956         else {
8957                 size = AOP_SIZE(result);
8958                 offset = 0 ;
8959                 
8960                 while (size--) {
8961                         pic14_emitcode("clr","a");
8962                         pic14_emitcode("movc","a,@a+dptr");
8963                         aopPut(AOP(result),"a",offset++);
8964                         if (size)
8965                                 pic14_emitcode("inc","dptr");
8966                 }
8967         }
8968         
8969         freeAsmop(result,NULL,ic,TRUE);
8970 }
8971 #endif
8972 /*-----------------------------------------------------------------*/
8973 /* genGenPointerGet - gget value from generic pointer space        */
8974 /*-----------------------------------------------------------------*/
8975 static void genGenPointerGet (operand *left,
8976                                                           operand *result, iCode *ic)
8977 {
8978         FENTRY;
8979         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8980         aopOp(left,ic,FALSE);
8981         aopOp(result,ic,FALSE);
8982         
8983         
8984         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8985
8986         if (IS_BITFIELD(getSpec(operandType(result))))
8987         {
8988           genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
8989           return;
8990         }
8991
8992         {
8993           /* emit call to __gptrget */
8994           char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
8995           int size = AOP_SIZE(result);
8996           int idx = 0;
8997
8998           assert (size > 0 && size <= 4);
8999
9000           /* pass arguments */
9001           assert (AOP_SIZE(left) == 3);
9002           mov2w(AOP(left), 0);
9003           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9004           mov2w(AOP(left), 1);
9005           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9006           mov2w(AOP(left), 2);
9007           call_libraryfunc (func[size]);
9008           
9009           /* save result */
9010           movwf (AOP(result), --size);
9011           while (size--) {
9012             emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
9013             movwf (AOP(result), size);
9014           } // while
9015         }
9016         
9017         freeAsmop(left,NULL,ic,TRUE);
9018         freeAsmop(result,NULL,ic,TRUE);
9019         
9020 }
9021
9022 /*-----------------------------------------------------------------*/
9023 /* genConstPointerGet - get value from const generic pointer space */
9024 /*-----------------------------------------------------------------*/
9025 static void genConstPointerGet (operand *left,
9026                                                                 operand *result, iCode *ic)
9027 {
9028         //sym_link *retype = getSpec(operandType(result));
9029         #if 0
9030         symbol *albl, *blbl;//, *clbl;
9031         pCodeOp *pcop;
9032         #endif
9033         PIC_OPCODE poc;
9034         int i, size, lit;
9035         
9036         FENTRY;
9037         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9038         aopOp(left,ic,FALSE);
9039         aopOp(result,ic,FALSE);
9040         
9041         size = AOP_SIZE(result);
9042         
9043         DEBUGpic14_AopType(__LINE__,left,NULL,result);
9044         
9045         DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9046
9047         lit = op_isLitLike (left);
9048         poc = lit ? POC_MOVLW : POC_MOVFW;
9049
9050         if (IS_BITFIELD(getSpec(operandType(result))))
9051         {
9052                 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9053                 goto release;
9054         }
9055
9056         {
9057                 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9058                 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9059                 assert (size > 0 && size <= 4);
9060                 
9061                 mov2w_op(left, 0);
9062                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9063                 mov2w_op(left, 1);
9064                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9065                 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9066                 call_libraryfunc (func[size]);
9067
9068                 movwf(AOP(result),size-1);
9069                 for (i = 1; i < size; i++)
9070                 {
9071                         emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9072                         movwf(AOP(result),size - 1 - i);
9073                 } // for
9074         }
9075         
9076 release:
9077         freeAsmop(left,NULL,ic,TRUE);
9078         freeAsmop(result,NULL,ic,TRUE);
9079         
9080 }
9081 /*-----------------------------------------------------------------*/
9082 /* genPointerGet - generate code for pointer get                   */
9083 /*-----------------------------------------------------------------*/
9084 static void genPointerGet (iCode *ic)
9085 {
9086         operand *left, *result ;
9087         sym_link *type, *etype;
9088         int p_type = -1;
9089         
9090         FENTRY;
9091         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9092         
9093         left = IC_LEFT(ic);
9094         result = IC_RESULT(ic) ;
9095         
9096         /* depending on the type of pointer we need to
9097         move it to the correct pointer register */
9098         type = operandType(left);
9099         etype = getSpec(type);
9100         
9101         if (IS_PTR_CONST(type))
9102                 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9103         
9104         /* if left is of type of pointer then it is simple */
9105         if (IS_PTR(type) && !IS_FUNC(type->next)) 
9106                 p_type = DCL_TYPE(type);
9107         else {
9108                 /* we have to go by the storage class */
9109                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9110                 
9111                 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9112                 
9113                 if (SPEC_OCLS(etype)->codesp ) {
9114                         DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9115                         //p_type = CPOINTER ; 
9116                 }
9117                 else
9118                         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9119                                 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9120                         /*p_type = FPOINTER ;*/ 
9121                         else
9122                                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9123                                         DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9124                                 /*        p_type = PPOINTER; */
9125                                 else
9126                                         if (SPEC_OCLS(etype) == idata )
9127                                                 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9128                                         /*      p_type = IPOINTER; */
9129                                         else
9130                                                 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9131                                         /*      p_type = POINTER ; */
9132         }
9133         
9134         /* now that we have the pointer type we assign
9135         the pointer values */
9136         switch (p_type) {
9137                 
9138         case POINTER: 
9139         case FPOINTER:
9140         //case IPOINTER:
9141                 genNearPointerGet (left,result,ic);
9142                 break;
9143 /*
9144         case PPOINTER:
9145                 genPagedPointerGet(left,result,ic);
9146                 break;
9147                 
9148         case FPOINTER:
9149                 genFarPointerGet (left,result,ic);
9150                 break;
9151 */              
9152         case CPOINTER:
9153                 genConstPointerGet (left,result,ic);
9154                 break;
9155                 
9156         case GPOINTER:
9157                 genGenPointerGet (left,result,ic);
9158                 break;
9159         default:
9160                 assert ( !"unhandled pointer type" );
9161                 break;
9162         }
9163         
9164 }
9165
9166 /*-----------------------------------------------------------------*/
9167 /* genPackBits - generates code for packed bit storage             */
9168 /*-----------------------------------------------------------------*/
9169 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9170 {
9171   int blen;             /* bitfield length */
9172   int bstr;             /* bitfield starting bit within byte */
9173   int litval;           /* source literal value (if AOP_LIT) */
9174   unsigned char mask;   /* bitmask within current byte */
9175
9176   FENTRY;
9177   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9178
9179   blen = SPEC_BLEN (etype);
9180   bstr = SPEC_BSTR (etype);
9181
9182   /* If the bitfield length is less than a byte and does not cross byte boundaries */
9183   if ((blen <= 8) && ((bstr + blen) <= 8))
9184   {
9185     mask = ((unsigned char) (0xFF << (blen + bstr)) |
9186             (unsigned char) (0xFF >> (8 - bstr)));
9187
9188     if (AOP_TYPE (right) == AOP_LIT)
9189     {
9190       /* Case with a bitfield length <8 and literal source */
9191       int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9192       if (blen == 1) {
9193         pCodeOp *pcop;
9194         
9195         switch (p_type)
9196         {
9197         case -1:
9198           if (AOP(result)->type == AOP_PCODE)
9199             pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9200           else
9201             pcop = popGet(AOP(result),0);
9202           emitpcode(lit?POC_BSF:POC_BCF,pcop);
9203           break;
9204         
9205         case POINTER:
9206         case FPOINTER:
9207           setup_fsr (result);
9208           emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9209           break;
9210         
9211         case CPOINTER:
9212           assert( !"trying to assign to bitfield via pointer to __code space" );
9213           break;
9214         
9215         case GPOINTER:
9216           emitPtrByteGet(result, p_type, FALSE);
9217           if (lit) {
9218             emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9219           } else {
9220             emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9221           }
9222           emitPtrByteSet(result, p_type, TRUE);
9223           break;
9224         
9225         default:
9226           assert( !"unhandled pointer type" );
9227           break;
9228         } // switch (p_type)
9229       } else {
9230         /* blen > 1 */
9231         litval = lit << bstr;
9232         litval &= (~mask) & 0x00ff;
9233         
9234         switch (p_type)
9235         {
9236         case -1:
9237           mov2w (AOP(result), 0);
9238           if ((litval|mask) != 0x00ff)
9239             emitpcode(POC_ANDLW, popGetLit (mask));
9240           if (litval != 0x00)
9241             emitpcode(POC_IORLW, popGetLit (litval));
9242           movwf (AOP(result), 0);
9243           break;
9244         
9245         case POINTER:
9246         case FPOINTER:
9247         case GPOINTER:
9248           emitPtrByteGet(result, p_type, FALSE);
9249           if ((litval|mask) != 0x00ff)
9250             emitpcode(POC_ANDLW, popGetLit (mask));
9251           if (litval != 0x00)
9252             emitpcode(POC_IORLW, popGetLit (litval));
9253           emitPtrByteSet(result, p_type, TRUE);
9254           break;
9255         
9256         case CPOINTER:
9257           assert( !"trying to assign to bitfield via pointer to __code space" );
9258           break;
9259         
9260         default:
9261           assert( !"unhandled pointer type" );
9262           break;
9263         } // switch
9264       } // if (blen > 1)
9265     }
9266     else
9267     {
9268       /* right is no literal */
9269       if (blen==1) {
9270         switch (p_type)
9271         {
9272         case -1:
9273           /* Note more efficient code, of pre clearing bit then only setting it if required,
9274            * can only be done if it is known that the result is not a SFR */
9275           emitpcode(POC_RRFW,popGet(AOP(right),0));
9276           emitSKPC;
9277           emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9278           emitSKPNC;
9279           emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9280           break;
9281         
9282         case POINTER:
9283         case FPOINTER:
9284         case GPOINTER:
9285           emitPtrByteGet (result, p_type, FALSE);
9286           emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9287           emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9288           emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9289           emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9290           emitPtrByteSet (result, p_type, TRUE);
9291           break;
9292         
9293         case CPOINTER:
9294           assert( !"trying to assign to bitfield via pointer to __code space" );
9295           break;
9296         
9297         default:
9298           assert( !"unhandled pointer type" );
9299           break;
9300         } // switch
9301         return;
9302       } else {
9303         /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9304         pCodeOp *temp = popGetTempReg ();
9305
9306         mov2w (AOP(right), 0);
9307         if (blen < 8) {
9308           emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9309         }
9310         emitpcode(POC_MOVWF, temp);
9311         if (bstr) {
9312           AccLsh (temp, bstr);
9313         }
9314         
9315         switch (p_type)
9316         {
9317         case -1:
9318           mov2w (AOP(result), 0);
9319           emitpcode(POC_ANDLW, popGetLit (mask));
9320           emitpcode(POC_IORFW, temp);
9321           movwf (AOP(result), 0);
9322           break;
9323         
9324         case POINTER:
9325         case FPOINTER:
9326         case GPOINTER:
9327           emitPtrByteGet (result, p_type, FALSE);
9328           emitpcode(POC_ANDLW, popGetLit (mask));
9329           emitpcode(POC_IORFW, temp);
9330           emitPtrByteSet (result, p_type, TRUE);
9331           break;
9332         
9333         case CPOINTER:
9334           assert( !"trying to assign to bitfield via pointer to __code space" );
9335           break;
9336         
9337         default:
9338           assert( !"unhandled pointer type" );
9339           break;
9340         } // switch
9341
9342         popReleaseTempReg (temp);
9343       } // if (blen > 1)
9344     } // if (AOP(right)->type != AOP_LIT)
9345     return;
9346   } // if (blen <= 8 && ((blen + bstr) <= 8))
9347
9348   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9349 }
9350
9351 unsigned long
9352 bitpatternFromVal (value *val)
9353 {
9354   union {
9355     float d;
9356     unsigned long l;
9357   } float_long;
9358
9359   assert (sizeof (float) == sizeof (long));
9360
9361   //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));
9362
9363   switch (SPEC_NOUN(val->type))
9364   {
9365   case V_INT:
9366   case V_CHAR:
9367     return (unsigned long)floatFromVal (val);
9368     
9369   case V_FLOAT:
9370   case V_DOUBLE:
9371     float_long.d = floatFromVal (val);
9372     return float_long.l;
9373     
9374   default:
9375     assert( !"unhandled value type" );
9376     break;
9377   }
9378
9379   float_long.d = floatFromVal (val);
9380   return float_long.l;
9381 }
9382
9383 /*-----------------------------------------------------------------*/
9384 /* genDataPointerSet - remat pointer to data space                 */
9385 /*-----------------------------------------------------------------*/
9386 static void genDataPointerSet(operand *right,
9387         operand *result,
9388         iCode *ic)
9389 {
9390         int size, offset = 0 ;
9391         int ressize;
9392         
9393         FENTRY;
9394         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9395         aopOp(right,ic,FALSE);
9396         aopOp(result,ic,FALSE);
9397         
9398         assert (IS_SYMOP(result));
9399         assert (IS_PTR(OP_SYM_TYPE(result)));
9400         
9401         size = AOP_SIZE(right);
9402         ressize = getSize(OP_SYM_ETYPE(result));
9403         if (size > ressize) size = ressize;
9404         //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9405         
9406         //assert( !"what's going on here?" );
9407
9408         /*
9409         if ( AOP_TYPE(result) == AOP_PCODE) {
9410         fprintf(stderr,"genDataPointerSet   %s, %d\n",
9411         AOP(result)->aopu.pcop->name,
9412         PCOI(AOP(result)->aopu.pcop)->offset);
9413         }
9414         */
9415         
9416         // tsd, was l+1 - the underline `_' prefix was being stripped
9417         while (size--) {
9418                 emitpComment ("%s:%u: size=%d/%d, offset=%i", __FILE__,__LINE__, size, ressize, offset);
9419                 
9420                 if (AOP_TYPE(right) == AOP_LIT) {
9421                         /* XXX: might be float... */
9422                         unsigned int lit = bitpatternFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9423                         lit = lit >> (8*offset);
9424                         //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9425                         if(lit&0xff) {
9426                                 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9427                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9428                         } else {
9429                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9430                         }
9431                 } else {
9432                         //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9433                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9434                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9435                 }
9436                 
9437                 offset++;
9438         }
9439         
9440         freeAsmop(right,NULL,ic,TRUE);
9441         freeAsmop(result,NULL,ic,TRUE);
9442 }
9443
9444 /*-----------------------------------------------------------------*/
9445 /* genNearPointerSet - pic14_emitcode for near pointer put         */
9446 /*-----------------------------------------------------------------*/
9447 static void genNearPointerSet (operand *right,
9448                                                            operand *result, 
9449                                                            iCode *ic)
9450 {
9451         asmop *aop = NULL;
9452         sym_link *ptype = operandType(result);
9453         sym_link *retype = getSpec(operandType(right));
9454         sym_link *letype = getSpec(ptype);
9455         int direct = 0;
9456         
9457         
9458         FENTRY;
9459         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9460         aopOp(result,ic,FALSE);
9461         
9462 #if 1
9463         /* if the result is rematerializable &
9464         in data space & not a bit variable */
9465         //if (AOP_TYPE(result) == AOP_IMMD &&
9466         if (AOP_TYPE(result) == AOP_PCODE &&
9467                 PIC_IS_DATA_PTR(ptype) &&
9468                 !IS_BITVAR (retype) &&
9469                 !IS_BITVAR (letype)) {
9470                 genDataPointerSet (right,result,ic);
9471                 freeAsmop(result,NULL,ic,TRUE);
9472                 return;
9473         }
9474 #endif
9475
9476         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9477         aopOp(right,ic,FALSE);
9478         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9479         
9480         /* Check if can access directly instead of via a pointer */
9481         if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9482                 direct = 1;
9483         }
9484         
9485         if (IS_BITFIELD (letype))
9486         {
9487           genPackBits (letype, result, right, direct?-1:POINTER);
9488           return;
9489         }
9490         
9491         /* If the pointer value is not in a the FSR then need to put it in */
9492         /* Must set/reset IRP bit for use with FSR. */
9493         /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9494         if (!direct)
9495                 setup_fsr (result);
9496
9497         {
9498                 /* we have can just get the values */
9499                 int size = AOP_SIZE(right);
9500                 int offset = 0 ;    
9501                 
9502                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9503                 while (size--) {
9504                         char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9505                         if (*l == '@' ) {
9506                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9507                         } else {
9508                                 if (AOP_TYPE(right) == AOP_LIT) {
9509                                         emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9510                                 } else {
9511                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9512                                 }
9513                                 if (direct)
9514                                         emitpcode(POC_MOVWF,popGet(AOP(result),0));
9515                                 else
9516                                         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9517                         }
9518                         if (size && !direct)
9519                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9520                         offset++;
9521                 }
9522         }
9523         
9524         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9525         /* now some housekeeping stuff */
9526         if (aop) {
9527                 /* we had to allocate for this iCode */
9528                 freeAsmop(NULL,aop,ic,TRUE);
9529         } else { 
9530                 /* we did not allocate which means left
9531                 already in a pointer register, then
9532                 if size > 0 && this could be used again
9533                 we have to point it back to where it 
9534                 belongs */
9535                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9536                 if (AOP_SIZE(right) > 1 &&
9537                         !OP_SYMBOL(result)->remat &&
9538                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9539                         ic->depth )) {
9540                         int size = AOP_SIZE(right) - 1;
9541                         while (size--)
9542                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9543                 }
9544         }
9545         
9546         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9547         /* done */
9548
9549         freeAsmop(right,NULL,ic,TRUE);
9550         freeAsmop(result,NULL,ic,TRUE);
9551 }
9552
9553 #if 0
9554 /*-----------------------------------------------------------------*/
9555 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
9556 /*-----------------------------------------------------------------*/
9557 static void genPagedPointerSet (operand *right,
9558                                                                 operand *result, 
9559                                                                 iCode *ic)
9560 {
9561         asmop *aop = NULL;
9562         regs *preg = NULL ;
9563         char *rname , *l;
9564         sym_link *retype;
9565         
9566         FENTRY;
9567         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9568         
9569         retype= getSpec(operandType(right));
9570         
9571         aopOp(result,ic,FALSE);
9572         
9573         /* if the value is already in a pointer register
9574         then don't need anything more */
9575         if (!AOP_INPREG(AOP(result))) {
9576                 /* otherwise get a free pointer register */
9577                 aop = newAsmop(0);
9578                 preg = getFreePtr(ic,&aop,FALSE);
9579                 pic14_emitcode("mov","%s,%s",
9580                         preg->name,
9581                         aopGet(AOP(result),0,FALSE,TRUE));
9582                 rname = preg->name ;
9583         } else
9584                 rname = aopGet(AOP(result),0,FALSE,FALSE);
9585         
9586         freeAsmop(result,NULL,ic,TRUE);
9587         aopOp (right,ic,FALSE);
9588         
9589         /* if bitfield then unpack the bits */
9590         if (IS_BITFIELD(retype)) 
9591                 genPackBits (retype,result,right,rname,PPOINTER);
9592         else {
9593                 /* we have can just get the values */
9594                 int size = AOP_SIZE(right);
9595                 int offset = 0 ;  
9596                 
9597                 while (size--) {
9598                         l = aopGet(AOP(right),offset,FALSE,TRUE);
9599                         
9600                         MOVA(l);
9601                         pic14_emitcode("movx","@%s,a",rname);
9602                         
9603                         if (size)
9604                                 pic14_emitcode("inc","%s",rname);
9605                         
9606                         offset++;
9607                 }
9608         }
9609         
9610         /* now some housekeeping stuff */
9611         if (aop) {
9612                 /* we had to allocate for this iCode */
9613                 freeAsmop(NULL,aop,ic,TRUE);
9614         } else { 
9615         /* we did not allocate which means left
9616         already in a pointer register, then
9617         if size > 0 && this could be used again
9618         we have to point it back to where it 
9619                 belongs */
9620                 if (AOP_SIZE(right) > 1 &&
9621                         !OP_SYMBOL(result)->remat &&
9622                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9623                         ic->depth )) {
9624                         int size = AOP_SIZE(right) - 1;
9625                         while (size--)
9626                                 pic14_emitcode("dec","%s",rname);
9627                 }
9628         }
9629         
9630         /* done */
9631         freeAsmop(right,NULL,ic,TRUE);
9632         
9633         
9634 }
9635
9636 /*-----------------------------------------------------------------*/
9637 /* genFarPointerSet - set value from far space                     */
9638 /*-----------------------------------------------------------------*/
9639 static void genFarPointerSet (operand *right,
9640                                                           operand *result, iCode *ic)
9641 {
9642         int size, offset ;
9643         sym_link *retype = getSpec(operandType(right));
9644         
9645         FENTRY;
9646         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9647         aopOp(result,ic,FALSE);
9648         
9649         /* if the operand is already in dptr 
9650         then we do nothing else we move the value to dptr */
9651         if (AOP_TYPE(result) != AOP_STR) {
9652                 /* if this is remateriazable */
9653                 if (AOP_TYPE(result) == AOP_IMMD)
9654                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9655                 else { /* we need to get it byte by byte */
9656                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9657                         pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9658                         if (options.model == MODEL_FLAT24)
9659                         {
9660                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9661                         }
9662                 }
9663         }
9664         /* so dptr know contains the address */
9665         freeAsmop(result,NULL,ic,TRUE);
9666         aopOp(right,ic,FALSE);
9667         
9668         /* if bit then unpack */
9669         if (IS_BITFIELD(retype)) 
9670                 genPackBits(retype,result,right,"dptr",FPOINTER);
9671         else {
9672                 size = AOP_SIZE(right);
9673                 offset = 0 ;
9674                 
9675                 while (size--) {
9676                         char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9677                         MOVA(l);
9678                         pic14_emitcode("movx","@dptr,a");
9679                         if (size)
9680                                 pic14_emitcode("inc","dptr");
9681                 }
9682         }
9683         
9684         freeAsmop(right,NULL,ic,TRUE);
9685 }
9686 #endif
9687
9688 /*-----------------------------------------------------------------*/
9689 /* genGenPointerSet - set value from generic pointer space         */
9690 /*-----------------------------------------------------------------*/
9691 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9692 {
9693         sym_link *retype = getSpec(operandType(result));
9694         
9695         FENTRY;
9696         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9697         aopOp(right,ic,FALSE);
9698         aopOp(result,ic,FALSE);
9699
9700         
9701         DEBUGpic14_AopType(__LINE__,right,NULL,result);
9702
9703         if (IS_BITFIELD(retype))
9704         {
9705           genPackBits (retype, result, right, GPOINTER);
9706           return;
9707         }
9708
9709         {
9710           /* emit call to __gptrput */
9711           char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9712           int size = AOP_SIZE(right);
9713           int idx = 0;
9714
9715           assert (size == getSize(OP_SYM_ETYPE(result)));
9716           assert (size > 0 && size <= 4);
9717
9718           /* pass arguments */
9719           /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9720           {
9721             int off = size;
9722             idx = 2;
9723             while (off--)
9724             {
9725               mov2w_op (right, off);
9726               emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9727             }
9728             idx = 0;
9729           }
9730           /* - address */
9731           assert (AOP_SIZE(result) == 3);
9732           mov2w(AOP(result), 0);
9733           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9734           mov2w(AOP(result), 1);
9735           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9736           mov2w(AOP(result), 2);
9737           call_libraryfunc (func[size]);
9738         }
9739         
9740         freeAsmop(right,NULL,ic,TRUE);
9741         freeAsmop(result,NULL,ic,TRUE);
9742 }
9743
9744 /*-----------------------------------------------------------------*/
9745 /* genPointerSet - stores the value into a pointer location        */
9746 /*-----------------------------------------------------------------*/
9747 static void genPointerSet (iCode *ic)
9748 {    
9749         operand *right, *result ;
9750         sym_link *type, *etype;
9751         int p_type;
9752         
9753         FENTRY;
9754         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9755         
9756         right = IC_RIGHT(ic);
9757         result = IC_RESULT(ic) ;
9758         
9759         /* depending on the type of pointer we need to
9760         move it to the correct pointer register */
9761         type = operandType(result);
9762         etype = getSpec(type);
9763         /* if left is of type of pointer then it is simple */
9764         if (IS_PTR(type) && !IS_FUNC(type->next)) {
9765                 p_type = DCL_TYPE(type);
9766         }
9767         else {
9768                 /* we have to go by the storage class */
9769                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9770                 
9771                 /*  if (SPEC_OCLS(etype)->codesp ) { */
9772                 /*      p_type = CPOINTER ;  */
9773                 /*  } */
9774                 /*  else */
9775                 /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9776                 /*    p_type = FPOINTER ; */
9777                 /*      else */
9778                 /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9779                 /*        p_type = PPOINTER ; */
9780                 /*    else */
9781                 /*        if (SPEC_OCLS(etype) == idata ) */
9782                 /*      p_type = IPOINTER ; */
9783                 /*        else */
9784                 /*      p_type = POINTER ; */
9785         }
9786         
9787         /* now that we have the pointer type we assign
9788         the pointer values */
9789         switch (p_type) {
9790                 
9791         case POINTER:
9792         case FPOINTER:
9793         //case IPOINTER:
9794                 genNearPointerSet (right,result,ic);
9795                 break;
9796 /*
9797         case PPOINTER:
9798                 genPagedPointerSet (right,result,ic);
9799                 break;
9800                 
9801         case FPOINTER:
9802                 genFarPointerSet (right,result,ic);
9803                 break;
9804 */
9805         case GPOINTER:
9806                 genGenPointerSet (right,result,ic);
9807                 break;
9808                 
9809         default:
9810                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9811                         "genPointerSet: illegal pointer type");
9812         }
9813 }
9814
9815 /*-----------------------------------------------------------------*/
9816 /* genIfx - generate code for Ifx statement                        */
9817 /*-----------------------------------------------------------------*/
9818 static void genIfx (iCode *ic, iCode *popIc)
9819 {
9820         operand *cond = IC_COND(ic);
9821         int isbit =0;
9822         
9823         FENTRY;
9824         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9825         
9826         aopOp(cond,ic,FALSE);
9827         
9828         /* get the value into acc */
9829         if (AOP_TYPE(cond) != AOP_CRY)
9830                 pic14_toBoolean(cond);
9831         else
9832                 isbit = 1;
9833         
9834         /* if there was something to be popped then do it */
9835         if (popIc)
9836                 genIpop(popIc);
9837         
9838         if (isbit)
9839         {
9840                 /* This assumes that CARRY is set iff cond is true */
9841                 if (IC_TRUE(ic))
9842                 {
9843                         assert (!IC_FALSE(ic));
9844                         emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9845                         //emitSKPNC;
9846                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9847                 } else {
9848                         assert (IC_FALSE(ic));
9849                         emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9850                         //emitSKPC;
9851                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9852                 }
9853                 if (0)
9854                 {
9855                         static int hasWarned = 0;
9856                         if (!hasWarned)
9857                         {
9858                                 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9859                                 hasWarned = 1;
9860                         }
9861                 }
9862         }
9863         else
9864         {
9865                 /* now Z is set iff !cond */
9866                 if (IC_TRUE(ic))
9867                 {
9868                         assert (!IC_FALSE(ic));
9869                         emitSKPZ;
9870                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9871                 } else {
9872                         emitSKPNZ;
9873                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9874                 }
9875         }
9876         
9877         ic->generated = 1;
9878         
9879         /* the result is now in the accumulator */
9880         freeAsmop(cond,NULL,ic,TRUE);
9881 }
9882
9883 /*-----------------------------------------------------------------*/
9884 /* genAddrOf - generates code for address of                       */
9885 /*-----------------------------------------------------------------*/
9886 static void genAddrOf (iCode *ic)
9887 {
9888         operand *right, *result, *left;
9889         int size, offset ;
9890         
9891         FENTRY;
9892         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9893         
9894         
9895         //aopOp(IC_RESULT(ic),ic,FALSE);
9896         
9897         aopOp((left=IC_LEFT(ic)),ic,FALSE);
9898         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9899         aopOp((result=IC_RESULT(ic)),ic,TRUE);
9900         
9901         DEBUGpic14_AopType(__LINE__,left,right,result);
9902         assert (IS_SYMOP (left));
9903         
9904         /* sanity check: generic pointers to code space are not yet supported,
9905          * pionters to codespace must not be assigned addresses of __data values. */
9906  #if 0
9907         fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9908         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)));
9909         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)));
9910         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)));
9911         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)));
9912 #endif
9913
9914         if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9915           fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9916                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9917                 OP_SYMBOL(left)->name);
9918         } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9919           fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9920                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9921                 OP_SYMBOL(left)->name);
9922         }
9923         
9924         size = AOP_SIZE(IC_RESULT(ic));
9925         if (IS_GENPTR(OP_SYM_TYPE(result))) {
9926                 /* strip tag */
9927                 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9928         }
9929         offset = 0;
9930         
9931         while (size--) {
9932                 /* fixing bug #863624, reported from (errolv) */
9933                 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9934                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9935                 
9936 #if 0
9937                 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9938                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9939 #endif
9940                 offset++;
9941         }
9942
9943         if (IS_GENPTR(OP_SYM_TYPE(result)))
9944         {
9945                 /* provide correct tag */
9946                 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9947                 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9948                 movwf (AOP(result), 2);
9949         }
9950         
9951         freeAsmop(left,NULL,ic,FALSE);
9952         freeAsmop(result,NULL,ic,TRUE);
9953         
9954 }
9955
9956 #if 0
9957 /*-----------------------------------------------------------------*/
9958 /* genFarFarAssign - assignment when both are in far space         */
9959 /*-----------------------------------------------------------------*/
9960 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9961 {
9962         int size = AOP_SIZE(right);
9963         int offset = 0;
9964         char *l ;
9965         /* first push the right side on to the stack */
9966         while (size--) {
9967                 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9968                 MOVA(l);
9969                 pic14_emitcode ("push","acc");
9970         }
9971         
9972         freeAsmop(right,NULL,ic,FALSE);
9973         /* now assign DPTR to result */
9974         aopOp(result,ic,FALSE);
9975         size = AOP_SIZE(result);
9976         while (size--) {
9977                 pic14_emitcode ("pop","acc");
9978                 aopPut(AOP(result),"a",--offset);
9979         }
9980         freeAsmop(result,NULL,ic,FALSE);
9981         
9982 }
9983 #endif
9984
9985 /*-----------------------------------------------------------------*/
9986 /* genAssign - generate code for assignment                        */
9987 /*-----------------------------------------------------------------*/
9988 static void genAssign (iCode *ic)
9989 {
9990         operand *result, *right;
9991         int size, offset,know_W;
9992         unsigned long lit = 0L;
9993         
9994         result = IC_RESULT(ic);
9995         right  = IC_RIGHT(ic) ;
9996         
9997         FENTRY;
9998         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9999         
10000         /* if they are the same */
10001         if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10002                 return ;
10003         
10004         aopOp(right,ic,FALSE);
10005         aopOp(result,ic,TRUE);
10006         
10007         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10008         
10009         /* if they are the same registers */
10010         if (pic14_sameRegs(AOP(right),AOP(result)))
10011                 goto release;
10012
10013         /* special case: assign from __code */
10014         if (!IS_ITEMP(right)                            /* --> iTemps never reside in __code */
10015                 && IS_SYMOP (right)                     /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
10016                 && !IS_FUNC(OP_SYM_TYPE(right))         /* --> we would want its address instead of the first instruction */
10017                 && !IS_CODEPTR(OP_SYM_TYPE(right))      /* --> get symbols address instread */
10018                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
10019         {
10020           emitpComment ("genAssign from CODESPACE");
10021           genConstPointerGet (right, result, ic);
10022           goto release;
10023         }
10024         
10025         /* just for symmetry reasons... */
10026         if (!IS_ITEMP(result)
10027                 && IS_SYMOP (result)
10028                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
10029         {
10030           assert ( !"cannot write to CODESPACE" );
10031         }
10032
10033         /* if the result is a bit */
10034         if (AOP_TYPE(result) == AOP_CRY) {
10035                 
10036         /* if the right size is a literal then
10037                 we know what the value is */
10038                 if (AOP_TYPE(right) == AOP_LIT) {
10039                         
10040                         emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10041                                 popGet(AOP(result),0));
10042                         
10043                         if (((int) operandLitValue(right))) 
10044                                 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10045                                 AOP(result)->aopu.aop_dir,
10046                                 AOP(result)->aopu.aop_dir);
10047                         else
10048                                 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10049                                 AOP(result)->aopu.aop_dir,
10050                                 AOP(result)->aopu.aop_dir);
10051                         goto release;
10052                 }
10053                 
10054                 /* the right is also a bit variable */
10055                 if (AOP_TYPE(right) == AOP_CRY) {
10056                         emitpcode(POC_BCF,    popGet(AOP(result),0));
10057                         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10058                         emitpcode(POC_BSF,    popGet(AOP(result),0));
10059                         
10060                         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10061                                 AOP(result)->aopu.aop_dir,
10062                                 AOP(result)->aopu.aop_dir);
10063                         pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10064                                 AOP(right)->aopu.aop_dir,
10065                                 AOP(right)->aopu.aop_dir);
10066                         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10067                                 AOP(result)->aopu.aop_dir,
10068                                 AOP(result)->aopu.aop_dir);
10069                         goto release ;
10070                 }
10071                 
10072                 /* we need to or */
10073                 emitpcode(POC_BCF,    popGet(AOP(result),0));
10074                 pic14_toBoolean(right);
10075                 emitSKPZ;
10076                 emitpcode(POC_BSF,    popGet(AOP(result),0));
10077                 //aopPut(AOP(result),"a",0);
10078                 goto release ;
10079         }
10080         
10081         /* bit variables done */
10082         /* general case */
10083         size = AOP_SIZE(result);
10084         offset = 0 ;
10085         if(AOP_TYPE(right) == AOP_LIT)
10086                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10087         
10088         if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10089                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10090                 if(aopIdx(AOP(result),0) == 4) {
10091                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10092                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10093                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10094                         goto release;
10095                 } else
10096                         DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10097         }
10098         
10099         know_W=-1;
10100         while (size--) {
10101                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10102                 if(AOP_TYPE(right) == AOP_LIT) {
10103                         if(lit&0xff) {
10104                                 if(know_W != (int)(lit&0xff))
10105                                         emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10106                                 know_W = lit&0xff;
10107                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10108                         } else
10109                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10110                         
10111                         lit >>= 8;
10112                         
10113                 } else if (AOP_TYPE(right) == AOP_CRY) {
10114                         emitpcode(POC_CLRF, popGet(AOP(result),offset));
10115                         if(offset == 0) {
10116                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10117                                 emitpcode(POC_INCF, popGet(AOP(result),0));
10118                         }
10119                 } else {
10120                         mov2w_op (right, offset);
10121                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10122                 }
10123                 
10124                 offset++;
10125         }
10126         
10127         
10128 release:
10129         freeAsmop (right,NULL,ic,FALSE);
10130         freeAsmop (result,NULL,ic,TRUE);
10131 }   
10132
10133 /*-----------------------------------------------------------------*/
10134 /* genJumpTab - genrates code for jump table                       */
10135 /*-----------------------------------------------------------------*/
10136 static void genJumpTab (iCode *ic)
10137 {
10138         symbol *jtab;
10139         char *l;
10140         
10141         FENTRY;
10142         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10143         
10144         aopOp(IC_JTCOND(ic),ic,FALSE);
10145         /* get the condition into accumulator */
10146         l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10147         MOVA(l);
10148         /* multiply by three */
10149         pic14_emitcode("add","a,acc");
10150         pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10151         
10152         jtab = newiTempLabel(NULL);
10153         pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10154         pic14_emitcode("jmp","@a+dptr");
10155         pic14_emitcode("","%05d_DS_:",jtab->key+100);
10156         
10157         emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10158         emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10159         emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10160         emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10161         emitSKPNC;
10162         emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10163         emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10164         emitpLabel(jtab->key);
10165         
10166         freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10167         
10168         /* now generate the jump labels */
10169         for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10170         jtab = setNextItem(IC_JTLABELS(ic))) {
10171                 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10172                 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10173                 
10174         }
10175         
10176 }
10177
10178 /*-----------------------------------------------------------------*/
10179 /* genMixedOperation - gen code for operators between mixed types  */
10180 /*-----------------------------------------------------------------*/
10181 /*
10182 TSD - Written for the PIC port - but this unfortunately is buggy.
10183 This routine is good in that it is able to efficiently promote 
10184 types to different (larger) sizes. Unfortunately, the temporary
10185 variables that are optimized out by this routine are sometimes
10186 used in other places. So until I know how to really parse the 
10187 iCode tree, I'm going to not be using this routine :(.
10188 */
10189 static int genMixedOperation (iCode *ic)
10190 {
10191         FENTRY;
10192 #if 0
10193         operand *result = IC_RESULT(ic);
10194         sym_link *ctype = operandType(IC_LEFT(ic));
10195         operand *right = IC_RIGHT(ic);
10196         int ret = 0;
10197         int big,small;
10198         int offset;
10199         
10200         iCode *nextic;
10201         operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10202         
10203         pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10204         
10205         nextic = ic->next;
10206         if(!nextic)
10207                 return 0;
10208         
10209         nextright = IC_RIGHT(nextic);
10210         nextleft  = IC_LEFT(nextic);
10211         nextresult = IC_RESULT(nextic);
10212         
10213         aopOp(right,ic,FALSE);
10214         aopOp(result,ic,FALSE);
10215         aopOp(nextright,  nextic, FALSE);
10216         aopOp(nextleft,   nextic, FALSE);
10217         aopOp(nextresult, nextic, FALSE);
10218         
10219         if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10220                 
10221                 operand *t = right;
10222                 right = nextright;
10223                 nextright = t; 
10224                 
10225                 pic14_emitcode(";remove right +","");
10226                 
10227         } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10228         /*
10229         operand *t = right;
10230         right = nextleft;
10231         nextleft = t; 
10232                 */
10233                 pic14_emitcode(";remove left +","");
10234         } else
10235                 return 0;
10236         
10237         big = AOP_SIZE(nextleft);
10238         small = AOP_SIZE(nextright);
10239         
10240         switch(nextic->op) {
10241                 
10242         case '+':
10243                 pic14_emitcode(";optimize a +","");
10244                 /* if unsigned or not an integral type */
10245                 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10246                         pic14_emitcode(";add a bit to something","");
10247                 } else {
10248                         
10249                         pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10250                         
10251                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10252                                 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10253                                 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10254                         } else
10255                                 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10256                         
10257                         offset = 0;
10258                         while(--big) {
10259                                 
10260                                 offset++;
10261                                 
10262                                 if(--small) {
10263                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10264                                                 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10265                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10266                                         }
10267                                         
10268                                         pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10269                                         emitSKPNC;
10270                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10271                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10272                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10273                                         pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10274                                         pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10275                                         
10276                                 } else {
10277                                         pic14_emitcode("rlf","known_zero,w");
10278                                         
10279                                         /*
10280                                         if right is signed
10281                                         btfsc  right,7
10282                                         addlw ff
10283                                         */
10284                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10285                                                 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10286                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10287                                         } else {
10288                                                 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10289                                         }
10290                                 }
10291                         }
10292                         ret = 1;
10293                 }
10294         }
10295         ret = 1;
10296         
10297 release:
10298         freeAsmop(right,NULL,ic,TRUE);
10299         freeAsmop(result,NULL,ic,TRUE);
10300         freeAsmop(nextright,NULL,ic,TRUE);
10301         freeAsmop(nextleft,NULL,ic,TRUE);
10302         if(ret)
10303                 nextic->generated = 1;
10304         
10305         return ret;
10306 #else
10307         return 0;
10308 #endif
10309 }
10310 /*-----------------------------------------------------------------*/
10311 /* genCast - gen code for casting                                  */
10312 /*-----------------------------------------------------------------*/
10313 static void genCast (iCode *ic)
10314 {
10315         operand *result = IC_RESULT(ic);
10316         sym_link *restype = operandType(result);
10317         sym_link *rtype = operandType(IC_RIGHT(ic));
10318         operand *right = IC_RIGHT(ic);
10319         int size, offset ;
10320         
10321         FENTRY;
10322         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10323         /* if they are equivalent then do nothing */
10324         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10325                 return ;
10326         
10327         aopOp(right,ic,FALSE) ;
10328         aopOp(result,ic,FALSE);
10329         
10330         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10331         
10332         /* if the result is a bit */
10333         if (AOP_TYPE(result) == AOP_CRY) {
10334                 assert(!"assigning to bit variables is not supported");
10335         }
10336         
10337         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10338                 int offset = 1;
10339                 size = AOP_SIZE(result);
10340                 
10341                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10342                 
10343                 emitpcode(POC_CLRF,   popGet(AOP(result),0));
10344                 emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10345                 emitpcode(POC_INCF,   popGet(AOP(result),0));
10346                 
10347                 while (size--)
10348                         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
10349                 
10350                 goto release;
10351         }
10352         
10353         if (IS_PTR(restype))
10354         {
10355           operand *result = IC_RESULT(ic);
10356           //operand *left = IC_LEFT(ic);
10357           operand *right = IC_RIGHT(ic);
10358           int tag = 0xff;
10359           
10360           /* copy common part */
10361           int max, size = AOP_SIZE(result);
10362           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10363           DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10364
10365           /* warn if we discard generic opinter tag */
10366           if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10367           {
10368             //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10369           } // if
10370
10371           max = size;
10372           while (size--)
10373           {
10374             mov2w_op (right, size);
10375             movwf (AOP(result), size);
10376           } // while
10377
10378           /* upcast into generic pointer type? */
10379           if (IS_GENPTR(restype)
10380                 && (size < AOP_SIZE(result))
10381                 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10382           {
10383             //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10384             if (IS_PTR(rtype))
10385             {
10386               switch (DCL_TYPE(rtype))
10387               {
10388               case POINTER:     /* __data */
10389               case FPOINTER:    /* __data */
10390                 assert (AOP_SIZE(right) == 2);
10391                 tag = GPTRTAG_DATA;
10392                 break;
10393
10394               case CPOINTER:    /* __code */
10395                 assert (AOP_SIZE(right) == 2);
10396                 tag = GPTRTAG_CODE;
10397                 break;
10398                 
10399               case GPOINTER:    /* unknown destination, __data or __code */
10400                 /* assume __data space (address of immediate) */
10401                 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10402                 if (AOP(right)->code)
10403                   tag = GPTRTAG_CODE;
10404                 else
10405                   tag = GPTRTAG_DATA;
10406                 break;
10407                 
10408               default:
10409                 assert (!"unhandled pointer type");
10410               } // switch
10411             } else {
10412               /* convert other values into pointers to __data space */
10413               tag = GPTRTAG_DATA;
10414             }
10415
10416             assert (AOP_SIZE(result) == 3);
10417             if (tag == 0) {
10418               emitpcode(POC_CLRF, popGet(AOP(result), 2));
10419             } else {
10420               emitpcode(POC_MOVLW, popGetLit(tag));
10421               movwf(AOP(result), 2);
10422             }
10423           } else {
10424             addSign(result, max, 0);
10425           } // if
10426           goto release;
10427         }
10428         
10429         /* if they are the same size : or less */
10430         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10431                 
10432                 /* if they are in the same place */
10433                 if (pic14_sameRegs(AOP(right),AOP(result)))
10434                         goto release;
10435                 
10436                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10437                 if (IS_PTR_CONST(rtype))
10438                         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10439                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10440                         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10441                 
10442                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10443                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10444                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
10445                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10446                         emitpcode(POC_MOVWF, popGet(AOP(result),1));
10447                         if(AOP_SIZE(result) <2)
10448                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10449                         
10450                 } else {
10451                         
10452                         /* if they in different places then copy */
10453                         size = AOP_SIZE(result);
10454                         offset = 0 ;
10455                         while (size--) {
10456                                 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10457                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10458                                 
10459                                 //aopPut(AOP(result),
10460                                 // aopGet(AOP(right),offset,FALSE,FALSE),
10461                                 // offset);
10462                                 
10463                                 offset++;
10464                         }
10465                 }
10466                 goto release;
10467         }
10468         
10469         /* so we now know that the size of destination is greater
10470         than the size of the source.
10471         Now, if the next iCode is an operator then we might be
10472         able to optimize the operation without performing a cast.
10473         */
10474         if(0 && genMixedOperation(ic)) {
10475                 /* XXX: cannot optimize: must copy regs! */
10476                 goto release;
10477         }
10478         
10479         /* we move to result for the size of source */
10480         size = AOP_SIZE(right);
10481         offset = 0 ;
10482         while (size--) {
10483                 emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
10484                 emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
10485                 offset++;
10486         }
10487
10488         addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10489
10490 release:
10491         freeAsmop(right,NULL,ic,TRUE);
10492         freeAsmop(result,NULL,ic,TRUE);
10493         
10494 }
10495
10496 /*-----------------------------------------------------------------*/
10497 /* genDjnz - generate decrement & jump if not zero instrucion      */
10498 /*-----------------------------------------------------------------*/
10499 static int genDjnz (iCode *ic, iCode *ifx)
10500 {
10501         symbol *lbl, *lbl1;
10502         FENTRY;
10503         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10504         
10505         if (!ifx)
10506                 return 0;
10507         
10508                 /* if the if condition has a false label
10509         then we cannot save */
10510         if (IC_FALSE(ifx))
10511                 return 0;
10512         
10513                 /* if the minus is not of the form 
10514         a = a - 1 */
10515         if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10516                 !IS_OP_LITERAL(IC_RIGHT(ic)))
10517                 return 0;
10518         
10519         if (operandLitValue(IC_RIGHT(ic)) != 1)
10520                 return 0;
10521         
10522                 /* if the size of this greater than one then no
10523         saving */
10524         if (getSize(operandType(IC_RESULT(ic))) > 1)
10525                 return 0;
10526         
10527         /* otherwise we can save BIG */
10528         lbl = newiTempLabel(NULL);
10529         lbl1= newiTempLabel(NULL);
10530         
10531         aopOp(IC_RESULT(ic),ic,FALSE);
10532         
10533         if (IS_AOP_PREG(IC_RESULT(ic))) {
10534                 pic14_emitcode("dec","%s",
10535                         aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10536                 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10537                 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10538         } else {  
10539                 
10540                 
10541                 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10542                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10543                 
10544                 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10545                 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10546                 
10547         }
10548         /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10549         /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10550         /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10551         /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10552         
10553         
10554         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10555         ifx->generated = 1;
10556         return 1;
10557 }
10558
10559 /*-----------------------------------------------------------------*/
10560 /* genReceive - generate code for a receive iCode                  */
10561 /*-----------------------------------------------------------------*/
10562 static void genReceive (iCode *ic)
10563 {
10564         FENTRY;
10565         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10566         
10567         if (isOperandInFarSpace(IC_RESULT(ic)) &&
10568                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10569                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10570                 
10571                 int size = getSize(operandType(IC_RESULT(ic)));
10572                 int offset =  fReturnSizePic - size;
10573                 while (size--) {
10574                         pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10575                                 fReturn[fReturnSizePic - offset - 1] : "acc"));
10576                         offset++;
10577                 }
10578                 aopOp(IC_RESULT(ic),ic,FALSE);
10579                 size = AOP_SIZE(IC_RESULT(ic));
10580                 offset = 0;
10581                 while (size--) {
10582                         pic14_emitcode ("pop","acc");
10583                         aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10584                 }
10585                 
10586         } else {
10587                 _G.accInUse++;
10588                 aopOp(IC_RESULT(ic),ic,FALSE);
10589                 _G.accInUse--;
10590                 assignResultValue(IC_RESULT(ic));
10591         }
10592         
10593         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10594 }
10595
10596 /*-----------------------------------------------------------------*/
10597 /* genDummyRead - generate code for dummy read of volatiles        */
10598 /*-----------------------------------------------------------------*/
10599 static void
10600 genDummyRead (iCode * ic)
10601 {
10602         FENTRY;
10603         pic14_emitcode ("; genDummyRead","");
10604         pic14_emitcode ("; not implemented","");
10605         
10606         ic = ic;
10607 }
10608
10609 /*-----------------------------------------------------------------*/
10610 /* genpic14Code - generate code for pic14 based controllers        */
10611 /*-----------------------------------------------------------------*/
10612 /*
10613 * At this point, ralloc.c has gone through the iCode and attempted
10614 * to optimize in a way suitable for a PIC. Now we've got to generate
10615 * PIC instructions that correspond to the iCode.
10616 *
10617 * Once the instructions are generated, we'll pass through both the
10618 * peep hole optimizer and the pCode optimizer.
10619 *-----------------------------------------------------------------*/
10620
10621 void genpic14Code (iCode *lic)
10622 {
10623         iCode *ic;
10624         int cln = 0;
10625         const char *cline;
10626         
10627         FENTRY;
10628         lineHead = lineCurr = NULL;
10629         
10630         pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10631         addpBlock(pb);
10632         
10633         /* if debug information required */
10634         if (options.debug && currFunc) { 
10635                 if (currFunc) {
10636                         debugFile->writeFunction (currFunc, lic);
10637                 }
10638         }
10639         
10640         
10641         for (ic = lic ; ic ; ic = ic->next ) {
10642                 
10643                 //DEBUGpic14_emitcode(";ic","");
10644                 //fprintf (stderr, "in ic loop\n");
10645                 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10646                 //ic->lineno, printCLine(ic->filename, ic->lineno));
10647                 
10648                 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10649                   cln = ic->lineno;
10650                   //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10651                   cline = printCLine (ic->filename, ic->lineno);
10652                   if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10653                   addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10654                   //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10655                 }
10656                 
10657                 if (options.iCodeInAsm) {
10658                   emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10659                 }
10660                 /* if the result is marked as
10661                 spilt and rematerializable or code for
10662                 this has already been generated then
10663                 do nothing */
10664                 if (resultRemat(ic) || ic->generated ) 
10665                         continue ;
10666                 
10667                 /* depending on the operation */
10668                 switch (ic->op) {
10669                 case '!' :
10670                         genNot(ic);
10671                         break;
10672                         
10673                 case '~' :
10674                         genCpl(ic);
10675                         break;
10676                         
10677                 case UNARYMINUS:
10678                         genUminus (ic);
10679                         break;
10680                         
10681                 case IPUSH:
10682                         genIpush (ic);
10683                         break;
10684                         
10685                 case IPOP:
10686                         /* IPOP happens only when trying to restore a 
10687                         spilt live range, if there is an ifx statement
10688                         following this pop then the if statement might
10689                         be using some of the registers being popped which
10690                         would destory the contents of the register so
10691                         we need to check for this condition and handle it */
10692                         if (ic->next            && 
10693                                 ic->next->op == IFX &&
10694                                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10695                                 genIfx (ic->next,ic);
10696                         else
10697                                 genIpop (ic);
10698                         break; 
10699                         
10700                 case CALL:
10701                         genCall (ic);
10702                         break;
10703                         
10704                 case PCALL:
10705                         genPcall (ic);
10706                         break;
10707                         
10708                 case FUNCTION:
10709                         genFunction (ic);
10710                         break;
10711                         
10712                 case ENDFUNCTION:
10713                         genEndFunction (ic);
10714                         break;
10715                         
10716                 case RETURN:
10717                         genRet (ic);
10718                         break;
10719                         
10720                 case LABEL:
10721                         genLabel (ic);
10722                         break;
10723                         
10724                 case GOTO:
10725                         genGoto (ic);
10726                         break;
10727                         
10728                 case '+' :
10729                         genPlus (ic) ;
10730                         break;
10731                         
10732                 case '-' :
10733                         if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10734                                 genMinus (ic);
10735                         break;
10736                         
10737                 case '*' :
10738                         genMult (ic);
10739                         break;
10740                         
10741                 case '/' :
10742                         genDiv (ic) ;
10743                         break;
10744                         
10745                 case '%' :
10746                         genMod (ic);
10747                         break;
10748                         
10749                 case '>' :
10750                         genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));         
10751                         break;
10752                         
10753                 case '<' :
10754                         genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10755                         break;
10756                         
10757                 case LE_OP:
10758                 case GE_OP:
10759                 case NE_OP:
10760                         
10761                         /* note these two are xlated by algebraic equivalence
10762                         during parsing SDCC.y */
10763                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10764                                 "got '>=' or '<=' shouldn't have come here");
10765                         break;  
10766                         
10767                 case EQ_OP:
10768                         genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10769                         break;      
10770                         
10771                 case AND_OP:
10772                         genAndOp (ic);
10773                         break;
10774                         
10775                 case OR_OP:
10776                         genOrOp (ic);
10777                         break;
10778                         
10779                 case '^' :
10780                         genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10781                         break;
10782                         
10783                 case '|' :
10784                         genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10785                         break;
10786                         
10787                 case BITWISEAND:
10788                         genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10789                         break;
10790                         
10791                 case INLINEASM:
10792                         genInline (ic);
10793                         break;
10794                         
10795                 case RRC:
10796                         genRRC (ic);
10797                         break;
10798                         
10799                 case RLC:
10800                         genRLC (ic);
10801                         break;
10802                         
10803                 case GETHBIT:
10804                         genGetHbit (ic);
10805                         break;
10806                         
10807                 case LEFT_OP:
10808                         genLeftShift (ic);
10809                         break;
10810                         
10811                 case RIGHT_OP:
10812                         genRightShift (ic);
10813                         break;
10814                         
10815                 case GET_VALUE_AT_ADDRESS:
10816                         genPointerGet(ic);
10817                         break;
10818                         
10819                 case '=' :
10820                         if (POINTER_SET(ic))
10821                                 genPointerSet(ic);
10822                         else
10823                                 genAssign(ic);
10824                         break;
10825                         
10826                 case IFX:
10827                         genIfx (ic,NULL);
10828                         break;
10829                         
10830                 case ADDRESS_OF:
10831                         genAddrOf (ic);
10832                         break;
10833                         
10834                 case JUMPTABLE:
10835                         genJumpTab (ic);
10836                         break;
10837                         
10838                 case CAST:
10839                         genCast (ic);
10840                         break;
10841                         
10842                 case RECEIVE:
10843                         genReceive(ic);
10844                         break;
10845                         
10846                 case SEND:
10847                         addSet(&_G.sendSet,ic);
10848                         break;
10849                         
10850                 case DUMMY_READ_VOLATILE:
10851                         genDummyRead (ic);
10852                         break;
10853                         
10854                 default :
10855                         fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10856                         ic = ic;
10857                         break;
10858                 }
10859         }
10860
10861         
10862         /* now we are ready to call the
10863         peep hole optimizer */
10864         if (!options.nopeep) {
10865                 peepHole (&lineHead);
10866         }
10867         /* now do the actual printing */
10868         printLine (lineHead,codeOutFile);
10869         
10870 #ifdef PCODE_DEBUG
10871         DFPRINTF((stderr,"printing pBlock\n\n"));
10872         printpBlock(stdout,pb);
10873 #endif
10874         
10875         return;
10876 }
10877
10878 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10879  * (meaning: representing its own address) or not (referencing its contents).
10880  * This can only be decided based on the operand's type. */
10881 int
10882 aop_isLitLike (asmop *aop)
10883 {
10884   assert (aop);
10885   if (aop->type == AOP_LIT) return 1;
10886 if (aop->type == AOP_IMMD) return 1;
10887   if ((aop->type == AOP_PCODE) &&
10888                 ((aop->aopu.pcop->type == PO_LITERAL)))
10889   {
10890     /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10891      * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10892     return 1;
10893   }
10894   return 0;
10895 }
10896
10897 int
10898 op_isLitLike (operand *op)
10899 {
10900   assert (op);
10901   if (aop_isLitLike (AOP(op))) return 1;
10902   if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10903   if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;
10904   return 0;
10905 }