* support/regression/tests/structflexarray.c: flexible array members
[fw/sdcc] / src / pic / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for pic
3   
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8     cont'd   -  Raphael Neider <rneider AT web.de> (2005)
9   
10   This program is free software; you can redistribute it and/or modify it
11   under the terms of the GNU General Public License as published by the
12   Free Software Foundation; either version 2, or (at your option) any
13   later version.
14   
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License for more details.
19   
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23   
24   In other words, you are welcome to use, share and improve this program.
25   You are forbidden to forbid anyone else to use, share and improve
26   what you give them.   Help stamp out software-hoarding!
27   
28   Notes:
29   000123 mlh  Moved aopLiteral to SDCCglue.c to help the split
30       Made everything static
31 -------------------------------------------------------------------------*/
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37 #ifndef __sun__
38 #if defined(_MSC_VER)
39         #include "pstdint.h"
40 #else
41         #include <stdint.h>
42 #endif
43 #endif
44 #include "SDCCglobl.h"
45 #include "newalloc.h" 
46
47 #include "common.h"
48 #include "SDCCpeeph.h"
49 #include "ralloc.h"
50 #include "pcode.h"
51 #include "gen.h"
52
53 /* When changing these, you must also update the assembler template
54  * in device/lib/libsdcc/macros.inc */
55 #define GPTRTAG_DATA    0x00
56 #define GPTRTAG_CODE    0x80
57
58 /* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
59 #define PIC_IS_DATA_PTR(x)      (IS_DATA_PTR(x) || IS_FARPTR(x))
60 #define PIC_IS_FARPTR(x)        (PIC_IS_DATA_PTR(x))
61
62 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
63 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
64 void genMult8X8_8 (operand *, operand *,operand *);
65 extern void printpBlock(FILE *of, pBlock *pb);
66
67 static int labelOffset=0;
68 extern int debug_verbose;
69 extern int pic14_hasInterrupt;
70 //static int optimized_for_speed = 0;
71
72 /* max_key keeps track of the largest label number used in 
73 a function. This is then used to adjust the label offset
74 for the next function.
75 */
76 static int max_key=0;
77 static int GpsuedoStkPtr=0;
78
79 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
80 extern char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
81 unsigned int pic14aopLiteral (value *val, int offset);
82 const char *AopType(short type);
83
84 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
85
86 /* this is the down and dirty file with all kinds of 
87 kludgy & hacky stuff. This is what it is all about
88 CODE GENERATION for a specific MCU . some of the
89 routines may be reusable, will have to see */
90
91 static char *zero = "#0x00";
92 static char *one  = "#0x01";
93 static char *spname = "sp";
94
95 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
96 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
97 static char **fReturn = fReturnpic14;
98
99 //static char *accUse[] = {"a","b"};
100
101 //static short rbank = -1;
102
103 static struct {
104         short r0Pushed;
105         short r1Pushed;
106         short accInUse;
107         short inLine;
108         short debugLine;
109         short nRegsSaved;
110         set *sendSet;
111 } _G;
112
113 /* Resolved ifx structure. This structure stores information
114 about an iCode ifx that makes it easier to generate code.
115 */
116 typedef struct resolvedIfx {
117         symbol *lbl;     /* pointer to a label */
118         int condition;   /* true or false ifx */
119         int generated;   /* set true when the code associated with the ifx
120                           * is generated */
121 } resolvedIfx;
122
123 extern int pic14_ptrRegReq ;
124 extern int pic14_nRegs;
125 extern FILE *codeOutFile;
126 static void saverbank (int, iCode *,bool);
127
128 static lineNode *lineHead = NULL;
129 static lineNode *lineCurr = NULL;
130
131 #if 0
132 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
133 0xE0, 0xC0, 0x80, 0x00};
134 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
135 0x07, 0x03, 0x01, 0x00};
136 #endif
137
138 static  pBlock *pb;
139
140 /*-----------------------------------------------------------------*/
141 /*      my_powof2(n) - If `n' is an integaer power of 2, then the          */
142 /*                                 exponent of 2 is returned, otherwise -1 is      */
143 /*                                 returned.                                                                       */
144 /* note that this is similar to the function `powof2' in SDCCsymt  */
145 /* if(n == 2^y)                                                                                                    */
146 /*       return y;                                                                                                         */
147 /* return -1;                                                                                                      */
148 /*-----------------------------------------------------------------*/
149 static int my_powof2 (unsigned long num)
150 {
151         if(num) {
152                 if( (num & (num-1)) == 0) {
153                         int nshifts = -1;
154                         while(num) {
155                                 num>>=1;
156                                 nshifts++;
157                         }
158                         return nshifts;
159                 }
160         }
161         
162         return -1;
163 }
164
165 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
166 {
167         
168         DEBUGpic14_emitcode ("; ","line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
169                 line_no,
170                 ((result) ? AopType(AOP_TYPE(result)) : "-"),
171                 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
172                 ((result) ? AOP_SIZE(result) : 0),
173                 ((left)   ? AopType(AOP_TYPE(left)) : "-"),
174                 ((left)   ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
175                 ((left)   ? AOP_SIZE(left) : 0),
176                 ((right)  ? AopType(AOP_TYPE(right)) : "-"),
177                 ((right)  ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
178                 ((right)  ? AOP_SIZE(right) : 0));
179         
180 }
181
182 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
183 {
184         
185         DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
186                 line_no,
187                 ((result) ? AopType(AOP_TYPE(result)) : "-"),
188                 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
189                 ((left)   ? AopType(AOP_TYPE(left)) : "-"),
190                 ((left)   ? (SPEC_USIGN(operandType(left))       ? 'u' : 's') : '-'),
191                 ((right)  ? AopType(AOP_TYPE(right)) : "-"),
192                 ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
193         
194 }
195
196 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
197 {
198         va_list ap;
199         char lb[INITIAL_INLINEASM];  
200         unsigned char *lbp = (unsigned char *)lb;
201         
202         if(!debug_verbose && !options.debug)
203                 return;
204         
205         va_start(ap,fmt);   
206         
207         if (inst && *inst) {
208                 if (fmt && *fmt)
209                         sprintf(lb,"%s\t",inst);
210                 else
211                         sprintf(lb,"%s",inst);
212                 vsprintf(lb+(strlen(lb)),fmt,ap);
213         }  else
214                 vsprintf(lb,fmt,ap);
215         
216         while (isspace(*lbp)) lbp++;
217         
218         if (lbp && *lbp) 
219                 lineCurr = (lineCurr ?
220                 connectLine(lineCurr,newLineNode(lb)) :
221         (lineHead = newLineNode(lb)));
222         lineCurr->isInline = _G.inLine;
223         lineCurr->isDebug  = _G.debugLine;
224         
225         addpCode2pBlock(pb,newpCodeCharP(lb));
226         
227         va_end(ap);
228 }
229
230 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
231 {
232 #if defined (HAVE_VSNPRINTF)
233   vsnprintf (buf, size, fmt, ap);
234 #elif defined (HAVE_VSPRINTF)
235   vsprintf (buf, size, fmt, ap);
236   if (strlen (buf) >= size)
237   {
238     fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
239   }
240 #elif defined (HAVE_SNPRINTF)
241   snprintf (buf, size, "vs(n)printf required");
242 #elif defined (HAVE_SRINTF)
243   sprintf (buf, "vs(n)printf required");
244   if (strlen (buf) >= size)
245   {
246     fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
247   }
248 #else
249   assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
250 #endif
251 }
252
253 void emitpComment (const char *fmt, ...)
254 {
255   va_list va;
256   char buffer[4096];
257   
258   va_start (va, fmt);
259   if (pb) {
260     Safe_vsnprintf (buffer, 4096, fmt, va);
261     //fprintf (stderr, "%s\n" ,buffer);
262     addpCode2pBlock (pb, newpCodeCharP (buffer));
263 #if 0
264   } else {
265     Safe_vsnprintf (buffer, 4096, fmt, va);
266     fprintf (stderr, "No current pBlock -- discarding comment [%s]\n", buffer);
267 #endif
268   }
269   va_end (va);
270 }
271
272 void emitpLabel(int key)
273 {
274         addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
275 }
276
277 /* gen.h defines a macro emitpcode that should be used to call emitpcode
278  * as this allows for easy debugging (ever asked the question: where was
279  * this instruction geenrated? Here is the answer... */
280 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
281 {
282         if(pcop)
283                 addpCode2pBlock(pb,newpCode(poc,pcop));
284         else
285                 DEBUGpic14_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
286 }
287
288 void emitpcodeNULLop(PIC_OPCODE poc)
289 {
290         
291         addpCode2pBlock(pb,newpCode(poc,NULL));
292         
293 }
294
295
296 /*-----------------------------------------------------------------*/
297 /* pic14_emitcode - writes the code into a file : for now it is simple    */
298 /*-----------------------------------------------------------------*/
299 void pic14_emitcode (char *inst,char *fmt, ...)
300 {
301         va_list ap;
302         char lb[INITIAL_INLINEASM];  
303         unsigned char *lbp = (unsigned char *)lb;
304         
305         va_start(ap,fmt);   
306         
307         if (inst && *inst) {
308                 if (fmt && *fmt)
309                         sprintf(lb,"%s\t",inst);
310                 else
311                         sprintf(lb,"%s",inst);
312                 vsprintf(lb+(strlen(lb)),fmt,ap);
313         }  else
314                 vsprintf(lb,fmt,ap);
315         
316         while (isspace(*lbp)) lbp++;
317         
318         if (lbp && *lbp) 
319                 lineCurr = (lineCurr ?
320                 connectLine(lineCurr,newLineNode(lb)) :
321         (lineHead = newLineNode(lb)));
322         lineCurr->isInline = _G.inLine;
323         lineCurr->isDebug  = _G.debugLine;
324         
325         if(debug_verbose)
326                 addpCode2pBlock(pb,newpCodeCharP(lb));
327         
328         va_end(ap);
329 }
330
331 /*-----------------------------------------------------------------*/
332 /* pic14_emitDebuggerSymbol - associate the current code location  */
333 /*       with a debugger symbol                                                                            */
334 /*-----------------------------------------------------------------*/
335 void
336 pic14_emitDebuggerSymbol (char * debugSym)
337 {
338         _G.debugLine = 1;
339         pic14_emitcode ("", ";%s ==.", debugSym);
340         _G.debugLine = 0;
341 }
342
343 #if 0
344 /*-----------------------------------------------------------------*/
345 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
346 /*-----------------------------------------------------------------*/
347 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
348 {
349         bool r0iu = FALSE , r1iu = FALSE;
350         bool r0ou = FALSE , r1ou = FALSE;
351         
352         /* the logic: if r0 & r1 used in the instruction
353         then we are in trouble otherwise */
354         
355         /* first check if r0 & r1 are used by this
356         instruction, in which case we are in trouble */
357         if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
358                 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
359         {
360                 goto endOfWorld;          
361         }
362         
363         r0ou = bitVectBitValue(ic->rMask,R0_IDX);
364         r1ou = bitVectBitValue(ic->rMask,R1_IDX);
365         
366         /* if no usage of r0 then return it */
367         if (!r0iu && !r0ou) {
368                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
369                 (*aopp)->type = AOP_R0;
370                 
371                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
372         }
373         
374         /* if no usage of r1 then return it */
375         if (!r1iu && !r1ou) {
376                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
377                 (*aopp)->type = AOP_R1;
378                 
379                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
380         }    
381         
382         /* now we know they both have usage */
383         /* if r0 not used in this instruction */
384         if (!r0iu) {
385                 /* push it if not already pushed */
386                 if (!_G.r0Pushed) {
387                         //pic14_emitcode ("push","%s",
388                         //                pic14_regWithIdx(R0_IDX)->dname);
389                         _G.r0Pushed++ ;
390                 }
391                 
392                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
393                 (*aopp)->type = AOP_R0;
394                 
395                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
396         }
397         
398         /* if r1 not used then */
399         
400         if (!r1iu) {
401                 /* push it if not already pushed */
402                 if (!_G.r1Pushed) {
403                         //pic14_emitcode ("push","%s",
404                         //                pic14_regWithIdx(R1_IDX)->dname);
405                         _G.r1Pushed++ ;
406                 }
407                 
408                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
409                 (*aopp)->type = AOP_R1;
410                 return pic14_regWithIdx(R1_IDX);
411         }
412         
413 endOfWorld :
414         /* I said end of world but not quite end of world yet */
415         /* if this is a result then we can push it on the stack*/
416         if (result) {
417                 (*aopp)->type = AOP_STK;        
418                 return NULL;
419         }
420         
421         /* other wise this is true end of the world */
422         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
423                 "getFreePtr should never reach here");
424         exit(0);
425 }
426 #endif
427
428 /*-----------------------------------------------------------------*/
429 /* newAsmop - creates a new asmOp                                                                  */
430 /*-----------------------------------------------------------------*/
431 asmop *newAsmop (short type)
432 {
433         asmop *aop;
434         
435         aop = Safe_calloc(1,sizeof(asmop));
436         aop->type = type;
437         return aop;
438 }
439
440 static void genSetDPTR(int n)
441 {
442         if (!n)
443         {
444                 pic14_emitcode(";", "Select standard DPTR");
445                 pic14_emitcode("mov", "dps, #0x00");
446         }
447         else
448         {
449                 pic14_emitcode(";", "Select alternate DPTR");
450                 pic14_emitcode("mov", "dps, #0x01");
451         }
452 }
453
454 /*-----------------------------------------------------------------*/
455 /* resolveIfx - converts an iCode ifx into a form more useful for  */
456 /*                              generating code                                                                    */
457 /*-----------------------------------------------------------------*/
458 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
459 {
460         if(!resIfx) 
461                 return;
462         
463         //  DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
464         
465         resIfx->condition = 1;  /* assume that the ifx is true */
466         resIfx->generated = 0;  /* indicate that the ifx has not been used */
467         
468         if(!ifx) {
469                 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL);      / * oops, there is no ifx. so create a label */
470                                                                                         /*
471                                                                                         DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
472                                                                                         __FUNCTION__,__LINE__,resIfx->lbl->key);
473                 */
474         } else {
475                 if(IC_TRUE(ifx)) {
476                         resIfx->lbl = IC_TRUE(ifx);
477                 } else {
478                         resIfx->lbl = IC_FALSE(ifx);
479                         resIfx->condition = 0;
480                 }
481                 /*
482                 if(IC_TRUE(ifx)) 
483                 DEBUGpic14_emitcode("; ***","ifx true is non-null");
484                 if(IC_FALSE(ifx)) 
485                 DEBUGpic14_emitcode("; ***","ifx false is non-null");
486                 */
487         }
488         
489         //  DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
490         
491 }
492 /*-----------------------------------------------------------------*/
493 /* pointerCode - returns the code for a pointer type                       */
494 /*-----------------------------------------------------------------*/
495 #if 0
496 static int pointerCode (sym_link *etype)
497 {
498         
499         return PTR_TYPE(SPEC_OCLS(etype));
500         
501 }
502 #endif
503
504 /*-----------------------------------------------------------------*/
505 /* aopForSym - for a true symbol                                                                   */
506 /*-----------------------------------------------------------------*/
507 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
508 {
509         asmop *aop;
510         memmap *space= SPEC_OCLS(sym->etype);
511         
512         DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
513         /* if already has one */
514         if (sym->aop)
515                 return sym->aop;
516         
517 #if 0
518         /* assign depending on the storage class */
519         /* if it is on the stack or indirectly addressable */
520         /* space we need to assign either r0 or r1 to it         */    
521         if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
522                 sym->aop = aop = newAsmop(0);
523                 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
524                 aop->size = getSize(sym->type);
525                 
526                 /* now assign the address of the variable to 
527                 the pointer register */
528                 if (aop->type != AOP_STK) {
529                         
530                         if (sym->onStack) {
531                                 if ( _G.accInUse )
532                                         pic14_emitcode("push","acc");
533                                 
534                                 pic14_emitcode("mov","a,_bp");
535                                 pic14_emitcode("add","a,#0x%02x",
536                                         ((sym->stack < 0) ?
537                                         ((char)(sym->stack - _G.nRegsSaved )) :
538                                 ((char)sym->stack)) & 0xff);
539                                 pic14_emitcode("mov","%s,a",
540                                         aop->aopu.aop_ptr->name);
541                                 
542                                 if ( _G.accInUse )
543                                         pic14_emitcode("pop","acc");
544                         } else
545                                 pic14_emitcode("mov","%s,#%s",
546                                 aop->aopu.aop_ptr->name,
547                                 sym->rname);
548                         aop->paged = space->paged;
549                 } else
550                         aop->aopu.aop_stk = sym->stack;
551                 return aop;
552         }
553         
554         if (sym->onStack && options.stack10bit)
555         {
556                 /* It's on the 10 bit stack, which is located in
557                 * far data space.
558                 */
559                 
560                 //DEBUGpic14_emitcode(";","%d",__LINE__);
561                 
562                 if ( _G.accInUse )
563                         pic14_emitcode("push","acc");
564                 
565                 pic14_emitcode("mov","a,_bp");
566                 pic14_emitcode("add","a,#0x%02x",
567                         ((sym->stack < 0) ?
568                         ((char)(sym->stack - _G.nRegsSaved )) :
569                 ((char)sym->stack)) & 0xff);
570                 
571                 genSetDPTR(1);
572                 pic14_emitcode ("mov","dpx1,#0x40");
573                 pic14_emitcode ("mov","dph1,#0x00");
574                 pic14_emitcode ("mov","dpl1, a");
575                 genSetDPTR(0);
576                 
577                 if ( _G.accInUse )
578                         pic14_emitcode("pop","acc");
579                 
580                 sym->aop = aop = newAsmop(AOP_DPTR2);
581                 aop->size = getSize(sym->type); 
582                 return aop;
583         }
584 #endif
585
586         //DEBUGpic14_emitcode(";","%d",__LINE__);
587         /* if in bit space */
588         if (IN_BITSPACE(space)) {
589                 sym->aop = aop = newAsmop (AOP_CRY);
590                 aop->aopu.aop_dir = sym->rname ;
591                 aop->size = getSize(sym->type);
592                 //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
593                 return aop;
594         }
595         /* if it is in direct space */
596         if (IN_DIRSPACE(space)) {
597                 sym->aop = aop = newAsmop (AOP_DIR);
598                 aop->aopu.aop_dir = sym->rname ;
599                 aop->size = getSize(sym->type);
600                 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
601                 return aop;
602         }
603         
604         /* special case for a function */
605         if (IS_FUNC(sym->type)) {   
606                 
607                 sym->aop = aop = newAsmop(AOP_PCODE);
608                 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
609                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
610                 PCOI(aop->aopu.pcop)->_function = 1;
611                 PCOI(aop->aopu.pcop)->index = 0;
612                 aop->size = FPTRSIZE; 
613                 /*
614                 sym->aop = aop = newAsmop(AOP_IMMD);    
615                 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
616                 strcpy(aop->aopu.aop_immd,sym->rname);
617                 aop->size = FPTRSIZE; 
618                 */
619                 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
620                 return aop;
621         }
622         
623         if (IS_ARRAY(sym->type)) {
624                 sym->aop = aop = newAsmop(AOP_PCODE);
625                 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
626                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
627                 PCOI(aop->aopu.pcop)->_function = 0;
628                 PCOI(aop->aopu.pcop)->index = 0;
629                 aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
630                 
631                 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
632                 return aop;
633         }
634         
635         /* only remaining is far space */
636         /* in which case DPTR gets the address */
637         sym->aop = aop = newAsmop(AOP_PCODE);
638         
639         aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
640         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
641         PCOI(aop->aopu.pcop)->index = 0;
642         
643         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
644                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
645         
646         allocDirReg (IC_LEFT(ic));
647         
648         aop->size = FPTRSIZE;
649         /*
650         DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
651         sym->aop = aop = newAsmop(AOP_DPTR);
652         pic14_emitcode ("mov","dptr,#%s", sym->rname);
653         aop->size = getSize(sym->type);
654         
655           DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
656         */
657         
658         /* if it is in code space */
659         if (IN_CODESPACE(space))
660                 aop->code = 1;
661         
662         return aop;       
663 }
664
665 /*-----------------------------------------------------------------*/
666 /* aopForRemat - rematerialzes an object                                                   */
667 /*-----------------------------------------------------------------*/
668 static asmop *aopForRemat (operand *op) // x symbol *sym)
669 {
670         symbol *sym = OP_SYMBOL(op);
671         iCode *ic = NULL;
672         asmop *aop = newAsmop(AOP_PCODE);
673         int val = 0;
674         int offset = 0;
675         
676         ic = sym->rematiCode;
677
678         DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
679         if(IS_OP_POINTER(op)) {
680                 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
681         }
682         for (;;) {
683                 if (ic->op == '+') {
684                         val += (int) operandLitValue(IC_RIGHT(ic));
685                 } else if (ic->op == '-') {
686                         val -= (int) operandLitValue(IC_RIGHT(ic));
687                 } else
688                         break;
689                 
690                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
691         }
692         
693         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
694         aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
695         PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
696         PCOI(aop->aopu.pcop)->index = val;
697         
698         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
699                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
700                 val, IS_PTR_CONST(operandType(op)));
701         
702         //      DEBUGpic14_emitcode(";","aop type  %s",AopType(AOP_TYPE(IC_LEFT(ic))));
703         
704         allocDirReg (IC_LEFT(ic));
705         
706         return aop;              
707 }
708
709 int aopIdx (asmop *aop, int offset)
710 {
711         if(!aop)
712                 return -1;
713         
714         if(aop->type !=  AOP_REG)
715                 return -2;
716         
717         return aop->aopu.aop_reg[offset]->rIdx;
718         
719 }
720 /*-----------------------------------------------------------------*/
721 /* regsInCommon - two operands have some registers in common       */
722 /*-----------------------------------------------------------------*/
723 static bool regsInCommon (operand *op1, operand *op2)
724 {
725         symbol *sym1, *sym2;
726         int i;
727         
728         /* if they have registers in common */
729         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
730                 return FALSE ;
731         
732         sym1 = OP_SYMBOL(op1);
733         sym2 = OP_SYMBOL(op2);
734         
735         if (sym1->nRegs == 0 || sym2->nRegs == 0)
736                 return FALSE ;
737         
738         for (i = 0 ; i < sym1->nRegs ; i++) {
739                 int j;
740                 if (!sym1->regs[i])
741                         continue ;
742                 
743                 for (j = 0 ; j < sym2->nRegs ;j++ ) {
744                         if (!sym2->regs[j])
745                                 continue ;
746                         
747                         if (sym2->regs[j] == sym1->regs[i])
748                                 return TRUE ;
749                 }
750         }
751         
752         return FALSE ;
753 }
754
755 /*-----------------------------------------------------------------*/
756 /* operandsEqu - equivalent                                                                        */
757 /*-----------------------------------------------------------------*/
758 static bool operandsEqu ( operand *op1, operand *op2)
759 {
760         symbol *sym1, *sym2;
761         
762         /* if they not symbols */
763         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
764                 return FALSE;
765         
766         sym1 = OP_SYMBOL(op1);
767         sym2 = OP_SYMBOL(op2);
768         
769         /* if both are itemps & one is spilt
770         and the other is not then false */
771         if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
772                 sym1->isspilt != sym2->isspilt )
773                 return FALSE ;
774         
775         /* if they are the same */
776         if (sym1 == sym2)
777                 return TRUE ;
778         
779         if (sym1->rname[0] && sym2->rname[0]
780                 && strcmp (sym1->rname, sym2->rname) == 0)
781                 return TRUE;
782         
783         
784         /* if left is a tmp & right is not */
785         if (IS_ITEMP(op1)  && 
786                 !IS_ITEMP(op2) &&
787                 sym1->isspilt  &&
788                 (sym1->usl.spillLoc == sym2))
789                 return TRUE;
790         
791         if (IS_ITEMP(op2)  && 
792                 !IS_ITEMP(op1) &&
793                 sym2->isspilt  &&
794                 sym1->level > 0 &&
795                 (sym2->usl.spillLoc == sym1))
796                 return TRUE ;
797         
798         return FALSE ;
799 }
800
801 /*-----------------------------------------------------------------*/
802 /* pic14_sameRegs - two asmops have the same registers             */
803 /*-----------------------------------------------------------------*/
804 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
805 {
806         int i;
807         
808         if (aop1 == aop2)
809                 return TRUE ;
810         
811         if (aop1->type != AOP_REG ||
812                 aop2->type != AOP_REG )
813                 return FALSE ;
814         
815         if (aop1->size != aop2->size )
816                 return FALSE ;
817         
818         for (i = 0 ; i < aop1->size ; i++ )
819                 if (aop1->aopu.aop_reg[i] !=
820                         aop2->aopu.aop_reg[i] )
821                         return FALSE ;
822                 
823                 return TRUE ;
824 }
825
826 /*-----------------------------------------------------------------*/
827 /* aopOp - allocates an asmop for an operand  :                    */
828 /*-----------------------------------------------------------------*/
829 void aopOp (operand *op, iCode *ic, bool result)
830 {
831         asmop *aop;
832         symbol *sym;
833         int i;
834         
835         if (!op)
836                 return ;
837         
838         /* if this a literal */
839         if (IS_OP_LITERAL(op)) {
840                 op->aop = aop = newAsmop(AOP_LIT);
841                 aop->aopu.aop_lit = op->operand.valOperand;
842                 aop->size = getSize(operandType(op));
843                 return;
844         }
845         
846         {
847                 sym_link *type = operandType(op);
848                 if(IS_PTR_CONST(type))
849                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
850         }
851         
852         /* if already has a asmop then continue */
853         if (op->aop)
854                 return ;
855         
856         /* if the underlying symbol has a aop */
857         if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
858                 DEBUGpic14_emitcode(";","%d",__LINE__);
859                 op->aop = OP_SYMBOL(op)->aop;
860                 return;
861         }
862         
863         /* if this is a true symbol */
864         if (IS_TRUE_SYMOP(op)) {          
865                 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
866                 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
867                 return ;
868         }
869         
870         /* this is a temporary : this has
871         only four choices :
872         a) register
873         b) spillocation
874         c) rematerialize 
875         d) conditional   
876         e) can be a return use only */
877         
878         sym = OP_SYMBOL(op);
879         
880         
881         /* if the type is a conditional */
882         if (sym->regType == REG_CND) {
883                 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
884                 aop->size = 0;
885                 return;
886         }
887         
888         /* if it is spilt then two situations
889         a) is rematerialize 
890         b) has a spill location */
891         if (sym->isspilt || sym->nRegs == 0) {
892                 
893                 DEBUGpic14_emitcode(";","%d",__LINE__);
894                 /* rematerialize it NOW */
895                 if (sym->remat) {
896                         
897                         sym->aop = op->aop = aop = aopForRemat (op);
898                         aop->size = getSize(sym->type);
899                         //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
900                         return;
901                 }
902                 
903 #if 0
904                 /* WREG is not usable as an ordinary operand with PIC architecture,
905                  * one might introduce a scratch register that can be used to make
906                  * WREG accesible as an operand... disable WREG for now */
907                 if (sym->accuse) {
908                         int i;
909                         aop = op->aop = sym->aop = newAsmop(AOP_ACC);
910                         aop->size = getSize(sym->type);
911                         for ( i = 0 ; i < 2 ; i++ )
912                                 aop->aopu.aop_str[i] = accUse[i];
913                         DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
914                         return;  
915                 }
916 #endif
917                 
918                 if (sym->ruonly ) {
919                         if(sym->isptr) {        // && sym->uptr 
920                                 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
921                                 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
922                                 
923                                 //PCOI(aop->aopu.pcop)->_const = 0;
924                                 //PCOI(aop->aopu.pcop)->index = 0;
925                                 /*
926                                 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
927                                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
928                                 */
929                                 //allocDirReg (IC_LEFT(ic));
930                                 
931                                 aop->size = getSize(sym->type);
932                                 DEBUGpic14_emitcode(";","%d",__LINE__);
933                                 return;
934                                 
935                         } else {
936                                 
937                                 unsigned i;
938                                 
939                                 aop = op->aop = sym->aop = newAsmop(AOP_STR);
940                                 aop->size = getSize(sym->type);
941                                 for ( i = 0 ; i < fReturnSizePic ; i++ )
942                                         aop->aopu.aop_str[i] = fReturn[i];
943                                 
944                                 DEBUGpic14_emitcode(";","%d",__LINE__);
945                                 return;
946                         }
947                 }
948                 
949                 /* else spill location  */
950                 if (sym->usl.spillLoc)
951                 {
952                         asmop *oldAsmOp = NULL;
953
954                         if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
955                         {
956                                 /* force a new aop if sizes differ */
957                                 oldAsmOp = sym->usl.spillLoc->aop;
958                                 sym->usl.spillLoc->aop = NULL;
959                         }
960                         DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
961                                 __FUNCTION__,__LINE__,
962                                 sym->usl.spillLoc->rname,
963                                 sym->rname, sym->usl.spillLoc->offset);
964                 
965                         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
966                         if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
967                         {
968                                 /* Don't reuse the new aop, go with the last one */
969                                 sym->usl.spillLoc->aop = oldAsmOp;
970                         }
971                         //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
972                         aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
973                                 getSize(sym->type), 
974                                 sym->usl.spillLoc->offset);
975                         aop->size = getSize(sym->type);
976                 
977                         return;
978                 }
979         }
980         
981         {
982                 sym_link *type = operandType(op);
983                 if(IS_PTR_CONST(type)) 
984                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
985         }
986         
987         /* must be in a register */
988         DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
989         sym->aop = op->aop = aop = newAsmop(AOP_REG);
990         aop->size = sym->nRegs;
991         for ( i = 0 ; i < sym->nRegs ;i++)
992                 aop->aopu.aop_reg[i] = sym->regs[i];
993 }
994
995 /*-----------------------------------------------------------------*/
996 /* freeAsmop - free up the asmop given to an operand                       */
997 /*----------------------------------------------------------------*/
998 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
999 {       
1000         asmop *aop ;
1001         
1002         if (!op)
1003                 aop = aaop;
1004         else 
1005                 aop = op->aop;
1006         
1007         if (!aop)
1008                 return ;
1009         
1010         if (aop->freed)
1011                 goto dealloc; 
1012         
1013         aop->freed = 1;
1014         
1015         /* depending on the asmop type only three cases need work AOP_RO
1016         , AOP_R1 && AOP_STK */
1017 #if 0
1018         switch (aop->type) {
1019         case AOP_R0 :
1020                 if (_G.r0Pushed ) {
1021                         if (pop) {
1022                                 pic14_emitcode ("pop","ar0");     
1023                                 _G.r0Pushed--;
1024                         }
1025                 }
1026                 bitVectUnSetBit(ic->rUsed,R0_IDX);
1027                 break;
1028                 
1029         case AOP_R1 :
1030                 if (_G.r1Pushed ) {
1031                         if (pop) {
1032                                 pic14_emitcode ("pop","ar1");
1033                                 _G.r1Pushed--;
1034                         }
1035                 }
1036                 bitVectUnSetBit(ic->rUsed,R1_IDX);                      
1037                 break;
1038                 
1039         case AOP_STK :
1040                 {
1041                         int sz = aop->size;      
1042                         int stk = aop->aopu.aop_stk + aop->size;
1043                         bitVectUnSetBit(ic->rUsed,R0_IDX);
1044                         bitVectUnSetBit(ic->rUsed,R1_IDX);                
1045                         
1046                         getFreePtr(ic,&aop,FALSE);
1047                         
1048                         if (options.stack10bit)
1049                         {
1050                                 /* I'm not sure what to do here yet... */
1051                                 /* #STUB */
1052                                 fprintf(stderr, 
1053                                         "*** Warning: probably generating bad code for "
1054                                         "10 bit stack mode.\n");
1055                         }
1056                         
1057                         if (stk) {
1058                                 pic14_emitcode ("mov","a,_bp");
1059                                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1060                                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1061                         } else {
1062                                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1063                         }
1064                         
1065                         while (sz--) {
1066                                 pic14_emitcode("pop","acc");
1067                                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1068                                 if (!sz) break;
1069                                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1070                         }
1071                         op->aop = aop;
1072                         freeAsmop(op,NULL,ic,TRUE);
1073                         if (_G.r0Pushed) {
1074                                 pic14_emitcode("pop","ar0");
1075                                 _G.r0Pushed--;
1076                         }
1077                         
1078                         if (_G.r1Pushed) {
1079                                 pic14_emitcode("pop","ar1");
1080                                 _G.r1Pushed--;
1081                         }         
1082                 }
1083         }
1084 #endif
1085         
1086 dealloc:
1087         /* all other cases just dealloc */
1088         if (op ) {
1089                 op->aop = NULL;
1090                 if (IS_SYMOP(op)) {
1091                         OP_SYMBOL(op)->aop = NULL;      
1092                         /* if the symbol has a spill */
1093                         if (SPIL_LOC(op))
1094                                 SPIL_LOC(op)->aop = NULL;
1095                 }
1096         }
1097 }
1098
1099 /*-----------------------------------------------------------------*/
1100 /* aopGet - for fetching value of the aop                                                  */
1101 /*-----------------------------------------------------------------*/
1102 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1103 {
1104         char *s = buffer ;
1105         char *rs;
1106         
1107         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1108         /* offset is greater than
1109         size then zero */
1110         if (offset > (aop->size - 1) &&
1111                 aop->type != AOP_LIT)
1112                 return zero;
1113         
1114         /* depending on type */
1115         switch (aop->type) {
1116                 
1117         case AOP_R0:
1118         case AOP_R1:
1119                 DEBUGpic14_emitcode(";","%d",__LINE__);
1120                 /* if we need to increment it */           
1121                 while (offset > aop->coff) {            
1122                         pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);    
1123                         aop->coff++;
1124                 }
1125                 
1126                 while (offset < aop->coff) {
1127                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1128                         aop->coff--;
1129                 }
1130                 
1131                 aop->coff = offset ;
1132                 if (aop->paged) {
1133                         pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1134                         return (dname ? "acc" : "a");
1135                 }               
1136                 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1137                 rs = Safe_calloc(1,strlen(s)+1);
1138                 strcpy(rs,s);   
1139                 return rs;
1140                 
1141         case AOP_DPTR:
1142         case AOP_DPTR2:
1143                 DEBUGpic14_emitcode(";","%d",__LINE__);
1144                 if (aop->type == AOP_DPTR2)
1145                 {
1146                         genSetDPTR(1);
1147                 }
1148                 
1149                 while (offset > aop->coff) {
1150                         pic14_emitcode ("inc","dptr");
1151                         aop->coff++;
1152                 }
1153                 
1154                 while (offset < aop->coff) {            
1155                         pic14_emitcode("lcall","__decdptr");
1156                         aop->coff--;
1157                 }
1158                 
1159                 aop->coff = offset;
1160                 if (aop->code) {
1161                         pic14_emitcode("clr","a");
1162                         pic14_emitcode("movc","a,@a+dptr");
1163                 }
1164                 else {
1165                         pic14_emitcode("movx","a,@dptr");
1166                 }
1167                 
1168                 if (aop->type == AOP_DPTR2)
1169                 {
1170                         genSetDPTR(0);
1171                 }
1172                 
1173                 return (dname ? "acc" : "a");
1174                 
1175                 
1176         case AOP_IMMD:
1177                 if (bit16) 
1178                         sprintf (s,"%s",aop->aopu.aop_immd);
1179                 else
1180                         if (offset) 
1181                                 sprintf(s,"(%s >> %d)",
1182                                 aop->aopu.aop_immd,
1183                                 offset*8);
1184                         else
1185                                 sprintf(s,"%s",
1186                                 aop->aopu.aop_immd);
1187                         DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1188                         rs = Safe_calloc(1,strlen(s)+1);
1189                         strcpy(rs,s);   
1190                         return rs;
1191                         
1192         case AOP_DIR:
1193                 if (offset) {
1194                         sprintf(s,"(%s + %d)",
1195                                 aop->aopu.aop_dir,
1196                                 offset);
1197                         DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1198                 } else
1199                         sprintf(s,"%s",aop->aopu.aop_dir);
1200                 rs = Safe_calloc(1,strlen(s)+1);
1201                 strcpy(rs,s);   
1202                 return rs;
1203                 
1204         case AOP_REG:
1205                 //if (dname) 
1206                 //        return aop->aopu.aop_reg[offset]->dname;
1207                 //else
1208                 return aop->aopu.aop_reg[offset]->name;
1209                 
1210         case AOP_CRY:
1211                 //pic14_emitcode(";","%d",__LINE__);
1212                 return aop->aopu.aop_dir;
1213                 
1214         case AOP_ACC:
1215                 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1216                 return "AOP_accumulator_bug";
1217                 
1218         case AOP_LIT:
1219                 sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1220                 rs = Safe_calloc(1,strlen(s)+1);
1221                 strcpy(rs,s);   
1222                 return rs;
1223                 
1224         case AOP_STR:
1225                 aop->coff = offset ;
1226                 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1227                         dname)
1228                         return "acc";
1229                 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1230                 
1231                 return aop->aopu.aop_str[offset];
1232                 
1233         case AOP_PCODE:
1234                 {
1235                         pCodeOp *pcop = aop->aopu.pcop;
1236                         DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1237                         if(pcop->name) {
1238                                 if (offset) {
1239                                         DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1240                                         sprintf(s,"(%s+%d)", pcop->name,offset);
1241                                 } else {
1242                                         DEBUGpic14_emitcode(";","%s",pcop->name);
1243                                         sprintf(s,"%s", pcop->name);
1244                                 }
1245                         } else
1246                                 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1247                         
1248                 }
1249                 rs = Safe_calloc(1,strlen(s)+1);
1250                 strcpy(rs,s);   
1251                 return rs;
1252                 
1253   }
1254   
1255   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1256           "aopget got unsupported aop->type");
1257   exit(0);
1258 }
1259
1260
1261 /*-----------------------------------------------------------------*/
1262 /* popGetTempReg - create a new temporary pCodeOp                                  */
1263 /*-----------------------------------------------------------------*/
1264 pCodeOp *popGetTempReg(void)
1265 {
1266         
1267         pCodeOp *pcop;
1268         
1269         pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1270         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1271                 PCOR(pcop)->r->wasUsed=1;
1272                 PCOR(pcop)->r->isFree=0;
1273         }
1274         
1275         return pcop;
1276 }
1277
1278 /*-----------------------------------------------------------------*/
1279 /* popReleaseTempReg - create a new temporary pCodeOp                              */
1280 /*-----------------------------------------------------------------*/
1281 void popReleaseTempReg(pCodeOp *pcop)
1282 {
1283         
1284         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1285                 PCOR(pcop)->r->isFree = 1;
1286         
1287 }
1288 /*-----------------------------------------------------------------*/
1289 /* popGetLabel - create a new pCodeOp of type PO_LABEL                     */
1290 /*-----------------------------------------------------------------*/
1291 pCodeOp *popGetLabel(unsigned int key)
1292 {
1293         
1294         DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1295         
1296         if(key>(unsigned int)max_key)
1297                 max_key = key;
1298         
1299         return newpCodeOpLabel(NULL,key+100+labelOffset);
1300 }
1301
1302 /*-------------------------------------------------------------------*/
1303 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1304 /*-------------------------------------------------------------------*/
1305 pCodeOp *popGetHighLabel(unsigned int key)
1306 {
1307         pCodeOp *pcop;
1308         pcop = popGetLabel(key);
1309         PCOLAB(pcop)->offset = 1;
1310         return pcop;
1311 }
1312
1313 /*-----------------------------------------------------------------*/
1314 /* popGetLit - asm operator to pcode operator conversion                           */
1315 /*-----------------------------------------------------------------*/
1316 pCodeOp *popGetLit(unsigned int lit)
1317 {
1318         
1319         return newpCodeOpLit((unsigned char)lit);
1320 }
1321
1322 /*-----------------------------------------------------------------*/
1323 /* popGetImmd - asm operator to pcode immediate conversion                 */
1324 /*-----------------------------------------------------------------*/
1325 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1326 {
1327         
1328         return newpCodeOpImmd(name, offset,index, 0, is_func);
1329 }
1330
1331 extern set *externs;
1332
1333 /*-----------------------------------------------------------------*/
1334 /* popGetWithString - asm operator to pcode operator conversion                    */
1335 /*-----------------------------------------------------------------*/
1336 pCodeOp *popGetWithString(char *str, int isExtern)
1337 {
1338         pCodeOp *pcop;
1339         
1340         
1341         if(!str) {
1342                 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1343                 exit (1);
1344         }
1345         
1346         pcop = newpCodeOp(str,PO_STR);
1347         PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1348
1349         return pcop;
1350 }
1351
1352 pCodeOp *popGetExternal (char *str)
1353 {
1354         pCodeOp *pcop = popGetWithString (str, 1);
1355         
1356         if (str) {
1357           symbol *sym;
1358           bool found = 0;
1359
1360           for (sym = setFirstItem (externs); !found && sym; sym = setNextItem (externs))
1361           {
1362             if (!strcmp (str, sym->rname))
1363               found = 1;
1364           }
1365           
1366           if (!found)
1367           {
1368             sym = newSymbol(str, 0);
1369             strncpy(sym->rname, str, SDCC_NAME_MAX);
1370             addSet (&externs, sym);
1371           } // if
1372         }
1373         return pcop;
1374 }
1375
1376 /*-----------------------------------------------------------------*/
1377 /* popRegFromString -                                                                                      */
1378 /*-----------------------------------------------------------------*/
1379 pCodeOp *popRegFromString(char *str, int size, int offset)
1380 {
1381         
1382         pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1383         pcop->type = PO_DIR;
1384         
1385         DEBUGpic14_emitcode(";","%d",__LINE__);
1386         
1387         if(!str)
1388                 str = "BAD_STRING";
1389         
1390         pcop->name = Safe_calloc(1,strlen(str)+1);
1391         strcpy(pcop->name,str);
1392         
1393         //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1394         
1395         PCOR(pcop)->r = dirregWithName(pcop->name);
1396         if(PCOR(pcop)->r == NULL) {
1397                 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1398                 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1399                 DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1400         } else {
1401                 DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1402         }
1403         PCOR(pcop)->instance = offset;
1404         
1405         return pcop;
1406 }
1407
1408 /*-----------------------------------------------------------------*/
1409 /*-----------------------------------------------------------------*/
1410 pCodeOp *popRegFromIdx(int rIdx)
1411 {
1412         pCodeOp *pcop;
1413         
1414         DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1415                 __FUNCTION__,__LINE__,rIdx);
1416         
1417         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1418         
1419         PCOR(pcop)->rIdx = rIdx;
1420         PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1421         PCOR(pcop)->r->isFree = 0;
1422         PCOR(pcop)->r->wasUsed = 1;
1423         
1424         pcop->type = PCOR(pcop)->r->pc_type;
1425         
1426         
1427         return pcop;
1428 }
1429
1430 /*-----------------------------------------------------------------*/
1431 /* popGet - asm operator to pcode operator conversion                      */
1432 /*-----------------------------------------------------------------*/
1433 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1434 {
1435         //char *s = buffer ;
1436         //char *rs;
1437         
1438         pCodeOp *pcop;
1439         
1440         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1441         /* offset is greater than
1442         size then zero */
1443
1444         assert (aop);
1445
1446         /* XXX: still needed for BIT operands (AOP_CRY) */
1447         if (offset > (aop->size - 1) &&
1448                 aop->type != AOP_LIT)
1449                 return NULL;  //zero;
1450         
1451         /* depending on type */
1452         switch (aop->type) {
1453                 
1454         case AOP_R0:
1455         case AOP_R1:
1456         case AOP_DPTR:
1457         case AOP_DPTR2:
1458         case AOP_ACC:
1459                 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1460                 return NULL;
1461                 
1462         case AOP_IMMD:
1463                 DEBUGpic14_emitcode(";","%d",__LINE__);
1464                 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1465                 
1466         case AOP_DIR:
1467                 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1468 #if 0
1469                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1470                 pcop->type = PO_DIR;
1471                 
1472                 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1473                 strcpy(pcop->name,aop->aopu.aop_dir);   
1474                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1475                 if(PCOR(pcop)->r == NULL) {
1476                         //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1477                         PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1478                         DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1479                 } else {
1480                         DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1481                 }
1482                 PCOR(pcop)->instance = offset;
1483                 
1484                 return pcop;
1485 #endif
1486                 
1487         case AOP_REG:
1488                 {
1489                         int rIdx;
1490                         assert (offset < aop->size);
1491                         rIdx = aop->aopu.aop_reg[offset]->rIdx;
1492                         
1493                         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1494                         PCOR(pcop)->rIdx = rIdx;
1495                         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1496                         PCOR(pcop)->r->wasUsed=1;
1497                         PCOR(pcop)->r->isFree=0;
1498                         
1499                         PCOR(pcop)->instance = offset;
1500                         pcop->type = PCOR(pcop)->r->pc_type;
1501                         //rs = aop->aopu.aop_reg[offset]->name;
1502                         DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1503                         return pcop;
1504                 }
1505                 
1506         case AOP_CRY:
1507                 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1508                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1509                 //if(PCOR(pcop)->r == NULL)
1510                 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1511                 return pcop;
1512                 
1513         case AOP_LIT:
1514                 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1515                 
1516         case AOP_STR:
1517                 DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1518                 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1519                 /*
1520                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1521                 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1522                 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1523                 pcop->type = PCOR(pcop)->r->pc_type;
1524                 pcop->name = PCOR(pcop)->r->name;
1525                 
1526                   return pcop;
1527                 */
1528                 
1529         case AOP_PCODE:
1530                 pcop = NULL;
1531                 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1532                         __LINE__, 
1533                         ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1534                 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1535                 switch (aop->aopu.pcop->type)
1536                 {
1537                 case PO_IMMEDIATE:
1538                   pcop = pCodeOpCopy (aop->aopu.pcop);
1539                   /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1540                    * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1541                   PCOI(pcop)->index += offset;
1542                   //PCOI(pcop)->offset = 0;
1543                   break;
1544                 case PO_DIR:
1545                   pcop = pCodeOpCopy (aop->aopu.pcop);
1546                   PCOR(pcop)->instance = offset;
1547                   break;
1548                 default:
1549                   assert ( !"unhandled pCode type" );
1550                   break;
1551                 } // switch
1552                 return pcop;
1553         }
1554         
1555         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1556                 "popGet got unsupported aop->type");
1557         exit(0);
1558 }
1559
1560 /*-----------------------------------------------------------------*/
1561 /* popGetAddr - access the low/high word of a symbol (immediate)   */
1562 /*              (for non-PO_IMMEDIATEs this is the same as popGet) */
1563 /*-----------------------------------------------------------------*/
1564 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1565 {
1566   if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1567   {
1568     pCodeOp *pcop = aop->aopu.pcop;
1569     assert (offset <= GPTRSIZE);
1570
1571     /* special case: index >= 2 should return GPOINTER-style values */
1572     if (offset == 2)
1573     {
1574       pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1575       return pcop;
1576     }
1577     
1578     pcop = pCodeOpCopy (pcop);
1579     /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1580      * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1581     PCOI(pcop)->offset += offset;
1582     PCOI(pcop)->index += index;
1583     //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);
1584     return pcop;
1585   } else {
1586     return popGet (aop, offset + index);
1587   }
1588 }
1589
1590 /*-----------------------------------------------------------------*/
1591 /* aopPut - puts a string for a aop                                                        */
1592 /*-----------------------------------------------------------------*/
1593 void aopPut (asmop *aop, char *s, int offset)
1594 {
1595         char *d = buffer ;
1596         symbol *lbl ;
1597         
1598         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1599         
1600         if (aop->size && offset > ( aop->size - 1)) {
1601                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1602                         "aopPut got offset > aop->size");
1603                 exit(0);
1604         }
1605         
1606         /* will assign value to value */
1607         /* depending on where it is ofcourse */
1608         switch (aop->type) {
1609         case AOP_DIR:
1610                 if (offset) {
1611                         sprintf(d,"(%s + %d)",
1612                                 aop->aopu.aop_dir,offset);
1613                         fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1614                         
1615                 } else
1616                         sprintf(d,"%s",aop->aopu.aop_dir);
1617                 
1618                 if (strcmp(d,s)) {
1619                         DEBUGpic14_emitcode(";","%d",__LINE__);
1620                         if(strcmp(s,"W"))
1621                                 pic14_emitcode("movf","%s,w",s);
1622                         pic14_emitcode("movwf","%s",d);
1623                         
1624                         if(strcmp(s,"W")) {
1625                                 pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1626                                 if(offset >= aop->size) {
1627                                         emitpcode(POC_CLRF,popGet(aop,offset));
1628                                         break;
1629                                 } else {
1630                                         emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1631                                 }
1632                         }
1633                         emitpcode(POC_MOVWF,popGet(aop,offset));
1634                 
1635                 }
1636                 break;
1637                 
1638         case AOP_REG:
1639                 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1640                         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1641                         /*
1642                         if (*s == '@'             ||
1643                         strcmp(s,"r0") == 0 ||
1644                         strcmp(s,"r1") == 0 ||
1645                         strcmp(s,"r2") == 0 ||
1646                         strcmp(s,"r3") == 0 ||
1647                         strcmp(s,"r4") == 0 ||
1648                         strcmp(s,"r5") == 0 ||
1649                         strcmp(s,"r6") == 0 || 
1650                         strcmp(s,"r7") == 0 )
1651                         pic14_emitcode("mov","%s,%s  ; %d",
1652                         aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1653                         else
1654                         */
1655                         
1656                         if(strcmp(s,"W")==0 )
1657                                 pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1658                         
1659                         pic14_emitcode("movwf","%s",
1660                                 aop->aopu.aop_reg[offset]->name);
1661                         
1662                         if(strcmp(s,zero)==0) {
1663                                 emitpcode(POC_CLRF,popGet(aop,offset));
1664                                 
1665                         } else if(strcmp(s,"W")==0) {
1666                                 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1667                                 pcop->type = PO_GPR_REGISTER;
1668                                 
1669                                 PCOR(pcop)->rIdx = -1;
1670                                 PCOR(pcop)->r = NULL;
1671                                 
1672                                 DEBUGpic14_emitcode(";","%d",__LINE__);
1673                                 pcop->name = Safe_strdup(s);
1674                                 emitpcode(POC_MOVFW,pcop);
1675                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1676                         } else if(strcmp(s,one)==0) {
1677                                 emitpcode(POC_CLRF,popGet(aop,offset));
1678                                 emitpcode(POC_INCF,popGet(aop,offset));
1679                         } else {
1680                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1681                         }
1682                 }
1683                 break;
1684                 
1685         case AOP_DPTR:
1686         case AOP_DPTR2:
1687                 
1688                 if (aop->type == AOP_DPTR2)
1689                 {
1690                         genSetDPTR(1);
1691                 }
1692                 
1693                 if (aop->code) {
1694                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1695                                 "aopPut writting to code space");
1696                         exit(0);
1697                 }
1698                 
1699                 while (offset > aop->coff) {
1700                         aop->coff++;
1701                         pic14_emitcode ("inc","dptr");
1702                 }
1703                 
1704                 while (offset < aop->coff) {
1705                         aop->coff-- ;
1706                         pic14_emitcode("lcall","__decdptr");
1707                 }
1708                 
1709                 aop->coff = offset;
1710                 
1711                 /* if not in accumulater */
1712                 MOVA(s);
1713                 
1714                 pic14_emitcode ("movx","@dptr,a");
1715                 
1716                 if (aop->type == AOP_DPTR2)
1717                 {
1718                         genSetDPTR(0);
1719                 }
1720                 break;
1721                 
1722         case AOP_R0:
1723         case AOP_R1:
1724                 while (offset > aop->coff) {
1725                         aop->coff++;
1726                         pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1727                 }
1728                 while (offset < aop->coff) {
1729                         aop->coff-- ;
1730                         pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1731                 }
1732                 aop->coff = offset;
1733                 
1734                 if (aop->paged) {
1735                         MOVA(s);                         
1736                         pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1737                         
1738                 } else
1739                         if (*s == '@') {
1740                                 MOVA(s);
1741                                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1742                         } else
1743                                 if (strcmp(s,"r0") == 0 ||
1744                                         strcmp(s,"r1") == 0 ||
1745                                         strcmp(s,"r2") == 0 ||
1746                                         strcmp(s,"r3") == 0 ||
1747                                         strcmp(s,"r4") == 0 ||
1748                                         strcmp(s,"r5") == 0 ||
1749                                         strcmp(s,"r6") == 0 || 
1750                                         strcmp(s,"r7") == 0 ) {
1751                                         char buffer[10];
1752                                         sprintf(buffer,"a%s",s);
1753                                         pic14_emitcode("mov","@%s,%s",
1754                                                 aop->aopu.aop_ptr->name,buffer);
1755                                 } else
1756                                         pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1757                                 
1758                                 break;
1759                                 
1760         case AOP_STK:
1761                 if (strcmp(s,"a") == 0)
1762                         pic14_emitcode("push","acc");
1763                 else
1764                         pic14_emitcode("push","%s",s);
1765                 
1766                 break;
1767                 
1768         case AOP_CRY:
1769                 /* if bit variable */
1770                 if (!aop->aopu.aop_dir) {
1771                         pic14_emitcode("clr","a");
1772                         pic14_emitcode("rlc","a");
1773                 } else {
1774                         if (s == zero) 
1775                                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1776                         else
1777                                 if (s == one)
1778                                         pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1779                                 else
1780                                         if (!strcmp(s,"c"))
1781                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1782                                         else {
1783                                                 lbl = newiTempLabel(NULL);
1784                                                 
1785                                                 if (strcmp(s,"a")) {
1786                                                         MOVA(s);
1787                                                 }
1788                                                 pic14_emitcode("clr","c");
1789                                                 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1790                                                 pic14_emitcode("cpl","c");
1791                                                 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1792                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1793                                         }
1794                 }
1795                 break;
1796                 
1797         case AOP_STR:
1798                 aop->coff = offset;
1799                 if (strcmp(aop->aopu.aop_str[offset],s))
1800                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1801                 break;
1802                 
1803         case AOP_ACC:
1804                 aop->coff = offset;
1805                 if (!offset && (strcmp(s,"acc") == 0))
1806                         break;
1807                 
1808                 if (strcmp(aop->aopu.aop_str[offset],s))
1809                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1810                 break;
1811                 
1812         default :
1813                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1814                         "aopPut got unsupported aop->type");
1815                 exit(0);
1816         }
1817         
1818 }
1819
1820 /*-----------------------------------------------------------------*/
1821 /* mov2w_op - generate either a MOVLW or MOVFW based operand type  */
1822 /*-----------------------------------------------------------------*/
1823 static void mov2w_op (operand *op, int offset)
1824 {
1825         assert (op);
1826         FENTRY;
1827
1828         /* for PO_IMMEDIATEs: use address or value? */
1829         if (op_isLitLike (op))
1830         {
1831                 /* access address of op */
1832                 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1833                 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1834                 {
1835                         if (offset == GPTRSIZE-1)
1836                                 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1837                         else
1838                                 emitpcode (POC_MOVLW, popGetLit (0));
1839                 }
1840                 else
1841                         emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1842         } else {
1843                 /* access value stored in op */
1844                 mov2w (AOP(op), offset);
1845         }
1846 }
1847
1848
1849 /*-----------------------------------------------------------------*/
1850 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1851 /*-----------------------------------------------------------------*/
1852 void mov2w (asmop *aop, int offset)
1853 {
1854         
1855         if(!aop)
1856                 return;
1857         
1858         DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1859         
1860         if ( aop_isLitLike (aop) )
1861                 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1862         else
1863                 emitpcode(POC_MOVFW,popGet(aop,offset));
1864         
1865 }
1866
1867 static void movwf (asmop *op, int offset)
1868 {
1869         emitpcode (POC_MOVWF, popGet(op, offset));
1870 }
1871
1872 static pCodeOp *get_argument_pcop (int idx)
1873 {
1874         assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1875         return popRegFromIdx (Gstack_base_addr - (idx - 1));
1876 }
1877
1878 static pCodeOp *get_return_val_pcop (int offset)
1879 {
1880         assert (offset > 0 && "the most significant byte is returned via WREG");
1881         return popRegFromIdx (Gstack_base_addr - (offset - 1));
1882 }
1883
1884 static void pass_argument (operand *op, int offset, int idx)
1885 {
1886         if (op)
1887                 mov2w_op (op, offset);
1888         if (idx != 0)
1889                 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1890 }
1891
1892 static void get_returnvalue (operand *op, int offset, int idx)
1893 {
1894         if (idx != 0)
1895                 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1896         movwf(AOP(op), offset);
1897 }
1898
1899 static void call_libraryfunc (char *name)
1900 {
1901   /* library code might reside in different page... */
1902   emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1903   /* call the library function */
1904   emitpcode (POC_CALL, popGetExternal (name));
1905   /* might return from different page... */
1906   emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1907 }
1908 #if 0
1909 /*-----------------------------------------------------------------*/
1910 /* reAdjustPreg - points a register back to where it should        */
1911 /*-----------------------------------------------------------------*/
1912 static void reAdjustPreg (asmop *aop)
1913 {
1914         int size ;
1915         
1916         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1917         aop->coff = 0;
1918         if ((size = aop->size) <= 1)
1919                 return ;
1920         size-- ;
1921         switch (aop->type) {
1922         case AOP_R0 :
1923         case AOP_R1 :
1924                 while (size--)
1925                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1926                 break;                  
1927         case AOP_DPTR :
1928         case AOP_DPTR2:
1929                 if (aop->type == AOP_DPTR2)
1930                 {
1931                         genSetDPTR(1);
1932                 } 
1933                 while (size--)
1934                 {
1935                         pic14_emitcode("lcall","__decdptr");
1936                 }
1937                 
1938                 if (aop->type == AOP_DPTR2)
1939                 {
1940                         genSetDPTR(0);
1941                 }
1942                 break;
1943                 
1944         }
1945         
1946 }
1947 #endif
1948
1949
1950 #if 0
1951 /*-----------------------------------------------------------------*/
1952 /* opIsGptr: returns non-zero if the passed operand is             */
1953 /* a generic pointer type.                                         */
1954 /*-----------------------------------------------------------------*/ 
1955 static int opIsGptr(operand *op)
1956 {
1957         sym_link *type = operandType(op);
1958         
1959         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1960         if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1961         {
1962                 return 1;
1963         }
1964         return 0;          
1965 }
1966 #endif
1967
1968 /*-----------------------------------------------------------------*/
1969 /* pic14_getDataSize - get the operand data size                   */
1970 /*-----------------------------------------------------------------*/
1971 int pic14_getDataSize(operand *op)
1972 {
1973         int size;
1974         
1975         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1976         
1977 #if 0
1978         size = getSize(OP_SYM_ETYPE(op));
1979         return size;
1980         //return AOP_SIZE(op);
1981         
1982         // tsd- in the pic port, the genptr size is 1, so this code here
1983         // fails. ( in the 8051 port, the size was 4).
1984 #else
1985         size = AOP_SIZE(op);
1986         if (IS_GENPTR(OP_SYM_TYPE(op)))
1987         {
1988                 sym_link *type = operandType(op);
1989                 if (IS_GENPTR(type))
1990                 {
1991                         /* generic pointer; arithmetic operations
1992                         * should ignore the high byte (pointer type).
1993                         */
1994                         size--;
1995                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1996                 }
1997         }
1998         return size;
1999 #endif
2000 }
2001
2002 /*-----------------------------------------------------------------*/
2003 /* pic14_outAcc - output Acc                                       */
2004 /*-----------------------------------------------------------------*/
2005 void pic14_outAcc(operand *result)
2006 {
2007         int size,offset;
2008         DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2009         DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
2010         
2011         
2012         size = pic14_getDataSize(result);
2013         if(size){
2014                 emitpcode(POC_MOVWF,popGet(AOP(result),0));
2015                 size--;
2016                 offset = 1;
2017                 /* unsigned or positive */
2018                 while(size--)
2019                         emitpcode(POC_CLRF,popGet(AOP(result),offset++));
2020         }
2021         
2022 }
2023
2024 /*-----------------------------------------------------------------*/
2025 /* pic14_outBitC - output a bit C                                  */
2026 /*-----------------------------------------------------------------*/
2027 void pic14_outBitC(operand *result)
2028 {
2029         
2030         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2031         /* if the result is bit */
2032         if (AOP_TYPE(result) == AOP_CRY) 
2033                 aopPut(AOP(result),"c",0);
2034         else {
2035                 pic14_emitcode("clr","a  ; %d", __LINE__);
2036                 pic14_emitcode("rlc","a");
2037                 pic14_outAcc(result);
2038         }
2039 }
2040
2041 /*-----------------------------------------------------------------*/
2042 /* pic14_toBoolean - emit code for orl a,operator(sizeop)          */
2043 /*-----------------------------------------------------------------*/
2044 void pic14_toBoolean(operand *oper)
2045 {
2046         int size = AOP_SIZE(oper);
2047         int offset = 0;
2048         
2049         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2050
2051         assert (size > 0);
2052
2053         if (size == 1) {
2054                 /* MOVFW does not load the flags... */
2055                 if (AOP_TYPE(oper) == AOP_ACC) {
2056                         emitpcode(POC_IORLW, popGetLit(0));
2057                         offset = 1;
2058                 } else {
2059                         emitpcode(POC_MOVLW, popGetLit(0));
2060                         offset = 0;
2061                 }
2062         } else {
2063                 if ( AOP_TYPE(oper) != AOP_ACC) {
2064                         emitpcode(POC_MOVFW,popGet(AOP(oper),0));
2065                         offset = 1;
2066                 }
2067         }
2068         
2069         while (offset < size) {
2070                 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
2071         }
2072         /* Z is set iff (oper == 0) */
2073 }
2074
2075
2076 /*-----------------------------------------------------------------*/
2077 /* genNot - generate code for ! operation                          */
2078 /*-----------------------------------------------------------------*/
2079 static void genNot (iCode *ic)
2080 {
2081         //symbol *tlbl;
2082         int size;
2083
2084         FENTRY;
2085         
2086         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2087         /* assign asmOps to operand & result */
2088         aopOp (IC_LEFT(ic),ic,FALSE);
2089         aopOp (IC_RESULT(ic),ic,TRUE);
2090         
2091         DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2092         /* if in bit space then a special case */
2093         if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2094                 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2095                         emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2096                         emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2097                 } else {
2098                         emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2099                         emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2100                         emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2101                 }
2102                 goto release;
2103         }
2104         
2105         size = AOP_SIZE(IC_LEFT(ic));
2106         mov2w (AOP(IC_LEFT(ic)),0);
2107         while (--size > 0)
2108         {
2109           if (op_isLitLike (IC_LEFT(ic)))
2110             emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2111           else
2112             emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2113         }
2114         emitpcode(POC_MOVLW, popGetLit (0));
2115         emitSKPNZ;
2116         emitpcode(POC_MOVLW, popGetLit (1));
2117         movwf(AOP(IC_RESULT(ic)), 0);
2118
2119         for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2120         {
2121           emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2122         }
2123         goto release;
2124         
2125 release:        
2126         /* release the aops */
2127         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2128         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2129 }
2130
2131
2132 /*-----------------------------------------------------------------*/
2133 /* genCpl - generate code for complement                                                   */
2134 /*-----------------------------------------------------------------*/
2135 static void genCpl (iCode *ic)
2136 {
2137         operand *left, *result;
2138         int size, offset=0;  
2139         
2140         FENTRY;
2141         
2142         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2143         aopOp((left = IC_LEFT(ic)),ic,FALSE);
2144         aopOp((result=IC_RESULT(ic)),ic,TRUE);
2145         
2146         /* if both are in bit space then 
2147         a special case */
2148         if (AOP_TYPE(result) == AOP_CRY &&
2149                 AOP_TYPE(left) == AOP_CRY ) { 
2150                 
2151                 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir); 
2152                 pic14_emitcode("cpl","c"); 
2153                 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir); 
2154                 goto release; 
2155         } 
2156         
2157         size = AOP_SIZE(result);
2158         if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2159         while (size--) {
2160                 
2161                 if(AOP_TYPE(left) == AOP_ACC) 
2162                         emitpcode(POC_XORLW, popGetLit(0xff));
2163                 else
2164                         emitpcode(POC_COMFW,popGet(AOP(left),offset));
2165                 
2166                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2167                 offset++;
2168         }
2169         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2170         
2171         
2172 release:
2173         /* release the aops */
2174         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2175         freeAsmop(result,NULL,ic,TRUE);
2176 }
2177
2178 /*-----------------------------------------------------------------*/
2179 /* genUminusFloat - unary minus for floating points                        */
2180 /*-----------------------------------------------------------------*/
2181 static void genUminusFloat(operand *op,operand *result)
2182 {
2183         int size ,offset =0 ;
2184         char *l;
2185         
2186         FENTRY;
2187
2188         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2189         /* for this we just need to flip the 
2190         first it then copy the rest in place */
2191         size = AOP_SIZE(op) - 1;
2192         l = aopGet(AOP(op),3,FALSE,FALSE);
2193         
2194         MOVA(l);          
2195         
2196         pic14_emitcode("cpl","acc.7");
2197         aopPut(AOP(result),"a",3);      
2198         
2199         while(size--) {
2200                 aopPut(AOP(result),
2201                         aopGet(AOP(op),offset,FALSE,FALSE),
2202                         offset);
2203                 offset++;
2204         }                
2205 }
2206
2207 /*-----------------------------------------------------------------*/
2208 /* genUminus - unary minus code generation                                                 */
2209 /*-----------------------------------------------------------------*/
2210 static void genUminus (iCode *ic)
2211 {
2212         int size, i;
2213         sym_link *optype, *rtype;
2214         
2215         FENTRY;
2216         
2217         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2218         /* assign asmops */
2219         aopOp(IC_LEFT(ic),ic,FALSE);
2220         aopOp(IC_RESULT(ic),ic,TRUE);
2221         
2222         /* if both in bit space then special
2223         case */
2224         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2225                 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2226                 
2227                 emitpcode(POC_BCF,       popGet(AOP(IC_RESULT(ic)),0));
2228                 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2229                 emitpcode(POC_BSF,       popGet(AOP(IC_RESULT(ic)),0));
2230                 
2231                 goto release; 
2232         } 
2233         
2234         optype = operandType(IC_LEFT(ic));
2235         rtype = operandType(IC_RESULT(ic));
2236         
2237         /* if float then do float stuff */
2238         if (IS_FLOAT(optype)) {
2239                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2240                 goto release;
2241         }
2242         
2243         /* otherwise subtract from zero by taking the 2's complement */
2244         size = AOP_SIZE(IC_LEFT(ic));
2245         
2246         for(i=0; i<size; i++) {
2247                 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2248                         emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
2249                 else {
2250                         emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2251                         emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2252                 }
2253         }
2254         
2255         emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
2256         for(i=1; i<size; i++) {
2257                 emitSKPNZ;
2258                 emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
2259         }
2260         
2261 release:
2262         /* release the aops */
2263         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2264         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);  
2265 }
2266
2267 /*-----------------------------------------------------------------*/
2268 /* saveRegisters - will look for a call and save the registers     */
2269 /*-----------------------------------------------------------------*/
2270 static void saveRegisters(iCode *lic) 
2271 {
2272         int i;
2273         iCode *ic;
2274         bitVect *rsave;
2275         sym_link *dtype;
2276         
2277         FENTRY;
2278
2279         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2280         /* look for call */
2281         for (ic = lic ; ic ; ic = ic->next) 
2282                 if (ic->op == CALL || ic->op == PCALL)
2283                         break;
2284                 
2285                 if (!ic) {
2286                         fprintf(stderr,"found parameter push with no function call\n");
2287                         return ;
2288                 }
2289                 
2290                 /* if the registers have been saved already then
2291                 do nothing */
2292                 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2293                         return ;
2294                 
2295                         /* find the registers in use at this time 
2296                 and push them away to safety */
2297                 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2298                         ic->rUsed);
2299                 
2300                 ic->regsSaved = 1;
2301                 if (options.useXstack) {
2302                         if (bitVectBitValue(rsave,R0_IDX))
2303                                 pic14_emitcode("mov","b,r0");
2304                         pic14_emitcode("mov","r0,%s",spname);
2305                         for (i = 0 ; i < pic14_nRegs ; i++) {
2306                                 if (bitVectBitValue(rsave,i)) {
2307                                         if (i == R0_IDX)
2308                                                 pic14_emitcode("mov","a,b");
2309                                         else
2310                                                 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2311                                         pic14_emitcode("movx","@r0,a");
2312                                         pic14_emitcode("inc","r0");
2313                                 }
2314                         }
2315                         pic14_emitcode("mov","%s,r0",spname);
2316                         if (bitVectBitValue(rsave,R0_IDX))
2317                                 pic14_emitcode("mov","r0,b");     
2318                 }// else
2319                 //for (i = 0 ; i < pic14_nRegs ; i++) {
2320                 //        if (bitVectBitValue(rsave,i))
2321                 //      pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2322                 //}
2323                 
2324                 dtype = operandType(IC_LEFT(ic));
2325                 if (currFunc && dtype && 
2326                         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2327                         IFFUNC_ISISR(currFunc->type) &&
2328                         !ic->bankSaved) 
2329                         
2330                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2331                 
2332 }
2333 /*-----------------------------------------------------------------*/
2334 /* unsaveRegisters - pop the pushed registers                                      */
2335 /*-----------------------------------------------------------------*/
2336 static void unsaveRegisters (iCode *ic)
2337 {
2338         int i;
2339         bitVect *rsave;
2340         
2341         FENTRY;
2342
2343         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2344         /* find the registers in use at this time 
2345         and push them away to safety */
2346         rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2347                 ic->rUsed);
2348         
2349         if (options.useXstack) {
2350                 pic14_emitcode("mov","r0,%s",spname); 
2351                 for (i =  pic14_nRegs ; i >= 0 ; i--) {
2352                         if (bitVectBitValue(rsave,i)) {
2353                                 pic14_emitcode("dec","r0");
2354                                 pic14_emitcode("movx","a,@r0");
2355                                 if (i == R0_IDX)
2356                                         pic14_emitcode("mov","b,a");
2357                                 else
2358                                         pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2359                         }       
2360                         
2361                 }
2362                 pic14_emitcode("mov","%s,r0",spname);
2363                 if (bitVectBitValue(rsave,R0_IDX))
2364                         pic14_emitcode("mov","r0,b");
2365         } //else
2366         //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2367         //      if (bitVectBitValue(rsave,i))
2368         //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2369         //}
2370         
2371 }  
2372
2373
2374 /*-----------------------------------------------------------------*/
2375 /* pushSide -                            */
2376 /*-----------------------------------------------------------------*/
2377 static void pushSide(operand * oper, int size)
2378 {
2379 #if 0
2380         int offset = 0;
2381         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2382         while (size--) {
2383                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2384                 if (AOP_TYPE(oper) != AOP_REG &&
2385                         AOP_TYPE(oper) != AOP_DIR &&
2386                         strcmp(l,"a") ) {
2387                         pic14_emitcode("mov","a,%s",l);
2388                         pic14_emitcode("push","acc");
2389                 } else
2390                         pic14_emitcode("push","%s",l);
2391         }
2392 #endif
2393 }
2394
2395 /*-----------------------------------------------------------------*/
2396 /* assignResultValue -                           */
2397 /*-----------------------------------------------------------------*/
2398 static void assignResultValue(operand * oper)
2399 {
2400         int size = AOP_SIZE(oper);
2401         int offset = 0;
2402         
2403         FENTRY;
2404
2405         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2406         
2407         DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2408         
2409         /* assign MSB first (passed via WREG) */
2410         while (size--) {
2411                 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2412                 GpsuedoStkPtr++;
2413         }
2414 }
2415
2416
2417 /*-----------------------------------------------------------------*/
2418 /* genIpush - genrate code for pushing this gets a little complex  */
2419 /*-----------------------------------------------------------------*/
2420 static void genIpush (iCode *ic)
2421 {
2422         FENTRY;
2423         
2424         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2425 #if 0
2426         int size, offset = 0 ;
2427         char *l;
2428         
2429         
2430         /* if this is not a parm push : ie. it is spill push 
2431         and spill push is always done on the local stack */
2432         if (!ic->parmPush) {
2433                 
2434                 /* and the item is spilt then do nothing */
2435                 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2436                         return ;
2437                 
2438                 aopOp(IC_LEFT(ic),ic,FALSE);
2439                 size = AOP_SIZE(IC_LEFT(ic));
2440                 /* push it on the stack */
2441                 while(size--) {
2442                         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2443                         if (*l == '#') {
2444                                 MOVA(l);
2445                                 l = "acc";
2446                         }
2447                         pic14_emitcode("push","%s",l);
2448                 }
2449                 return ;                
2450         }
2451         
2452         /* this is a paramter push: in this case we call
2453         the routine to find the call and save those
2454         registers that need to be saved */   
2455         saveRegisters(ic);
2456         
2457         /* then do the push */
2458         aopOp(IC_LEFT(ic),ic,FALSE);
2459         
2460         
2461         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2462         size = AOP_SIZE(IC_LEFT(ic));
2463         
2464         while (size--) {
2465                 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2466                 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2467                         AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2468                         strcmp(l,"a") ) {
2469                         pic14_emitcode("mov","a,%s",l);
2470                         pic14_emitcode("push","acc");
2471                 } else
2472                         pic14_emitcode("push","%s",l);
2473         }         
2474         
2475         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2476 #endif
2477 }
2478
2479 /*-----------------------------------------------------------------*/
2480 /* genIpop - recover the registers: can happen only for spilling   */
2481 /*-----------------------------------------------------------------*/
2482 static void genIpop (iCode *ic)
2483 {
2484         FENTRY;
2485
2486         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2487         assert (!"genIpop -- unimplemented");
2488 #if 0
2489         int size,offset ;
2490         
2491         
2492         /* if the temp was not pushed then */
2493         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2494                 return ;
2495         
2496         aopOp(IC_LEFT(ic),ic,FALSE);
2497         size = AOP_SIZE(IC_LEFT(ic));
2498         offset = (size-1);
2499         while (size--) 
2500                 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2501                 FALSE,TRUE));
2502         
2503         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2504 #endif
2505 }
2506
2507 /*-----------------------------------------------------------------*/
2508 /* unsaverbank - restores the resgister bank from stack                    */
2509 /*-----------------------------------------------------------------*/
2510 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2511 {
2512         FENTRY;
2513
2514         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2515 #if 0
2516         int i;
2517         asmop *aop ;
2518         regs *r = NULL;
2519         
2520         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2521         if (popPsw) {
2522                 if (options.useXstack) {
2523                         aop = newAsmop(0);
2524                         r = getFreePtr(ic,&aop,FALSE);
2525                         
2526                         
2527                         pic14_emitcode("mov","%s,_spx",r->name);
2528                         pic14_emitcode("movx","a,@%s",r->name);
2529                         pic14_emitcode("mov","psw,a");
2530                         pic14_emitcode("dec","%s",r->name);
2531                         
2532                 }else
2533                         pic14_emitcode ("pop","psw");
2534         }
2535         
2536         for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2537                 if (options.useXstack) {           
2538                         pic14_emitcode("movx","a,@%s",r->name);
2539                         //pic14_emitcode("mov","(%s+%d),a",
2540                         //         regspic14[i].base,8*bank+regspic14[i].offset);
2541                         pic14_emitcode("dec","%s",r->name);
2542                         
2543                 } else 
2544                         pic14_emitcode("pop",""); //"(%s+%d)",
2545                 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2546         }
2547         
2548         if (options.useXstack) {
2549                 
2550                 pic14_emitcode("mov","_spx,%s",r->name);
2551                 freeAsmop(NULL,aop,ic,TRUE);
2552                 
2553         }
2554 #endif 
2555 }
2556
2557 /*-----------------------------------------------------------------*/
2558 /* saverbank - saves an entire register bank on the stack                  */
2559 /*-----------------------------------------------------------------*/
2560 static void saverbank (int bank, iCode *ic, bool pushPsw)
2561 {
2562         FENTRY;
2563
2564         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2565 #if 0
2566         int i;
2567         asmop *aop ;
2568         regs *r = NULL;
2569         
2570         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2571         if (options.useXstack) {
2572                 
2573                 aop = newAsmop(0);
2574                 r = getFreePtr(ic,&aop,FALSE);  
2575                 pic14_emitcode("mov","%s,_spx",r->name);
2576                 
2577         }
2578         
2579         for (i = 0 ; i < pic14_nRegs ;i++) {
2580                 if (options.useXstack) {
2581                         pic14_emitcode("inc","%s",r->name);
2582                         //pic14_emitcode("mov","a,(%s+%d)",
2583                         //               regspic14[i].base,8*bank+regspic14[i].offset);
2584                         pic14_emitcode("movx","@%s,a",r->name);                 
2585                 } else 
2586                         pic14_emitcode("push","");// "(%s+%d)",
2587                 //regspic14[i].base,8*bank+regspic14[i].offset);
2588         }
2589         
2590         if (pushPsw) {
2591                 if (options.useXstack) {
2592                         pic14_emitcode("mov","a,psw");
2593                         pic14_emitcode("movx","@%s,a",r->name); 
2594                         pic14_emitcode("inc","%s",r->name);
2595                         pic14_emitcode("mov","_spx,%s",r->name);                 
2596                         freeAsmop (NULL,aop,ic,TRUE);
2597                         
2598                 } else
2599                         pic14_emitcode("push","psw");
2600                 
2601                 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2602         }
2603         ic->bankSaved = 1;
2604 #endif
2605 }
2606
2607 /*-----------------------------------------------------------------*/
2608 /* genCall - generates a call statement                                                    */
2609 /*-----------------------------------------------------------------*/
2610 static void genCall (iCode *ic)
2611 {
2612         sym_link *dtype;         
2613         symbol *sym;
2614         char *name;
2615         int isExtern;
2616         
2617         FENTRY;
2618
2619         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2620         
2621         /* if caller saves & we have not saved then */
2622         if (!ic->regsSaved)
2623                 saveRegisters(ic);
2624         
2625                 /* if we are calling a function that is not using
2626                 the same register bank then we need to save the
2627         destination registers on the stack */
2628         dtype = operandType(IC_LEFT(ic));
2629         if (currFunc && dtype && 
2630                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2631                 IFFUNC_ISISR(currFunc->type) &&
2632                 !ic->bankSaved) 
2633                 
2634                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2635         
2636         /* if send set is not empty the assign */
2637         if (_G.sendSet) {
2638                 iCode *sic;
2639                 /* For the Pic port, there is no data stack.
2640                 * So parameters passed to functions are stored
2641                 * in registers. (The pCode optimizer will get
2642                 * rid of most of these :).
2643                 */
2644                 int psuedoStkPtr=-1;
2645                 int firstTimeThruLoop = 1;
2646                 
2647                 _G.sendSet = reverseSet(_G.sendSet);
2648                 
2649                 /* First figure how many parameters are getting passed */
2650                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2651                 sic = setNextItem(_G.sendSet)) {
2652                         
2653                         aopOp(IC_LEFT(sic),sic,FALSE);
2654                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2655                         freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2656                 }
2657                 
2658                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2659                 sic = setNextItem(_G.sendSet)) {
2660                         int size, offset = 0;
2661                         
2662                         aopOp(IC_LEFT(sic),sic,FALSE);
2663                         size = AOP_SIZE(IC_LEFT(sic));
2664                         
2665                         while (size--) {
2666                                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2667                                         AopType(AOP_TYPE(IC_LEFT(sic))));
2668                                 
2669                                 if(!firstTimeThruLoop) {
2670                                         /* If this is not the first time we've been through the loop
2671                                         * then we need to save the parameter in a temporary
2672                                         * register. The last byte of the last parameter is
2673                                         * passed in W. */
2674                                         emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2675                                         
2676                                 }
2677                                 firstTimeThruLoop=0;
2678                                 
2679                                 mov2w_op (IC_LEFT(sic),  offset);
2680                                 offset++;
2681                         }
2682                         freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2683                 }
2684                 _G.sendSet = NULL;
2685         }
2686         /* make the call */
2687         sym = OP_SYMBOL(IC_LEFT(ic));
2688         name = sym->rname[0] ? sym->rname : sym->name;
2689         isExtern = IS_EXTERN(sym->etype);
2690         if (isExtern) {
2691                 emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2692         }
2693         emitpcode(POC_CALL,popGetWithString(name,isExtern));
2694         if (isExtern) {
2695                 emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel to restore PCLATH before next goto or call instruction */
2696         }
2697         GpsuedoStkPtr=0;
2698         /* if we need assign a result value */
2699         if ((IS_ITEMP(IC_RESULT(ic)) && 
2700                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2701                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2702                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2703                 
2704                 _G.accInUse++;
2705                 aopOp(IC_RESULT(ic),ic,FALSE);
2706                 _G.accInUse--;
2707                 
2708                 assignResultValue(IC_RESULT(ic));
2709                 
2710                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2711                         AopType(AOP_TYPE(IC_RESULT(ic))));
2712                 
2713                 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2714         }
2715         
2716         /* if register bank was saved then pop them */
2717         if (ic->bankSaved)
2718                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2719         
2720         /* if we hade saved some registers then unsave them */
2721         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2722                 unsaveRegisters (ic);
2723         
2724         
2725 }
2726
2727 /*-----------------------------------------------------------------*/
2728 /* genPcall - generates a call by pointer statement                        */
2729 /*-----------------------------------------------------------------*/
2730 static void genPcall (iCode *ic)
2731 {
2732         sym_link *dtype;
2733         symbol *albl = newiTempLabel(NULL);
2734         symbol *blbl = newiTempLabel(NULL);
2735         PIC_OPCODE poc;
2736         pCodeOp *pcop;
2737         operand *left;
2738         
2739         FENTRY;
2740
2741         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2742         /* if caller saves & we have not saved then */
2743         if (!ic->regsSaved)
2744                 saveRegisters(ic);
2745         
2746                 /* if we are calling a function that is not using
2747                 the same register bank then we need to save the
2748         destination registers on the stack */
2749         dtype = operandType(IC_LEFT(ic));
2750         if (currFunc && dtype && 
2751                 IFFUNC_ISISR(currFunc->type) &&
2752                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2753                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2754         
2755         left = IC_LEFT(ic);
2756         aopOp(left,ic,FALSE);
2757         DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2758         
2759         poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2760         
2761         pushSide(IC_LEFT(ic), FPTRSIZE);
2762         
2763         /* if send set is not empty, assign parameters */
2764         if (_G.sendSet) {
2765                 
2766                 DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2767                 /* no way to pass args - W always gets used to make the call */
2768         }
2769         /* first idea - factor out a common helper function and call it.
2770         But don't know how to get it generated only once in its own block
2771         
2772         if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2773                 char *rname;
2774                 char *buffer;
2775                 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2776                 DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2777                 buffer = Safe_calloc(1,strlen(rname)+16);
2778                 sprintf(buffer, "%s_goto_helper", rname);
2779                 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2780                 free(buffer);
2781         }
2782         */
2783         emitpcode(POC_CALL,popGetLabel(albl->key));
2784         pcop = popGetLabel(blbl->key);
2785         emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2786         emitpcode(POC_GOTO,pcop);
2787         emitpLabel(albl->key);
2788         
2789         emitpcode(poc,popGetAddr(AOP(left),1,0));
2790         emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2791         emitpcode(poc,popGetAddr(AOP(left),0,0));
2792         emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2793         
2794         emitpLabel(blbl->key);
2795         
2796         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2797         
2798         /* if we need to assign a result value */
2799         if ((IS_ITEMP(IC_RESULT(ic)) &&
2800                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2801                 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2802                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2803                 
2804                 _G.accInUse++;
2805                 aopOp(IC_RESULT(ic),ic,FALSE);
2806                 _G.accInUse--;
2807
2808                 GpsuedoStkPtr = 0;
2809                 
2810                 assignResultValue(IC_RESULT(ic));
2811                 
2812                 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2813         }
2814         
2815         /* if register bank was saved then unsave them */
2816         if (currFunc && dtype && 
2817                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2818                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2819         
2820                 /* if we hade saved some registers then
2821         unsave them */
2822         if (ic->regsSaved)
2823                 unsaveRegisters (ic);
2824         
2825 }
2826
2827 /*-----------------------------------------------------------------*/
2828 /* resultRemat - result  is rematerializable                                       */
2829 /*-----------------------------------------------------------------*/
2830 static int resultRemat (iCode *ic)
2831 {
2832         //      DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2833         FENTRY;
2834
2835         if (SKIP_IC(ic) || ic->op == IFX)
2836                 return 0;
2837         
2838         if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2839                 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2840                 if (sym->remat && !POINTER_SET(ic)) 
2841                         return 1;
2842         }
2843         
2844         return 0;
2845 }
2846
2847 #if defined(__BORLANDC__) || defined(_MSC_VER)
2848 #define STRCASECMP stricmp
2849 #else
2850 #define STRCASECMP strcasecmp
2851 #endif
2852
2853 #if 0
2854 /*-----------------------------------------------------------------*/
2855 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2856 /*-----------------------------------------------------------------*/
2857 static bool inExcludeList(char *s)
2858 {
2859         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2860         int i =0;
2861         
2862         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2863         if (options.excludeRegs[i] &&
2864                 STRCASECMP(options.excludeRegs[i],"none") == 0)
2865                 return FALSE ;
2866         
2867         for ( i = 0 ; options.excludeRegs[i]; i++) {
2868                 if (options.excludeRegs[i] &&
2869                         STRCASECMP(s,options.excludeRegs[i]) == 0)
2870                         return TRUE;
2871         }
2872         return FALSE ;
2873 }
2874 #endif
2875
2876 /*-----------------------------------------------------------------*/
2877 /* genFunction - generated code for function entry                                 */
2878 /*-----------------------------------------------------------------*/
2879 static void genFunction (iCode *ic)
2880 {
2881         symbol *sym;
2882         sym_link *ftype;
2883         
2884         FENTRY;
2885
2886         DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2887         
2888         labelOffset += (max_key+4);
2889         max_key=0;
2890         GpsuedoStkPtr=0;
2891         _G.nRegsSaved = 0;
2892         /* create the function header */
2893         pic14_emitcode(";","-----------------------------------------");
2894         pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2895         pic14_emitcode(";","-----------------------------------------");
2896         
2897         pic14_emitcode("","%s:",sym->rname);
2898         addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2899         
2900         ftype = operandType(IC_LEFT(ic));
2901         
2902         /* if critical function then turn interrupts off */
2903         if (IFFUNC_ISCRITICAL(ftype))
2904                 pic14_emitcode("clr","ea");
2905         
2906                 /* here we need to generate the equates for the
2907         register bank if required */
2908 #if 0
2909         if (FUNC_REGBANK(ftype) != rbank) {
2910                 int i ;
2911                 
2912                 rbank = FUNC_REGBANK(ftype);
2913                 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2914                         if (strcmp(regspic14[i].base,"0") == 0)
2915                                 pic14_emitcode("","%s = 0x%02x",
2916                                 regspic14[i].dname,
2917                                 8*rbank+regspic14[i].offset);
2918                         else
2919                                 pic14_emitcode ("","%s = %s + 0x%02x",
2920                                 regspic14[i].dname,
2921                                 regspic14[i].base,
2922                                 8*rbank+regspic14[i].offset);
2923                 }
2924         }
2925 #endif
2926         
2927         /* if this is an interrupt service routine */
2928         if (IFFUNC_ISISR(sym->type)) {
2929         /*  already done in pic14createInterruptVect() - delete me
2930         addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2931         emitpcodeNULLop(POC_NOP);
2932         emitpcodeNULLop(POC_NOP);
2933         emitpcodeNULLop(POC_NOP);
2934                 */
2935                 emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2936                 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2937                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2938                 emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2939                 emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2940                 emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2941                 emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2942                 
2943                 pBlockConvert2ISR(pb);
2944                 pic14_hasInterrupt = 1;
2945 #if 0  
2946                 if (!inExcludeList("acc"))              
2947                         pic14_emitcode ("push","acc");  
2948                 if (!inExcludeList("b"))
2949                         pic14_emitcode ("push","b");
2950                 if (!inExcludeList("dpl"))
2951                         pic14_emitcode ("push","dpl");
2952                 if (!inExcludeList("dph"))
2953                         pic14_emitcode ("push","dph");
2954                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2955                 {
2956                         pic14_emitcode ("push", "dpx");
2957                         /* Make sure we're using standard DPTR */
2958                         pic14_emitcode ("push", "dps");
2959                         pic14_emitcode ("mov", "dps, #0x00");
2960                         if (options.stack10bit)
2961                         { 
2962                                 /* This ISR could conceivably use DPTR2. Better save it. */
2963                                 pic14_emitcode ("push", "dpl1");
2964                                 pic14_emitcode ("push", "dph1");
2965                                 pic14_emitcode ("push", "dpx1");
2966                         }
2967                 }
2968                 /* if this isr has no bank i.e. is going to
2969                 run with bank 0 , then we need to save more
2970                 registers :-) */
2971                 if (!FUNC_REGBANK(sym->type)) {
2972                         
2973                 /* if this function does not call any other
2974                 function then we can be economical and
2975                         save only those registers that are used */
2976                         if (! IFFUNC_HASFCALL(sym->type)) {
2977                                 int i;
2978                                 
2979                                 /* if any registers used */
2980                                 if (sym->regsUsed) {
2981                                         /* save the registers used */
2982                                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2983                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2984                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2985                                                         pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);               
2986                                         }
2987                                 }
2988                                 
2989                         } else {
2990                         /* this function has    a function call cannot
2991                         determines register usage so we will have the
2992                                 entire bank */
2993                                 saverbank(0,ic,FALSE);
2994                         }       
2995                 }
2996 #endif
2997         } else {
2998         /* if callee-save to be used for this function
2999                 then save the registers being used in this function */
3000                 if (IFFUNC_CALLEESAVES(sym->type)) {
3001                         int i;
3002                         
3003                         /* if any registers used */
3004                         if (sym->regsUsed) {
3005                                 /* save the registers used */
3006                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3007                                         if (bitVectBitValue(sym->regsUsed,i) ||
3008                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
3009                                                 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
3010                                                 _G.nRegsSaved++;
3011                                         }
3012                                 }
3013                         }
3014                 }
3015         }
3016         
3017         /* set the register bank to the desired value */
3018         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
3019                 pic14_emitcode("push","psw");
3020                 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);       
3021         }
3022         
3023         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3024                 
3025                 if (options.useXstack) {
3026                         pic14_emitcode("mov","r0,%s",spname);
3027                         pic14_emitcode("mov","a,_bp");
3028                         pic14_emitcode("movx","@r0,a");
3029                         pic14_emitcode("inc","%s",spname);
3030                 }
3031                 else
3032                 {
3033                         /* set up the stack */
3034                         pic14_emitcode ("push","_bp");   /* save the callers stack      */
3035                 }
3036                 pic14_emitcode ("mov","_bp,%s",spname);
3037         }
3038         
3039         /* adjust the stack for the function */
3040         if (sym->stack) {
3041                 
3042                 int i = sym->stack;
3043                 if (i > 256 ) 
3044                         werror(W_STACK_OVERFLOW,sym->name);
3045                 
3046                 if (i > 3 && sym->recvSize < 4) {                
3047                         
3048                         pic14_emitcode ("mov","a,sp");
3049                         pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3050                         pic14_emitcode ("mov","sp,a");
3051                         
3052                 }
3053                 else
3054                         while(i--)
3055                                 pic14_emitcode("inc","sp");
3056         }
3057         
3058         if (sym->xstack) {
3059                 
3060                 pic14_emitcode ("mov","a,_spx");
3061                 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3062                 pic14_emitcode ("mov","_spx,a");
3063         }
3064         
3065 }
3066
3067 /*-----------------------------------------------------------------*/
3068 /* genEndFunction - generates epilogue for functions                       */
3069 /*-----------------------------------------------------------------*/
3070 static void genEndFunction (iCode *ic)
3071 {
3072         symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3073         
3074         FENTRY;
3075
3076         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3077         
3078         if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3079         {
3080                 pic14_emitcode ("mov","%s,_bp",spname);
3081         }
3082         
3083         /* if use external stack but some variables were
3084         added to the local stack then decrement the
3085         local stack */
3086         if (options.useXstack && sym->stack) {    
3087                 pic14_emitcode("mov","a,sp");
3088                 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3089                 pic14_emitcode("mov","sp,a");
3090         }
3091         
3092         
3093         if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3094                 if (options.useXstack) {
3095                         pic14_emitcode("mov","r0,%s",spname);
3096                         pic14_emitcode("movx","a,@r0");
3097                         pic14_emitcode("mov","_bp,a");
3098                         pic14_emitcode("dec","%s",spname);
3099                 }
3100                 else
3101                 {
3102                         pic14_emitcode ("pop","_bp");
3103                 }
3104         }
3105         
3106         /* restore the register bank    */        
3107         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3108                 pic14_emitcode ("pop","psw");
3109         
3110         if (IFFUNC_ISISR(sym->type)) {
3111                 
3112                 /* now we need to restore the registers */
3113                 /* if this isr has no bank i.e. is going to
3114                 run with bank 0 , then we need to save more
3115 registers :-) */
3116                 if (!FUNC_REGBANK(sym->type)) {
3117                         
3118                 /* if this function does not call any other
3119                 function then we can be economical and
3120                         save only those registers that are used */
3121                         if (! IFFUNC_HASFCALL(sym->type)) {
3122                                 int i;
3123                                 
3124                                 /* if any registers used */
3125                                 if (sym->regsUsed) {
3126                                         /* save the registers used */
3127                                         for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3128                                                 if (bitVectBitValue(sym->regsUsed,i) ||
3129                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3130                                                         pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3131                                         }
3132                                 }
3133                                 
3134                         } else {
3135                         /* this function has    a function call cannot
3136                         determines register usage so we will have the
3137                                 entire bank */
3138                                 unsaverbank(0,ic,FALSE);
3139                         }       
3140                 }
3141 #if 0
3142                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3143                 {
3144                         if (options.stack10bit)
3145                         {
3146                                 pic14_emitcode ("pop", "dpx1");
3147                                 pic14_emitcode ("pop", "dph1");
3148                                 pic14_emitcode ("pop", "dpl1");
3149                         } 
3150                         pic14_emitcode ("pop", "dps");
3151                         pic14_emitcode ("pop", "dpx");
3152                 }
3153                 if (!inExcludeList("dph"))
3154                         pic14_emitcode ("pop","dph");
3155                 if (!inExcludeList("dpl"))
3156                         pic14_emitcode ("pop","dpl");
3157                 if (!inExcludeList("b"))
3158                         pic14_emitcode ("pop","b");
3159                 if (!inExcludeList("acc"))
3160                         pic14_emitcode ("pop","acc");
3161                 
3162                 if (IFFUNC_ISCRITICAL(sym->type))
3163                         pic14_emitcode("setb","ea");
3164 #endif
3165                 
3166                 /* if debug then send end of function */
3167                 /*      if (options.debug && currFunc) { */
3168                 if (currFunc) {
3169                         debugFile->writeEndFunction (currFunc, ic, 1);
3170                 }
3171                 
3172                 pic14_emitcode ("reti","");
3173                 emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
3174                 emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
3175                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
3176                 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3177                 emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
3178                 emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
3179                 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3180                 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3181                 emitpcodeNULLop(POC_RETFIE);
3182         }
3183         else {
3184                 if (IFFUNC_ISCRITICAL(sym->type))
3185                         pic14_emitcode("setb","ea");
3186                 
3187                 if (IFFUNC_CALLEESAVES(sym->type)) {
3188                         int i;
3189                         
3190                         /* if any registers used */
3191                         if (sym->regsUsed) {
3192                                 /* save the registers used */
3193                                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3194                                         if (bitVectBitValue(sym->regsUsed,i) ||
3195                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3196                                                 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3197                                 }
3198                         }
3199                         
3200                 }
3201                 
3202                 /* if debug then send end of function */
3203                 if (currFunc) {
3204                         debugFile->writeEndFunction (currFunc, ic, 1);
3205                 }
3206                 
3207                 pic14_emitcode ("return","");
3208                 emitpcodeNULLop(POC_RETURN);
3209                 
3210                 /* Mark the end of a function */
3211                 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3212         }
3213         
3214 }
3215
3216 /*-----------------------------------------------------------------*/
3217 /* genRet - generate code for return statement                                     */
3218 /*-----------------------------------------------------------------*/
3219 static void genRet (iCode *ic)
3220 {
3221         int size,offset = 0;
3222         
3223         FENTRY;
3224
3225         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3226         /* if we have no return value then
3227         just generate the "ret" */
3228         if (!IC_LEFT(ic)) 
3229                 goto jumpret;           
3230         
3231                 /* we have something to return then
3232         move the return value into place */
3233         aopOp(IC_LEFT(ic),ic,FALSE);
3234         size = AOP_SIZE(IC_LEFT(ic));
3235
3236         for (offset = 0; offset < size; offset++)
3237         {
3238                 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3239         }
3240         
3241         freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3242         
3243 jumpret:
3244         /* generate a jump to the return label
3245         if the next is not the return statement */
3246         if (!(ic->next && ic->next->op == LABEL &&
3247                 IC_LABEL(ic->next) == returnLabel)) {
3248                 
3249                 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3250         }
3251         
3252 }
3253
3254 /*-----------------------------------------------------------------*/
3255 /* genLabel - generates a label                                                                    */
3256 /*-----------------------------------------------------------------*/
3257 static void genLabel (iCode *ic)
3258 {
3259         FENTRY;
3260
3261         /* special case never generate */
3262         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3263         if (IC_LABEL(ic) == entryLabel)
3264                 return ;
3265         
3266         emitpLabel(IC_LABEL(ic)->key);
3267         pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3268 }
3269
3270 /*-----------------------------------------------------------------*/
3271 /* genGoto - generates a goto                                                                      */
3272 /*-----------------------------------------------------------------*/
3273 //tsd
3274 static void genGoto (iCode *ic)
3275 {
3276         FENTRY;
3277
3278         emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3279         pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3280 }
3281
3282
3283 /*-----------------------------------------------------------------*/
3284 /* genMultbits :- multiplication of bits                                                   */
3285 /*-----------------------------------------------------------------*/
3286 static void genMultbits (operand *left, 
3287                                                  operand *right, 
3288                                                  operand *result)
3289 {
3290         FENTRY;
3291         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3292         
3293         if(!pic14_sameRegs(AOP(result),AOP(right)))
3294                 emitpcode(POC_BSF,      popGet(AOP(result),0));
3295         
3296         emitpcode(POC_BTFSC,popGet(AOP(right),0));
3297         emitpcode(POC_BTFSS,popGet(AOP(left),0));
3298         emitpcode(POC_BCF,  popGet(AOP(result),0));
3299         
3300 }
3301
3302
3303 /*-----------------------------------------------------------------*/
3304 /* genMultOneByte : 8 bit multiplication & division                        */
3305 /*-----------------------------------------------------------------*/
3306 static void genMultOneByte (operand *left,
3307                                                         operand *right,
3308                                                         operand *result)
3309 {
3310         char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3311         
3312         // symbol *lbl ;
3313         int size,offset,i;
3314         
3315         
3316         FENTRY;
3317         
3318         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3319         DEBUGpic14_AopType(__LINE__,left,right,result);
3320         DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3321         
3322         /* (if two literals, the value is computed before) */
3323         /* if one literal, literal on the right */
3324         if (AOP_TYPE(left) == AOP_LIT){
3325                 operand *t = right;
3326                 right = left;
3327                 left = t;
3328         }
3329
3330         assert (AOP_SIZE(left) == AOP_SIZE(right));
3331         
3332         size = min(AOP_SIZE(result),AOP_SIZE(left));
3333         offset = Gstack_base_addr - (2*size - 1);
3334
3335         /* pass right operand as argument */
3336         for (i=0; i < size; i++)
3337         {
3338                 mov2w (AOP(right), i);
3339                 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3340         } // for
3341         
3342         /* pass left operand as argument */
3343         for (i=0; i < size; i++)
3344         {
3345                 mov2w (AOP(left), i);
3346                 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3347         } // for
3348         assert (offset == Gstack_base_addr);
3349         
3350         /* call library routine */
3351         assert (size > 0 && size <= 4);
3352         call_libraryfunc (func[size]);
3353         
3354         /* assign result */
3355         movwf (AOP(result), size-1);
3356         for (i=0; i < size - 1; i++)
3357         {
3358                 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3359                 movwf (AOP(result), size - 2 - i);
3360         } // for
3361
3362         /* now (zero-/sign) extend the result to its size */
3363         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3364 }
3365
3366 /*-----------------------------------------------------------------*/
3367 /* genMult - generates code for multiplication                                     */
3368 /*-----------------------------------------------------------------*/
3369 static void genMult (iCode *ic)
3370 {
3371         operand *left = IC_LEFT(ic);
3372         operand *right = IC_RIGHT(ic);
3373         operand *result= IC_RESULT(ic); 
3374         
3375         FENTRY;
3376
3377         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3378         /* assign the amsops */
3379         aopOp (left,ic,FALSE);
3380         aopOp (right,ic,FALSE);
3381         aopOp (result,ic,TRUE);
3382         
3383         DEBUGpic14_AopType(__LINE__,left,right,result);
3384         
3385         /* special cases first */
3386         /* both are bits */
3387         if (AOP_TYPE(left) == AOP_CRY &&
3388                 AOP_TYPE(right)== AOP_CRY) {
3389                 genMultbits(left,right,result);
3390                 goto release ;
3391         }
3392         
3393         /* if both are of size == 1 */
3394         if (AOP_SIZE(left) == 1 &&
3395                 AOP_SIZE(right) == 1 ) {
3396                 genMultOneByte(left,right,result);
3397                 goto release ;
3398         }
3399         
3400         /* should have been converted to function call */
3401         assert(0) ;
3402         
3403 release :
3404         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3405         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3406         freeAsmop(result,NULL,ic,TRUE); 
3407 }
3408
3409 /*-----------------------------------------------------------------*/
3410 /* genDivbits :- division of bits                                                                  */
3411 /*-----------------------------------------------------------------*/
3412 static void genDivbits (operand *left, 
3413                                                 operand *right, 
3414                                                 operand *result)
3415 {
3416         
3417         char *l;
3418         
3419         FENTRY;
3420
3421         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3422         /* the result must be bit */      
3423         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3424         l = aopGet(AOP(left),0,FALSE,FALSE);
3425         
3426         MOVA(l);          
3427         
3428         pic14_emitcode("div","ab");
3429         pic14_emitcode("rrc","a");
3430         aopPut(AOP(result),"c",0);
3431 }
3432
3433 /*-----------------------------------------------------------------*/
3434 /* genDivOneByte : 8 bit division                                                                  */
3435 /*-----------------------------------------------------------------*/
3436 static void genDivOneByte (operand *left,
3437                                                    operand *right,
3438                                                    operand *result)
3439 {
3440         int size;
3441         
3442         FENTRY;
3443         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3444         
3445         assert (AOP_SIZE(result) == 1);
3446         assert (AOP_SIZE(right) == 1);
3447         assert (AOP_SIZE(left) == 1);
3448
3449         size = min(AOP_SIZE(result),AOP_SIZE(left));
3450
3451         if (AOP_TYPE(right) == AOP_LIT)
3452         {
3453                 /* XXX: might add specialized code */
3454         }
3455
3456         if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3457         {
3458                 /* unsigned division */
3459         #if 1
3460                 mov2w(AOP(right),0);
3461                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3462                 mov2w(AOP(left),0);
3463                 call_libraryfunc("__divuchar");
3464                 movwf(AOP(result),0);
3465         #else
3466                 pCodeOp *temp;
3467                 symbol *lbl;
3468
3469                 temp = popGetTempReg();
3470                 lbl = newiTempLabel(NULL);
3471                 
3472                 /* XXX: improve this naive approach:
3473                    [result] = [a] / [b]
3474                         ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3475
3476                    In PIC assembler:
3477                    movf  left,W
3478                    movwf temp           // temp <-- left
3479                    movf  right,W        // W <-- right
3480                    clrf  result
3481                    label1:
3482                    incf  result
3483                    subwf temp,F         // temp <-- temp - W
3484                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if temp < W
3485                    goto  label1
3486                    decf result          // we just subtract once too often
3487                  */
3488
3489                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3490                 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3491                 
3492                 mov2w(AOP(left),0);
3493                 emitpcode(POC_MOVWF, temp);
3494                 mov2w(AOP(right),0);
3495                 emitpcode(POC_CLRF, popGet(AOP(result),0));
3496
3497                 emitpLabel(lbl->key);
3498                 emitpcode(POC_INCF, popGet(AOP(result),0));
3499                 emitpcode(POC_SUBWF, temp);
3500                 emitSKPNC;
3501                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3502                 emitpcode(POC_DECF, popGet(AOP(result),0));
3503         #endif
3504         }
3505         else
3506         {
3507                 /* signed division */
3508                 mov2w(AOP(right),0);
3509                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3510                 mov2w(AOP(left),0);
3511                 call_libraryfunc("__divschar");
3512                 movwf(AOP(result),0);
3513         }
3514
3515         /* now performed the signed/unsigned division -- extend result */
3516         addSign(result, 1, !SPEC_USIGN(operandType(result)));
3517 }
3518
3519 /*-----------------------------------------------------------------*/
3520 /* genDiv - generates code for division                            */
3521 /*-----------------------------------------------------------------*/
3522 static void genDiv (iCode *ic)
3523 {
3524         operand *left = IC_LEFT(ic);
3525         operand *right = IC_RIGHT(ic);
3526         operand *result= IC_RESULT(ic); 
3527         
3528         FENTRY;
3529         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3530         /* assign the amsops */
3531         aopOp (left,ic,FALSE);
3532         aopOp (right,ic,FALSE);
3533         aopOp (result,ic,TRUE);
3534         
3535         /* special cases first */
3536         /* both are bits */
3537         if (AOP_TYPE(left) == AOP_CRY &&
3538                 AOP_TYPE(right)== AOP_CRY) {
3539                 genDivbits(left,right,result);
3540                 goto release ;
3541         }
3542         
3543         /* if both are of size == 1 */
3544         if (AOP_SIZE(left) == 1 &&
3545                 AOP_SIZE(right) == 1 ) {
3546                 genDivOneByte(left,right,result);
3547                 goto release ;
3548         }
3549         
3550         /* should have been converted to function call */
3551         assert(0);
3552 release :
3553         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3554         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3555         freeAsmop(result,NULL,ic,TRUE); 
3556 }
3557
3558 /*-----------------------------------------------------------------*/
3559 /* genModbits :- modulus of bits                                                                   */
3560 /*-----------------------------------------------------------------*/
3561 static void genModbits (operand *left, 
3562                                                 operand *right, 
3563                                                 operand *result)
3564 {
3565         
3566         char *l;
3567         
3568         FENTRY;
3569         /* the result must be bit */      
3570         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3571         l = aopGet(AOP(left),0,FALSE,FALSE);
3572         
3573         MOVA(l);
3574         
3575         pic14_emitcode("div","ab");
3576         pic14_emitcode("mov","a,b");
3577         pic14_emitcode("rrc","a");
3578         aopPut(AOP(result),"c",0);
3579 }
3580
3581 /*-----------------------------------------------------------------*/
3582 /* genModOneByte : 8 bit modulus                                                                   */
3583 /*-----------------------------------------------------------------*/
3584 static void genModOneByte (operand *left,
3585                                                    operand *right,
3586                                                    operand *result)
3587 {
3588         int size;
3589         
3590         FENTRY;
3591         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3592         
3593         assert (AOP_SIZE(result) == 1);
3594         assert (AOP_SIZE(right) == 1);
3595         assert (AOP_SIZE(left) == 1);
3596
3597         size = min(AOP_SIZE(result),AOP_SIZE(left));
3598
3599         if (AOP_TYPE(right) == AOP_LIT)
3600         {
3601                 /* XXX: might add specialized code */
3602         }
3603
3604         if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3605         {
3606                 /* unsigned division */
3607         #if 1
3608                 mov2w(AOP(right),0);
3609                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3610                 mov2w(AOP(left),0);
3611                 call_libraryfunc("__moduchar");
3612                 movwf(AOP(result),0);
3613         #else
3614                 pCodeOp *temp;
3615                 symbol *lbl;
3616
3617                 lbl = newiTempLabel(NULL);
3618                 
3619                 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3620
3621                 /* XXX: improve this naive approach:
3622                    [result] = [a] % [b]
3623                         ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3624
3625                    In PIC assembler:
3626                    movf  left,W
3627                    movwf result         // result <-- left
3628                    movf  right,W        // W <-- right
3629                    label1:
3630                    subwf result,F       // result <-- result - W
3631                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if result < W
3632                    goto  label1
3633                    addwf result, F      // we just subtract once too often
3634                  */
3635
3636                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3637                 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3638                 
3639                 if (!pic14_sameRegs(AOP(left), AOP(result)))
3640                 {
3641                         mov2w(AOP(left),0);
3642                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
3643                 }
3644                 mov2w(AOP(right),0);
3645
3646                 emitpLabel(lbl->key);
3647                 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3648                 emitSKPNC;
3649                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3650                 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3651         #endif
3652         }
3653         else
3654         {
3655                 /* signed division */
3656                 mov2w(AOP(right),0);
3657                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3658                 mov2w(AOP(left),0);
3659                 call_libraryfunc("__modschar");
3660                 movwf(AOP(result),0);
3661         }
3662
3663         /* now we performed the signed/unsigned modulus -- extend result */
3664         addSign(result, 1, !SPEC_USIGN(operandType(result)));
3665 }
3666
3667 /*-----------------------------------------------------------------*/
3668 /* genMod - generates code for division                                                    */
3669 /*-----------------------------------------------------------------*/
3670 static void genMod (iCode *ic)
3671 {
3672         operand *left = IC_LEFT(ic);
3673         operand *right = IC_RIGHT(ic);
3674         operand *result= IC_RESULT(ic);  
3675         
3676         FENTRY;
3677         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3678         /* assign the amsops */
3679         aopOp (left,ic,FALSE);
3680         aopOp (right,ic,FALSE);
3681         aopOp (result,ic,TRUE);
3682         
3683         /* special cases first */
3684         /* both are bits */
3685         if (AOP_TYPE(left) == AOP_CRY &&
3686                 AOP_TYPE(right)== AOP_CRY) {
3687                 genModbits(left,right,result);
3688                 goto release ;
3689         }
3690         
3691         /* if both are of size == 1 */
3692         if (AOP_SIZE(left) == 1 &&
3693                 AOP_SIZE(right) == 1 ) {
3694                 genModOneByte(left,right,result);
3695                 goto release ;
3696         }
3697         
3698         /* should have been converted to function call */
3699         assert(0);
3700         
3701 release :
3702         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3703         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3704         freeAsmop(result,NULL,ic,TRUE); 
3705 }
3706
3707 /*-----------------------------------------------------------------*/
3708 /* genIfxJump :- will create a jump depending on the ifx                   */
3709 /*-----------------------------------------------------------------*/
3710 /*
3711 note: May need to add parameter to indicate when a variable is in bit space.
3712 */
3713 static void genIfxJump (iCode *ic, char *jval)
3714 {
3715         
3716         FENTRY;
3717         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3718         /* if true label then we jump if condition
3719         supplied is true */
3720         if ( IC_TRUE(ic) ) {
3721                 
3722                 if(strcmp(jval,"a") == 0)
3723                         emitSKPZ;
3724                 else if (strcmp(jval,"c") == 0)
3725                         emitSKPC;
3726                 else {
3727                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3728                         emitpcode(POC_BTFSC,    newpCodeOpBit(jval,-1,1));
3729                 }
3730                 
3731                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3732                 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3733                 
3734         }
3735         else {
3736                 /* false label is present */
3737                 if(strcmp(jval,"a") == 0)
3738                         emitSKPNZ;
3739                 else if (strcmp(jval,"c") == 0)
3740                         emitSKPNC;
3741                 else {
3742                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3743                         emitpcode(POC_BTFSS,    newpCodeOpBit(jval,-1,1));
3744                 }
3745                 
3746                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3747                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3748                 
3749         }
3750         
3751         
3752         /* mark the icode as generated */
3753         ic->generated = 1;
3754 }
3755
3756 #if 0
3757 /*-----------------------------------------------------------------*/
3758 /* genSkip                                                                                                                 */
3759 /*-----------------------------------------------------------------*/
3760 static void genSkip(iCode *ifx,int status_bit)
3761 {
3762         FENTRY;
3763         if(!ifx)
3764                 return;
3765         
3766         if ( IC_TRUE(ifx) ) {
3767                 switch(status_bit) {
3768                 case 'z':
3769                         emitSKPNZ;
3770                         break;
3771                         
3772                 case 'c':
3773                         emitSKPNC;
3774                         break;
3775                         
3776                 case 'd':
3777                         emitSKPDC;
3778                         break;
3779                         
3780                 }
3781                 
3782                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3783                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3784                 
3785         } else {
3786                 
3787                 switch(status_bit) {
3788                         
3789                 case 'z':
3790                         emitSKPZ;
3791                         break;
3792                         
3793                 case 'c':
3794                         emitSKPC;
3795                         break;
3796                         
3797                 case 'd':
3798                         emitSKPDC;
3799                         break;
3800                 }
3801                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3802                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3803                 
3804         }
3805         
3806 }
3807 #endif
3808
3809 /*-----------------------------------------------------------------*/
3810 /* genSkipc                                                                                                        */
3811 /*-----------------------------------------------------------------*/
3812 static void genSkipc(resolvedIfx *rifx)
3813 {
3814         FENTRY;
3815         if(!rifx)
3816                 return;
3817         
3818         if(rifx->condition)
3819                 emitSKPNC;
3820         else
3821                 emitSKPC;
3822         
3823         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3824         emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3825         rifx->generated = 1;
3826 }
3827
3828 #if 0
3829 /*-----------------------------------------------------------------*/
3830 /* genSkipz2                                                                                                       */
3831 /*-----------------------------------------------------------------*/
3832 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3833 {
3834         FENTRY;
3835         if(!rifx)
3836                 return;
3837         
3838         if( (rifx->condition ^ invert_condition) & 1)
3839                 emitSKPZ;
3840         else
3841                 emitSKPNZ;
3842         
3843         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3844         rifx->generated = 1;
3845 }
3846 #endif
3847
3848 #if 0
3849 /*-----------------------------------------------------------------*/
3850 /* genSkipz                                                        */
3851 /*-----------------------------------------------------------------*/
3852 static void genSkipz(iCode *ifx, int condition)
3853 {
3854         FENTRY;
3855         assert (ifx != NULL);
3856         
3857         if(condition)
3858                 emitSKPNZ;
3859         else
3860                 emitSKPZ;
3861         
3862         if ( IC_TRUE(ifx) )
3863                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3864         else
3865                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3866         
3867         if ( IC_TRUE(ifx) )
3868                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3869         else
3870                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3871         
3872 }
3873 #endif
3874
3875 #if 0
3876 /*-----------------------------------------------------------------*/
3877 /* genSkipCond                                                     */
3878 /*-----------------------------------------------------------------*/
3879 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3880 {
3881         FENTRY;
3882         if(!rifx)
3883                 return;
3884         
3885         if(rifx->condition)
3886                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3887         else
3888                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3889         
3890         
3891         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3892         rifx->generated = 1;
3893 }
3894 #endif
3895
3896 #if 0
3897 /*-----------------------------------------------------------------*/
3898 /* genChkZeroes :- greater or less than comparison                 */
3899 /*     For each byte in a literal that is zero, inclusive or the   */
3900 /*     the corresponding byte in the operand with W                */
3901 /*     returns true if any of the bytes are zero                   */
3902 /*-----------------------------------------------------------------*/
3903 static int genChkZeroes(operand *op, int lit,  int size)
3904 {
3905         
3906         int i;
3907         int flag =1;
3908         
3909         while(size--) {
3910                 i = (lit >> (size*8)) & 0xff;
3911                 
3912                 if(i==0) {
3913                         if(flag) 
3914                                 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3915                         else
3916                                 emitpcode(POC_IORFW, popGet(AOP(op),size));
3917                         flag = 0;
3918                 }
3919         }
3920         
3921         return (flag==0);
3922 }
3923 #endif
3924
3925
3926 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3927 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
3928 #define DEBUGpc           emitpComment
3929
3930 /*-----------------------------------------------------------------*/
3931 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
3932 /*                  aop (if it's NOT a literal) or from lit (if    */
3933 /*                  aop is a literal)                              */
3934 /*-----------------------------------------------------------------*/
3935 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3936   if (aop->type == AOP_LIT) {
3937     emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3938   } else {
3939     emitpcode (POC_MOVFW, popGet (aop, offset));
3940   }
3941 }
3942
3943 /* genCmp performs a left < right comparison, stores
3944  * the outcome in result (if != NULL) and generates
3945  * control flow code for the ifx (if != NULL).
3946  *
3947  * This version leaves in sequences like
3948  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3949  * which should be optmized by the peephole
3950  * optimizer - RN 2005-01-01 */
3951 static void genCmp (operand *left,operand *right,
3952                     operand *result, iCode *ifx, int sign)
3953 {
3954   resolvedIfx rIfx;
3955   int size;
3956   int offs;
3957   symbol *templbl;
3958   operand *dummy;
3959   unsigned long lit;
3960   unsigned long mask;
3961   int performedLt;
3962   int invert_result = 0;
3963
3964   FENTRY;
3965   
3966   assert (AOP_SIZE(left) == AOP_SIZE(right));
3967   assert (left && right);
3968
3969   size = AOP_SIZE(right) - 1;
3970   mask = (0x100UL << (size*8)) - 1;
3971   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3972   performedLt = 1;
3973   templbl = NULL;
3974   lit = 0;
3975   
3976   resolveIfx (&rIfx, ifx);
3977
3978   /**********************************************************************
3979    * handle bits - bit compares are promoted to int compares seemingly! *
3980    **********************************************************************/
3981 #if 0
3982   // THIS IS COMPLETELY UNTESTED!
3983   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3984     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3985     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3986     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3987
3988     emitSETC;
3989     // 1 < {0,1} is false --> clear C by skipping the next instruction
3990     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3991     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3992     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3993     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3994     emitCLRC; // only skipped for left=0 && right=1
3995
3996     goto correct_result_in_carry;
3997   } // if
3998 #endif
3999
4000   /*************************************************
4001    * make sure that left is register (or the like) *
4002    *************************************************/
4003   if (!isAOP_REGlike(left)) {
4004     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4005     assert (isAOP_LIT(left));
4006     assert (isAOP_REGlike(right));
4007     // swap left and right
4008     // left < right <==> right > left <==> (right >= left + 1)
4009     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4010
4011     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4012       // MAXVALUE < right? always false
4013       if (performedLt) emitCLRC; else emitSETC;
4014       goto correct_result_in_carry;
4015     } // if
4016
4017     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4018     // that's why we handled it above.
4019     lit++;
4020
4021     dummy = left;
4022     left = right;
4023     right = dummy;
4024
4025     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4026   } else if (isAOP_LIT(right)) {
4027     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4028   } // if
4029
4030   assert (isAOP_REGlike(left)); // left must be register or the like
4031   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4032
4033   /*************************************************
4034    * special cases go here                         *
4035    *************************************************/
4036
4037   if (isAOP_LIT(right)) {
4038     if (!sign) {
4039       // unsigned comparison to a literal
4040       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4041       if (lit == 0) {
4042         // unsigned left < 0? always false
4043         if (performedLt) emitCLRC; else emitSETC;
4044         goto correct_result_in_carry;
4045       }
4046     } else {
4047       // signed comparison to a literal
4048       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4049       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4050         // signed left < 0x80000000? always false
4051         if (performedLt) emitCLRC; else emitSETC;
4052         goto correct_result_in_carry;
4053       } else if (lit == 0) {
4054         // compare left < 0; set CARRY if SIGNBIT(left) is set
4055         if (performedLt) emitSETC; else emitCLRC;
4056         emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
4057         if (performedLt) emitCLRC; else emitSETC;
4058         goto correct_result_in_carry;
4059       }
4060     } // if (!sign)
4061   } // right is literal
4062
4063   /*************************************************
4064    * perform a general case comparison             *
4065    * make sure we get CARRY==1 <==> left >= right  *
4066    *************************************************/
4067   // compare most significant bytes
4068   //DEBUGpc ("comparing bytes at offset %d", size);
4069   if (!sign) {
4070     // unsigned comparison
4071     pic14_mov2w_regOrLit (AOP(right), lit, size);
4072     emitpcode (POC_SUBFW, popGet (AOP(left), size));
4073   } else {
4074     // signed comparison
4075     // (add 2^n to both operands then perform an unsigned comparison)
4076     if (isAOP_LIT(right)) {
4077       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4078       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4079
4080       if (litbyte == 0x80) {
4081         // left >= 0x80 -- always true, but more bytes to come
4082         mov2w (AOP(left), size);
4083         emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
4084         emitSETC;
4085       } else {
4086         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4087         mov2w (AOP(left), size);
4088         emitpcode (POC_ADDLW, popGetLit (0x80));
4089         emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4090       } // if
4091     } else {
4092       pCodeOp *pctemp = popGetTempReg();
4093       mov2w (AOP(left), size);
4094       emitpcode (POC_ADDLW, popGetLit (0x80));
4095       emitpcode (POC_MOVWF, pctemp);
4096       mov2w (AOP(right), size);
4097       emitpcode (POC_ADDLW, popGetLit (0x80));
4098       emitpcode (POC_SUBFW, pctemp);
4099       popReleaseTempReg(pctemp);
4100     }
4101   } // if (!sign)
4102
4103   // compare remaining bytes (treat as unsigned case from above)
4104   templbl = newiTempLabel ( NULL );
4105   offs = size;
4106   while (offs--) {
4107     //DEBUGpc ("comparing bytes at offset %d", offs);
4108     emitSKPZ;
4109     emitpcode (POC_GOTO, popGetLabel (templbl->key));
4110     pic14_mov2w_regOrLit (AOP(right), lit, offs);
4111     emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4112   } // while (offs)
4113   emitpLabel (templbl->key);
4114   goto result_in_carry;
4115
4116 result_in_carry:
4117   
4118   /****************************************************
4119    * now CARRY contains the result of the comparison: *
4120    * SUBWF sets CARRY iff                             *
4121    * F-W >= 0 <==> F >= W <==> !(F < W)               *
4122    * (F=left, W=right)                                *
4123    ****************************************************/
4124
4125   if (performedLt) {
4126     invert_result = 1;
4127     // value will be used in the following genSkipc()
4128     rIfx.condition ^= 1;
4129   } // if
4130
4131 correct_result_in_carry:
4132
4133   // assign result to variable (if neccessary)
4134   if (result && AOP_TYPE(result) != AOP_CRY) {
4135     //DEBUGpc ("assign result");
4136     size = AOP_SIZE(result);
4137     while (size--) {
4138       emitpcode (POC_CLRF, popGet (AOP(result), size));
4139     } // while
4140     if (invert_result) {
4141       emitSKPC;
4142       emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4143     } else {
4144       emitpcode (POC_RLF, popGet (AOP(result), 0));
4145     }
4146   } // if (result)
4147
4148   // perform conditional jump
4149   if (ifx) {
4150     //DEBUGpc ("generate control flow");
4151     genSkipc (&rIfx);
4152     ifx->generated = 1;
4153   } // if
4154 }
4155
4156
4157 #if 0
4158 /* OLD VERSION -- BUGGY, DO NOT USE */
4159
4160 /*-----------------------------------------------------------------*/
4161 /* genCmp :- greater or less than comparison                       */
4162 /*-----------------------------------------------------------------*/
4163 static void genCmp (operand *left,operand *right,
4164                                         operand *result, iCode *ifx, int sign)
4165 {
4166         int size; //, offset = 0 ;
4167         unsigned long lit = 0L,i = 0;
4168         resolvedIfx rFalseIfx;
4169         //  resolvedIfx rTrueIfx;
4170         symbol *truelbl;
4171
4172         FENTRY;
4173         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4174         /*
4175         if(ifx) {
4176         DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4177         DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4178         }
4179         */
4180         
4181         resolveIfx(&rFalseIfx,ifx);
4182         truelbl  = newiTempLabel(NULL);
4183         size = max(AOP_SIZE(left),AOP_SIZE(right));
4184         
4185         DEBUGpic14_AopType(__LINE__,left,right,result);
4186         
4187 #define _swapp
4188         
4189         /* if literal is on the right then swap with left */
4190         if ((AOP_TYPE(right) == AOP_LIT)) {
4191                 operand *tmp = right ;
4192                 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4193                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4194 #ifdef _swapp
4195                 
4196                 lit = (lit - 1) & mask;
4197                 right = left;
4198                 left = tmp;
4199                 rFalseIfx.condition ^= 1;
4200 #endif
4201                 
4202         } else if ((AOP_TYPE(left) == AOP_LIT)) {
4203                 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4204         }
4205         
4206         
4207         //if(IC_TRUE(ifx) == NULL)
4208         /* if left & right are bit variables */
4209         if (AOP_TYPE(left) == AOP_CRY &&
4210                 AOP_TYPE(right) == AOP_CRY ) {
4211                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4212                 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4213         } else {
4214         /* subtract right from left if at the
4215         end the carry flag is set then we know that
4216                 left is greater than right */
4217                 
4218                 symbol *lbl  = newiTempLabel(NULL);
4219                 
4220 #ifndef _swapp
4221                 if(AOP_TYPE(right) == AOP_LIT) {
4222                         
4223                         //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4224                         
4225                         DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4226                         
4227                         /* special cases */
4228                         
4229                         if(lit == 0) {
4230                                 
4231                                 if(sign != 0) 
4232                                         genSkipCond(&rFalseIfx,left,size-1,7);
4233                                 else 
4234                                         /* no need to compare to 0...*/
4235                                         /* NOTE: this is a de-generate compare that most certainly 
4236                                         *       creates some dead code. */
4237                                         emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4238                                 
4239                                 if(ifx) ifx->generated = 1;
4240                                 return;
4241                                 
4242                         }
4243                         size--;
4244                         
4245                         if(size == 0) {
4246                                 //i = (lit >> (size*8)) & 0xff;
4247                                 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4248                                 
4249                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4250                                 
4251                                 i = ((0-lit) & 0xff);
4252                                 if(sign) {
4253                                         if( i == 0x81) { 
4254                                         /* lit is 0x7f, all signed chars are less than
4255                                                 * this except for 0x7f itself */
4256                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4257                                                 genSkipz2(&rFalseIfx,0);
4258                                         } else {
4259                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4260                                                 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4261                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4262                                         }
4263                                         
4264                                 } else {
4265                                         if(lit == 1) {
4266                                                 genSkipz2(&rFalseIfx,1);
4267                                         } else {
4268                                                 emitpcode(POC_ADDLW, popGetLit(i));
4269                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4270                                         }
4271                                 }
4272                                 
4273                                 if(ifx) ifx->generated = 1;
4274                                 return;
4275                         }
4276                         
4277                         /* chars are out of the way. now do ints and longs */
4278                         
4279                         
4280                         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4281                         
4282                         /* special cases */
4283                         
4284                         if(sign) {
4285                                 
4286                                 if(lit == 0) {
4287                                         genSkipCond(&rFalseIfx,left,size,7);
4288                                         if(ifx) ifx->generated = 1;
4289                                         return;
4290                                 }
4291                                 
4292                                 if(lit <0x100) {
4293                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4294                                         
4295                                         //rFalseIfx.condition ^= 1;
4296                                         //genSkipCond(&rFalseIfx,left,size,7);
4297                                         //rFalseIfx.condition ^= 1;
4298                                         
4299                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4300                                         if(rFalseIfx.condition)
4301                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4302                                         else
4303                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4304                                         
4305                                         emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4306                                         emitpcode(POC_ADDFW, popGet(AOP(left),0));
4307                                         emitpcode(POC_MOVFW, popGet(AOP(left),1));
4308                                         
4309                                         while(size > 1)
4310                                                 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4311                                         
4312                                         if(rFalseIfx.condition) {
4313                                                 emitSKPZ;
4314                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4315                                                 
4316                                         } else {
4317                                                 emitSKPNZ;
4318                                         }
4319                                         
4320                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4321                                         emitpLabel(truelbl->key);
4322                                         if(ifx) ifx->generated = 1;
4323                                         return;
4324                                         
4325                                 }
4326                                 
4327                                 if(size == 1) {
4328                                         
4329                                         if( (lit & 0xff) == 0) {
4330                                                 /* lower byte is zero */
4331                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4332                                                 i = ((lit >> 8) & 0xff) ^0x80;
4333                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4334                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4335                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4336                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4337                                                 
4338                                                 
4339                                                 if(ifx) ifx->generated = 1;
4340                                                 return;
4341                                                 
4342                                         }
4343                                 } else {
4344                                         /* Special cases for signed longs */
4345                                         if( (lit & 0xffffff) == 0) {
4346                                                 /* lower byte is zero */
4347                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4348                                                 i = ((lit >> 8*3) & 0xff) ^0x80;
4349                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4350                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4351                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4352                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4353                                                 
4354                                                 
4355                                                 if(ifx) ifx->generated = 1;
4356                                                 return;
4357                                                 
4358                                         }
4359                                         
4360                                 }
4361                                 
4362                                 
4363                                 if(lit & (0x80 << (size*8))) {
4364                                         /* lit is negative */
4365                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4366                                         
4367                                         //genSkipCond(&rFalseIfx,left,size,7);
4368                                         
4369                                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4370                                         
4371                                         if(rFalseIfx.condition)
4372                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4373                                         else
4374                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4375                                         
4376                                         
4377                                 } else {
4378                                         /* lit is positive */
4379                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4380                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4381                                         if(rFalseIfx.condition)
4382                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4383                                         else
4384                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4385                                         
4386                                 }
4387                                 
4388                                 /* There are no more special cases, so perform a general compare */
4389                                 
4390                                 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4391                                 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4392                                 
4393                                 while(size--) {
4394                                         
4395                                         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4396                                         emitSKPNZ;
4397                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4398                                 }
4399                                 //rFalseIfx.condition ^= 1;
4400                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4401                                 
4402                                 emitpLabel(truelbl->key);
4403                                 
4404                                 if(ifx) ifx->generated = 1;
4405                                 return;
4406                                 
4407                                 
4408                         }
4409
4410
4411                         /* sign is out of the way. So now do an unsigned compare */
4412                         DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4413
4414
4415                         /* General case - compare to an unsigned literal on the right.*/
4416
4417                         i = (lit >> (size*8)) & 0xff;
4418                         emitpcode(POC_MOVLW, popGetLit(i));
4419                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4420                         while(size--) {
4421                                 i = (lit >> (size*8)) & 0xff;
4422                                 
4423                                 if(i) {
4424                                         emitpcode(POC_MOVLW, popGetLit(i));
4425                                         emitSKPNZ;
4426                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4427                                 } else {
4428                                 /* this byte of the lit is zero, 
4429                                         *if it's not the last then OR in the variable */
4430                                         if(size)
4431                                                 emitpcode(POC_IORFW, popGet(AOP(left),size));
4432                                 }
4433                         }
4434
4435
4436                 emitpLabel(lbl->key);
4437                 //if(emitFinalCheck)
4438                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4439                 if(sign)
4440                         emitpLabel(truelbl->key);
4441
4442                 if(ifx) ifx->generated = 1;
4443                 return;
4444
4445
4446                 }
4447 #endif  // _swapp
4448
4449                 if(AOP_TYPE(left) == AOP_LIT) {
4450                         //symbol *lbl = newiTempLabel(NULL);
4451                         
4452                         //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4453                         
4454                         
4455                         DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4456                         
4457                         /* Special cases */
4458                         if((lit == 0) && (sign == 0)){
4459                                 
4460                                 size--;
4461                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4462                                 while(size) 
4463                                         emitpcode(POC_IORFW, popGet(AOP(right),--size));
4464                                 
4465                                 genSkipz2(&rFalseIfx,0);
4466                                 if(ifx) ifx->generated = 1;
4467                                 return;
4468                         }
4469                         
4470                         if(size==1) {
4471                                 /* Special cases */
4472                                 lit &= 0xff;
4473                                 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4474                                         /* degenerate compare can never be true */
4475                                         if(rFalseIfx.condition == 0)
4476                                                 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4477                                         
4478                                         if(ifx) ifx->generated = 1;
4479                                         return;
4480                                 }
4481                                 
4482                                 if(sign) {
4483                                         /* signed comparisons to a literal byte */
4484                                         
4485                                         int lp1 = (lit+1) & 0xff;
4486                                         
4487                                         DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4488                                         switch (lp1) {
4489                                         case 0:
4490                                                 rFalseIfx.condition ^= 1;
4491                                                 genSkipCond(&rFalseIfx,right,0,7);
4492                                                 break;
4493                                         case 0x7f:
4494                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4495                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4496                                                 genSkipz2(&rFalseIfx,1);
4497                                                 break;
4498                                         default:
4499                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4500                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4501                                                 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4502                                                 rFalseIfx.condition ^= 1;
4503                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4504                                                 break;
4505                                         }
4506                                         if(ifx) ifx->generated = 1;
4507                                 } else {
4508                                         /* unsigned comparisons to a literal byte */
4509                                         
4510                                         switch(lit & 0xff ) {
4511                                         case 0:
4512                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4513                                                 genSkipz2(&rFalseIfx,0);
4514                                                 if(ifx) ifx->generated = 1;
4515                                                 break;
4516                                         case 0x7f:
4517                                                 genSkipCond(&rFalseIfx,right,0,7);
4518                                                 if(ifx) ifx->generated = 1;
4519                                                 break;
4520                                                 
4521                                         default:
4522                                                 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4523                                                 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4524                                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4525                                                 rFalseIfx.condition ^= 1;
4526                                                 if (AOP_TYPE(result) == AOP_CRY) {
4527                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4528                                                         if(ifx) ifx->generated = 1;
4529                                                 } else {
4530                                                         DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4531                                                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4532                                                         emitpcode(POC_RLF, popGet(AOP(result),0));
4533                                                         emitpcode(POC_MOVLW, popGetLit(0x01));
4534                                                         emitpcode(POC_XORWF, popGet(AOP(result),0));
4535                                                 }       
4536                                                 break;
4537                                         }
4538                                 }
4539                                 
4540                                 //goto check_carry;
4541                                 return;
4542                                 
4543                         } else {
4544                                 
4545                                 /* Size is greater than 1 */
4546                                 
4547                                 if(sign) {
4548                                         int lp1 = lit+1;
4549                                         
4550                                         size--;
4551                                         
4552                                         if(lp1 == 0) {
4553                                                 /* this means lit = 0xffffffff, or -1 */
4554                                                 
4555                                                 
4556                                                 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4557                                                 rFalseIfx.condition ^= 1;
4558                                                 genSkipCond(&rFalseIfx,right,size,7);
4559                                                 if(ifx) ifx->generated = 1;
4560                                                 return;
4561                                         }
4562                                         
4563                                         if(lit == 0) {
4564                                                 int s = size;
4565                                                 
4566                                                 if(rFalseIfx.condition) {
4567                                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4568                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4569                                                 }
4570                                                 
4571                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4572                                                 while(size--)
4573                                                         emitpcode(POC_IORFW, popGet(AOP(right),size));
4574                                                 
4575                                                 
4576                                                 emitSKPZ;
4577                                                 if(rFalseIfx.condition) {
4578                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4579                                                         emitpLabel(truelbl->key);
4580                                                 }else {
4581                                                         rFalseIfx.condition ^= 1;
4582                                                         genSkipCond(&rFalseIfx,right,s,7);
4583                                                 }
4584                                                 
4585                                                 if(ifx) ifx->generated = 1;
4586                                                 return;
4587                                         }
4588                                         
4589                                         if((size == 1) &&  (0 == (lp1&0xff))) {
4590                                                 /* lower byte of signed word is zero */
4591                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4592                                                 i = ((lp1 >> 8) & 0xff) ^0x80;
4593                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4594                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4595                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4596                                                 rFalseIfx.condition ^= 1;
4597                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4598                                                 
4599                                                 
4600                                                 if(ifx) ifx->generated = 1;
4601                                                 return;
4602                                         }
4603                                         
4604                                         if(lit & (0x80 << (size*8))) {
4605                                                 /* Lit is less than zero */
4606                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4607                                                 //rFalseIfx.condition ^= 1;
4608                                                 //genSkipCond(&rFalseIfx,left,size,7);
4609                                                 //rFalseIfx.condition ^= 1;
4610                                                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4611                                                 //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4612                                                 
4613                                                 if(rFalseIfx.condition)
4614                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4615                                                 else
4616                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4617                                                 
4618                                                 
4619                                         } else {
4620                                                 /* Lit is greater than or equal to zero */
4621                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4622                                                 //rFalseIfx.condition ^= 1;
4623                                                 //genSkipCond(&rFalseIfx,right,size,7);
4624                                                 //rFalseIfx.condition ^= 1;
4625                                                 
4626                                                 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4627                                                 //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4628                                                 
4629                                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4630                                                 if(rFalseIfx.condition)
4631                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4632                                                 else
4633                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4634                                                 
4635                                         }
4636                                         
4637                                         
4638                                         emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4639                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4640                                         
4641                                         while(size--) {
4642                                                 
4643                                                 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4644                                                 emitSKPNZ;
4645                                                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4646                                         }
4647                                         rFalseIfx.condition ^= 1;
4648                                         //rFalseIfx.condition = 1;
4649                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4650                                         
4651                                         emitpLabel(truelbl->key);
4652                                         
4653                                         if(ifx) ifx->generated = 1;
4654                                         return;
4655                                         // end of if (sign)
4656                                 } else {
4657                                         
4658                                         /* compare word or long to an unsigned literal on the right.*/
4659                                         
4660                                         
4661                                         size--;
4662                                         if(lit < 0xff) {
4663                                                 DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4664                                                 switch (lit) {
4665                                                 case 0:
4666                                                         break; /* handled above */
4667                                                 /*
4668                                                 case 0xff:
4669                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4670                                                         while(size--)
4671                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4672                                                         genSkipz2(&rFalseIfx,0);
4673                                                         break;
4674                                                 */
4675                                                 default:
4676                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4677                                                         while(--size)
4678                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4679                                                         
4680                                                         emitSKPZ;
4681                                                         if(rFalseIfx.condition)
4682                                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4683                                                         else
4684                                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4685                                                         
4686                                                         
4687                                                         emitpcode(POC_MOVLW, popGetLit(lit+1));
4688                                                         emitpcode(POC_SUBFW, popGet(AOP(right),0));
4689                                                         
4690                                                         rFalseIfx.condition ^= 1;
4691                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4692                                                 }
4693                                                 
4694                                                 emitpLabel(truelbl->key);
4695                                                 
4696                                                 if(ifx) ifx->generated = 1;
4697                                                 return;
4698                                         }
4699                                         
4700                                         
4701                                         lit++;
4702                                         DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4703                                         i = (lit >> (size*8)) & 0xff;
4704                                         
4705                                         emitpcode(POC_MOVLW, popGetLit(i));
4706                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4707                                         
4708                                         while(size--) {
4709                                                 i = (lit >> (size*8)) & 0xff;
4710                                                 
4711                                                 if(i) {
4712                                                         emitpcode(POC_MOVLW, popGetLit(i));
4713                                                         emitSKPNZ;
4714                                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4715                                                 } else {
4716                                                 /* this byte of the lit is zero, 
4717                                                         *if it's not the last then OR in the variable */
4718                                                         if(size)
4719                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4720                                                 }
4721                                         }
4722                                         
4723                                         
4724                                         emitpLabel(lbl->key);
4725                                         
4726                                         rFalseIfx.condition ^= 1;
4727                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4728                                 }
4729                                 
4730                                 if(sign)
4731                                         emitpLabel(truelbl->key);
4732                                 if(ifx) ifx->generated = 1;
4733                                 return;
4734                         }
4735                 }
4736                 /* Compare two variables */
4737                 
4738                 DEBUGpic14_emitcode(";sign","%d",sign);
4739                 
4740                 size--;
4741                 if(sign) {
4742                         /* Sigh. thus sucks... */
4743                         if(size) {
4744                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4745                                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4746                                 emitpcode(POC_MOVLW, popGetLit(0x80));
4747                                 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4748                                 emitpcode(POC_XORFW, popGet(AOP(right),size));
4749                                 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4750                         } else {
4751                                 /* Signed char comparison */
4752                                 /* Special thanks to Nikolai Golovchenko for this snippet */
4753                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4754                                 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4755                                 emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4756                                 emitpcode(POC_XORFW, popGet(AOP(left),0));
4757                                 emitpcode(POC_XORFW, popGet(AOP(right),0));
4758                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4759                                 
4760                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4761                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4762                                 
4763                                 if(ifx) ifx->generated = 1;
4764                                 return;
4765                         }
4766                         
4767                 } else {
4768                         
4769                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4770                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4771                 }
4772                 
4773                 
4774                 /* The rest of the bytes of a multi-byte compare */
4775                 while (size) {
4776                         
4777                         emitSKPZ;
4778                         emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4779                         size--;
4780                         
4781                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4782                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4783                         
4784                         
4785                 }
4786                 
4787                 emitpLabel(lbl->key);
4788                 
4789                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4790                 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4791                         (AOP_TYPE(result) == AOP_REG)) {
4792                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4793                         emitpcode(POC_RLF, popGet(AOP(result),0));
4794                 } else {
4795                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4796                 }       
4797                 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4798                 if(ifx) ifx->generated = 1;
4799                 
4800                 return;
4801                 
4802         }
4803         
4804         // check_carry:
4805         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4806                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4807                 pic14_outBitC(result);
4808         } else {
4809                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4810                 /* if the result is used in the next
4811                 ifx conditional branch then generate
4812                 code a little differently */
4813                 if (ifx )
4814                         genIfxJump (ifx,"c");
4815                 else
4816                         pic14_outBitC(result);
4817                 /* leave the result in acc */
4818         }
4819         
4820 }
4821 #endif
4822
4823 /*-----------------------------------------------------------------*/
4824 /* genCmpGt :- greater than comparison                             */
4825 /*-----------------------------------------------------------------*/
4826 static void genCmpGt (iCode *ic, iCode *ifx)
4827 {
4828         operand *left, *right, *result;
4829         sym_link *letype , *retype;
4830         int sign ;
4831         
4832         FENTRY;
4833         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4834         left = IC_LEFT(ic);
4835         right= IC_RIGHT(ic);
4836         result = IC_RESULT(ic);
4837         
4838         letype = getSpec(operandType(left));
4839         retype =getSpec(operandType(right));
4840         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4841         /* assign the amsops */
4842         aopOp (left,ic,FALSE);
4843         aopOp (right,ic,FALSE);
4844         aopOp (result,ic,TRUE);
4845         
4846         genCmp(right, left, result, ifx, sign);
4847         
4848         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4849         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4850         freeAsmop(result,NULL,ic,TRUE); 
4851 }
4852
4853 /*-----------------------------------------------------------------*/
4854 /* genCmpLt - less than comparisons                                */
4855 /*-----------------------------------------------------------------*/
4856 static void genCmpLt (iCode *ic, iCode *ifx)
4857 {
4858         operand *left, *right, *result;
4859         sym_link *letype , *retype;
4860         int sign ;
4861         
4862         FENTRY;
4863         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4864         left = IC_LEFT(ic);
4865         right= IC_RIGHT(ic);
4866         result = IC_RESULT(ic);
4867         
4868         letype = getSpec(operandType(left));
4869         retype =getSpec(operandType(right));
4870         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4871         
4872         /* assign the amsops */
4873         aopOp (left,ic,FALSE);
4874         aopOp (right,ic,FALSE);
4875         aopOp (result,ic,TRUE);
4876         
4877         genCmp(left, right, result, ifx, sign);
4878         
4879         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4880         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4881         freeAsmop(result,NULL,ic,TRUE); 
4882 }
4883
4884 #if 0
4885 /*-----------------------------------------------------------------*/
4886 /* genc16bit2lit - compare a 16 bit value to a literal             */
4887 /*-----------------------------------------------------------------*/
4888 static void genc16bit2lit(operand *op, int lit, int offset)
4889 {
4890         int i;
4891         
4892         FENTRY;
4893         DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4894         if( (lit&0xff) == 0) 
4895                 i=1;
4896         else
4897                 i=0;
4898         
4899         switch( BYTEofLONG(lit,i)) { 
4900         case 0:
4901                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4902                 break;
4903         case 1:
4904                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4905                 break;
4906         case 0xff:
4907                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4908                 break;
4909         default:
4910                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4911                 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4912         }
4913         
4914         i ^= 1;
4915         
4916         switch( BYTEofLONG(lit,i)) { 
4917         case 0:
4918                 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4919                 break;
4920         case 1:
4921                 emitSKPNZ;
4922                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4923                 break;
4924         case 0xff:
4925                 emitSKPNZ;
4926                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4927                 break;
4928         default:
4929                 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4930                 emitSKPNZ;
4931                 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4932                 
4933         }
4934         
4935 }
4936 #endif
4937
4938 #if 0
4939 /*-----------------------------------------------------------------*/
4940 /* gencjneshort - compare and jump if not equal                    */
4941 /*-----------------------------------------------------------------*/
4942 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4943 {
4944         int size = min(AOP_SIZE(left),AOP_SIZE(right));
4945         int offset = 0;
4946         //resolvedIfx rIfx;
4947         symbol *lbl;
4948         
4949         //unsigned long lit = 0L;
4950         FENTRY;
4951         if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4952           emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4953           return;
4954         }
4955         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4956         DEBUGpic14_AopType(__LINE__,left,right,result);
4957         
4958         assert (!pic14_sameRegs (AOP(left), AOP(result)));
4959         assert (!pic14_sameRegs (AOP(right), AOP(result)));
4960         if (AOP_SIZE(result)) {
4961           for (offset = 0; offset < AOP_SIZE(result); offset++)
4962             emitpcode (POC_CLRF, popGet (AOP(result), offset));
4963         }
4964         
4965         assert (AOP_SIZE(left) == AOP_SIZE(right));
4966         //resolveIfx(&rIfx,ifx);
4967         lbl = newiTempLabel (NULL);
4968         while (size--)
4969         {
4970           mov2w (AOP(right),size);
4971           emitpcode (POC_XORFW, popGet (AOP(left), size));
4972           if (size)
4973           {
4974             emitSKPZ;
4975             emitpcode (POC_GOTO, popGetLabel (lbl->key));
4976           }
4977         } // while
4978         emitpLabel (lbl->key);
4979         if (AOP_SIZE(result)) {
4980           emitSKPNZ;
4981           emitpcode (POC_INCF, popGet (AOP(result), 0));
4982         } else {
4983           assert (ifx);
4984           genSkipz (ifx, NULL != IC_TRUE(ifx));
4985           ifx->generated = 1;
4986         }
4987         return;
4988 #if 0   
4989         if(result)
4990         {
4991                 DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4992                 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4993                 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4994                 for (offset=0; offset < AOP_SIZE(result); offset++)
4995                 {
4996                         emitpcode (POC_CLRF, popGet (AOP(result), offset));
4997                 } // for offset
4998         }
4999         
5000         
5001         /* if the left side is a literal or 
5002         if the right is in a pointer register and left 
5003         is not */
5004         if ((AOP_TYPE(left) == AOP_LIT) || 
5005                 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5006                 operand *t = right;
5007                 right = left;
5008                 left = t;
5009         }
5010         if(AOP_TYPE(right) == AOP_LIT)
5011                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5012         
5013         /* if the right side is a literal then anything goes */
5014         if (AOP_TYPE(right) == AOP_LIT &&
5015                 AOP_TYPE(left) != AOP_DIR ) {
5016                 switch(size) {
5017                 case 2:
5018                         genc16bit2lit(left, lit, 0);
5019                         emitSKPNZ;
5020                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
5021                         break;
5022                 default:
5023                         offset = 0;
5024                         while (size--) {
5025                                 if(lit & 0xff) {
5026                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5027                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5028                                 } else {
5029                                         emitpcode(POC_MOVF,popGet(AOP(left),offset));
5030                                 }
5031                                 
5032                                 emitSKPNZ;
5033                                 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5034                                 offset++;
5035                                 lit >>= 8;
5036                         }
5037                         break;
5038                 }
5039         }
5040         
5041         /* if the right side is in a register or in direct space or
5042         if the left is a pointer register & right is not */    
5043         else if (AOP_TYPE(right) == AOP_REG ||
5044                 AOP_TYPE(right) == AOP_DIR || 
5045                 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5046                 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5047                 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5048                 int lbl_key = lbl->key;
5049                 
5050                 if(!result) {
5051                         DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5052                         fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5053                                 __FUNCTION__,__LINE__);
5054                         return;
5055                 }
5056                 
5057                 /*     switch(size) { */
5058                 /*     case 2: */
5059                 /*       genc16bit2lit(left, lit, 0); */
5060                 /*       emitSKPNZ; */
5061                 /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
5062                 /*       break; */
5063                 /*     default: */
5064                 offset = 0;
5065                 while (size--) {
5066                         int emit_skip=1;
5067                         if((AOP_TYPE(left) == AOP_DIR) && 
5068                                 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5069                                 
5070                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5071                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5072                                 
5073                         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5074                                 
5075                                 switch (lit & 0xff) {
5076                                 case 0:
5077                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5078                                         break;
5079                                 case 1:
5080                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5081                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5082                                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
5083                                         emit_skip=0;
5084                                         break;
5085                                 case 0xff:
5086                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5087                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5088                                         //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5089                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5090                                         emit_skip=0;
5091                                         break;
5092                                 default:
5093                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5094                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5095                                 }
5096                                 lit >>= 8;
5097                                 
5098                         } else {
5099                                 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5100                         }
5101                         if(emit_skip) {
5102                                 if(AOP_TYPE(result) == AOP_CRY) {
5103                                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5104                                         if(rIfx.condition)
5105                                                 emitSKPNZ;
5106                                         else
5107                                                 emitSKPZ;
5108                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5109                                 } else {
5110                                         /* fix me. probably need to check result size too */
5111                                         //emitpcode(POC_CLRF,popGet(AOP(result),0));
5112                                         if(rIfx.condition)
5113                                                 emitSKPZ;
5114                                         else
5115                                                 emitSKPNZ;
5116                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5117                                 }
5118                                 if(ifx)
5119                                         ifx->generated=1;
5120                         }
5121                         emit_skip++;
5122                         offset++;
5123                 }
5124                 /*       break; */
5125                 /*     } */
5126         } else if(AOP_TYPE(right) == AOP_REG &&
5127                 AOP_TYPE(left) != AOP_DIR){
5128
5129                 offset = 0;
5130                 while(size--) {
5131                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5132                         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5133                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5134                         if(rIfx.condition)
5135                                 emitSKPNZ;
5136                         else
5137                                 emitSKPZ;
5138                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5139                         offset++;
5140                 }
5141                 
5142         }else{
5143                 /* right is a pointer reg need both a & b */
5144                 offset = 0;
5145                 while(size--) {
5146                         char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5147                         if(strcmp(l,"b"))
5148                                 pic14_emitcode("mov","b,%s",l);
5149                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5150                         pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5151                         offset++;
5152                 }
5153         }
5154         
5155         emitpcode(POC_INCF,popGet(AOP(result),0));
5156         if(!rIfx.condition)
5157                 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5158         
5159         emitpLabel(lbl->key);
5160         
5161         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5162         
5163         if(ifx)
5164                 ifx->generated = 1;
5165 #endif
5166 }
5167 #endif
5168
5169 #if 0
5170 /*-----------------------------------------------------------------*/
5171 /* gencjne - compare and jump if not equal                         */
5172 /*-----------------------------------------------------------------*/
5173 static void gencjne(operand *left, operand *right, iCode *ifx)
5174 {
5175         symbol *tlbl  = newiTempLabel(NULL);
5176         
5177         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5178         gencjneshort(left, right, lbl);
5179         
5180         pic14_emitcode("mov","a,%s",one);
5181         pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5182         pic14_emitcode("","%05d_DS_:",lbl->key+100);
5183         pic14_emitcode("clr","a");
5184         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5185         
5186         emitpLabel(lbl->key);
5187         emitpLabel(tlbl->key);
5188         
5189 }
5190 #endif
5191
5192 /*-----------------------------------------------------------------*/
5193 /* genCmpEq - generates code for equal to                          */
5194 /*-----------------------------------------------------------------*/
5195 static void genCmpEq (iCode *ic, iCode *ifx)
5196 {
5197   operand *left, *right, *result;
5198   int size;
5199   symbol *false_label;
5200
5201   FENTRY;
5202   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5203
5204   if(ifx)
5205     DEBUGpic14_emitcode ("; ifx is non-null","");
5206   else
5207     DEBUGpic14_emitcode ("; ifx is null","");
5208
5209   aopOp((left=IC_LEFT(ic)),ic,FALSE);
5210   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5211   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5212
5213   DEBUGpic14_AopType(__LINE__,left,right,result);
5214
5215   /* if literal, move literal to right */ 
5216   if (op_isLitLike (IC_LEFT(ic))) {
5217     operand *tmp = right ;
5218     right = left;
5219     left = tmp;
5220   }
5221
5222   false_label = NULL;
5223   if (ifx && !IC_TRUE(ifx))
5224   {
5225     assert (IC_FALSE(ifx));
5226     false_label = IC_FALSE(ifx);
5227   }
5228
5229   size = min(AOP_SIZE(left),AOP_SIZE(right));
5230   assert(!pic14_sameRegs(AOP(result),AOP(left)));
5231   assert(!pic14_sameRegs(AOP(result),AOP(right)));
5232
5233   /* assume left != right */
5234   {
5235     int i;
5236     for (i=0; i < AOP_SIZE(result); i++)
5237     {
5238       emitpcode(POC_CLRF, popGet(AOP(result),i));
5239     }
5240   }
5241
5242   if (AOP_TYPE(right) == AOP_LIT)
5243   {
5244     unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5245     int i;
5246     size = AOP_SIZE(left);
5247     assert(!op_isLitLike(left));
5248
5249     switch (lit)
5250     {
5251       case 0:
5252         mov2w(AOP(left), 0);
5253         for (i=1; i < size; i++)
5254           emitpcode(POC_IORFW,popGet(AOP(left),i));
5255         /* now Z is set iff `left == right' */
5256         emitSKPZ;
5257         if (!false_label) false_label = newiTempLabel(NULL);
5258         emitpcode(POC_GOTO, popGetLabel(false_label->key));
5259         break;
5260
5261       default:
5262         for (i=0; i < size; i++)
5263         {
5264           mov2w(AOP(left),i);
5265           emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5266           /* now Z is cleared if `left != right' */
5267           emitSKPZ;
5268           if (!false_label) false_label = newiTempLabel(NULL);
5269           emitpcode(POC_GOTO, popGetLabel(false_label->key));
5270         } // for i
5271         break;
5272     } // switch (lit)
5273   }
5274   else
5275   {
5276     /* right is no literal */
5277     int i;
5278
5279     for (i=0; i < size; i++)
5280     {
5281       mov2w(AOP(right),i);
5282       emitpcode(POC_XORFW,popGet(AOP(left),i));
5283       /* now Z is cleared if `left != right' */
5284       emitSKPZ;
5285       if (!false_label) false_label = newiTempLabel(NULL);
5286       emitpcode(POC_GOTO, popGetLabel(false_label->key));
5287     } // for i
5288   }
5289
5290   /* if we reach here, left == right */
5291
5292   if (AOP_SIZE(result) > 0)
5293   {
5294     emitpcode(POC_INCF, popGet(AOP(result),0));
5295   }
5296
5297   if (ifx && IC_TRUE(ifx))
5298   {
5299     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5300   }
5301
5302   if (false_label && (!ifx || IC_TRUE(ifx)))
5303     emitpLabel(false_label->key);
5304
5305   if (ifx) ifx->generated = 1;
5306
5307   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5308   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5309   freeAsmop(result,NULL,ic,TRUE);
5310 }
5311
5312 /*-----------------------------------------------------------------*/
5313 /* ifxForOp - returns the icode containing the ifx for operand     */
5314 /*-----------------------------------------------------------------*/
5315 static iCode *ifxForOp ( operand *op, iCode *ic )
5316 {
5317         FENTRY;
5318         /* if true symbol then needs to be assigned */
5319         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5320         if (IS_TRUE_SYMOP(op))
5321                 return NULL ;
5322         
5323         /* if this has register type condition and
5324         the next instruction is ifx with the same operand
5325         and live to of the operand is upto the ifx only then */
5326         if (ic->next &&
5327                 ic->next->op == IFX &&
5328                 IC_COND(ic->next)->key == op->key &&
5329                 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5330                 return ic->next;
5331         
5332         if (ic->next &&
5333                 ic->next->op == IFX &&
5334                 IC_COND(ic->next)->key == op->key) {
5335                 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5336                 return ic->next;
5337         }
5338         
5339         DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5340         if (ic->next &&
5341                 ic->next->op == IFX)
5342                 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5343         
5344         if (ic->next &&
5345                 ic->next->op == IFX &&
5346                 IC_COND(ic->next)->key == op->key) {
5347                 DEBUGpic14_emitcode ("; "," key is okay");
5348                 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5349                         OP_SYMBOL(op)->liveTo,
5350                         ic->next->seq);
5351         }
5352         
5353         
5354         return NULL;
5355 }
5356 /*-----------------------------------------------------------------*/
5357 /* genAndOp - for && operation                                     */
5358 /*-----------------------------------------------------------------*/
5359 static void genAndOp (iCode *ic)
5360 {
5361         operand *left,*right, *result;
5362         /*     symbol *tlbl; */
5363         
5364         FENTRY;
5365         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5366         /* note here that && operations that are in an
5367         if statement are taken away by backPatchLabels
5368         only those used in arthmetic operations remain */
5369         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5370         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5371         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5372         
5373         DEBUGpic14_AopType(__LINE__,left,right,result);
5374         
5375         emitpcode(POC_MOVFW,popGet(AOP(left),0));
5376         emitpcode(POC_ANDFW,popGet(AOP(right),0));
5377         emitpcode(POC_MOVWF,popGet(AOP(result),0));
5378         
5379         /* if both are bit variables */
5380         /*     if (AOP_TYPE(left) == AOP_CRY && */
5381         /*         AOP_TYPE(right) == AOP_CRY ) { */
5382         /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5383         /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5384         /*         pic14_outBitC(result); */
5385         /*     } else { */
5386         /*         tlbl = newiTempLabel(NULL); */
5387         /*         pic14_toBoolean(left);     */
5388         /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5389         /*         pic14_toBoolean(right); */
5390         /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5391         /*         pic14_outBitAcc(result); */
5392         /*     } */
5393         
5394         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5395         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5396         freeAsmop(result,NULL,ic,TRUE);
5397 }
5398
5399
5400 /*-----------------------------------------------------------------*/
5401 /* genOrOp - for || operation                                      */
5402 /*-----------------------------------------------------------------*/
5403 /*
5404 tsd pic port -
5405 modified this code, but it doesn't appear to ever get called
5406 */
5407
5408 static void genOrOp (iCode *ic)
5409 {
5410         operand *left,*right, *result;
5411         symbol *tlbl;
5412         int i;
5413         
5414         /* note here that || operations that are in an
5415         if statement are taken away by backPatchLabels
5416         only those used in arthmetic operations remain */
5417         FENTRY;
5418         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5419         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5420         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5421         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5422         
5423         DEBUGpic14_AopType(__LINE__,left,right,result);
5424
5425         for (i=0; i < AOP_SIZE(result); i++)
5426         {
5427                 emitpcode(POC_CLRF, popGet(AOP(result), i));
5428         } // for i
5429
5430         tlbl = newiTempLabel(NULL);
5431         pic14_toBoolean(left);
5432         emitSKPZ;
5433         emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5434         pic14_toBoolean(right);
5435         emitpLabel(tlbl->key);
5436         /* here Z is clear IFF `left || right' */
5437         emitSKPZ;
5438         emitpcode(POC_INCF, popGet(AOP(result), 0));
5439         
5440         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5441         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5442         freeAsmop(result,NULL,ic,TRUE);            
5443 }
5444
5445 /*-----------------------------------------------------------------*/
5446 /* isLiteralBit - test if lit == 2^n                               */
5447 /*-----------------------------------------------------------------*/
5448 static int isLiteralBit(unsigned long lit)
5449 {
5450         unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5451                 0x100L,0x200L,0x400L,0x800L,
5452                 0x1000L,0x2000L,0x4000L,0x8000L,
5453                 0x10000L,0x20000L,0x40000L,0x80000L,
5454                 0x100000L,0x200000L,0x400000L,0x800000L,
5455                 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5456                 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5457         int idx;
5458         
5459         FENTRY;
5460         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5461         for(idx = 0; idx < 32; idx++)
5462                 if(lit == pw[idx])
5463                         return idx+1;
5464                 return 0;
5465 }
5466
5467 /*-----------------------------------------------------------------*/
5468 /* continueIfTrue -                                                */
5469 /*-----------------------------------------------------------------*/
5470 static void continueIfTrue (iCode *ic)
5471 {
5472         FENTRY;
5473         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5474         if(IC_TRUE(ic))
5475                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5476         ic->generated = 1;
5477 }
5478
5479 /*-----------------------------------------------------------------*/
5480 /* jmpIfTrue -                                                     */
5481 /*-----------------------------------------------------------------*/
5482 static void jumpIfTrue (iCode *ic)
5483 {
5484         FENTRY;
5485         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5486         if(!IC_TRUE(ic))
5487                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5488         ic->generated = 1;
5489 }
5490
5491 /*-----------------------------------------------------------------*/
5492 /* jmpTrueOrFalse -                                                */
5493 /*-----------------------------------------------------------------*/
5494 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5495 {
5496         FENTRY;
5497         // ugly but optimized by peephole
5498         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5499         if(IC_TRUE(ic)){
5500                 symbol *nlbl = newiTempLabel(NULL);
5501                 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5502                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5503                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5504                 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5505         }
5506         else{
5507                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5508                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5509         }
5510         ic->generated = 1;
5511 }
5512
5513 /*-----------------------------------------------------------------*/
5514 /* genAnd  - code for and                                          */
5515 /*-----------------------------------------------------------------*/
5516 static void genAnd (iCode *ic, iCode *ifx)
5517 {
5518         operand *left, *right, *result;
5519         int size, offset=0;  
5520         unsigned long lit = 0L;
5521         int bytelit = 0;
5522         resolvedIfx rIfx;
5523         
5524         FENTRY;
5525         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5526         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5527         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5528         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5529         
5530         resolveIfx(&rIfx,ifx);
5531         
5532         /* if left is a literal & right is not then exchange them */
5533         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5534                 AOP_NEEDSACC(left)) {
5535                 operand *tmp = right ;
5536                 right = left;
5537                 left = tmp;
5538         }
5539         
5540         /* if result = right then exchange them */
5541         if(pic14_sameRegs(AOP(result),AOP(right))){
5542                 operand *tmp = right ;
5543                 right = left;
5544                 left = tmp;
5545         }
5546         
5547         /* if right is bit then exchange them */
5548         if (AOP_TYPE(right) == AOP_CRY &&
5549                 AOP_TYPE(left) != AOP_CRY){
5550                 operand *tmp = right ;
5551                 right = left;
5552                 left = tmp;
5553         }
5554         if(AOP_TYPE(right) == AOP_LIT)
5555                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5556         
5557         size = AOP_SIZE(result);
5558         
5559         DEBUGpic14_AopType(__LINE__,left,right,result);
5560         
5561         // if(bit & yy)
5562         // result = bit & yy;
5563         if (AOP_TYPE(left) == AOP_CRY){
5564                 // c = bit & literal;
5565                 if(AOP_TYPE(right) == AOP_LIT){
5566                         if(lit & 1) {
5567                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5568                                         // no change
5569                                         goto release;
5570                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5571                         } else {
5572                                 // bit(result) = 0;
5573                                 if(size && (AOP_TYPE(result) == AOP_CRY)){
5574                                         pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5575                                         goto release;
5576                                 }
5577                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5578                                         jumpIfTrue(ifx);
5579                                         goto release;
5580                                 }
5581                                 pic14_emitcode("clr","c");
5582                         }
5583                 } else {
5584                         if (AOP_TYPE(right) == AOP_CRY){
5585                                 // c = bit & bit;
5586                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5587                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5588                         } else {
5589                                 // c = bit & val;
5590                                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5591                                 // c = lsb
5592                                 pic14_emitcode("rrc","a");
5593                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5594                         }
5595                 }
5596                 // bit = c
5597                 // val = c
5598                 if(size)
5599                         pic14_outBitC(result);
5600                 // if(bit & ...)
5601                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5602                         genIfxJump(ifx, "c");           
5603                 goto release ;
5604         }
5605         
5606         // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5607         // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5608         if((AOP_TYPE(right) == AOP_LIT) &&
5609                 (AOP_TYPE(result) == AOP_CRY) &&
5610                 (AOP_TYPE(left) != AOP_CRY)){
5611                 int posbit = isLiteralBit(lit);
5612                 /* left &  2^n */
5613                 if(posbit){
5614                         posbit--;
5615                         //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5616                         // bit = left & 2^n
5617                         if(size)
5618                                 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5619                         // if(left &  2^n)
5620                         else{
5621                                 if(ifx){
5622                                         int offset = 0;
5623                                         while (posbit > 7) {
5624                                                 posbit -= 8;
5625                                                 offset++;
5626                                         }
5627                                         emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5628                                                 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5629                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5630                                         
5631                                         ifx->generated = 1;
5632                                 }
5633                                 goto release;
5634                         }
5635                 } else {
5636                         symbol *tlbl = newiTempLabel(NULL);
5637                         int sizel = AOP_SIZE(left);
5638                         if(size)
5639                                 pic14_emitcode("setb","c");
5640                         while(sizel--){
5641                                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5642                                         MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5643                                         // byte ==  2^n ?
5644                                         if((posbit = isLiteralBit(bytelit)) != 0)
5645                                                 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5646                                         else{
5647                                                 if(bytelit != 0x0FFL)
5648                                                         pic14_emitcode("anl","a,%s",
5649                                                         aopGet(AOP(right),offset,FALSE,TRUE));
5650                                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5651                                         }
5652                                 }
5653                                 offset++;
5654                         }
5655                         // bit = left & literal
5656                         if(size){
5657                                 pic14_emitcode("clr","c");
5658                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5659                         }
5660                         // if(left & literal)
5661                         else{
5662                                 if(ifx)
5663                                         jmpTrueOrFalse(ifx, tlbl);
5664                                 goto release ;
5665                         }
5666                 }
5667                 pic14_outBitC(result);
5668                 goto release ;
5669         }
5670         
5671         /* if left is same as result */
5672         if(pic14_sameRegs(AOP(result),AOP(left))){
5673                 int know_W = -1;
5674                 for(;size--; offset++,lit>>=8) {
5675                         if(AOP_TYPE(right) == AOP_LIT){
5676                                 switch(lit & 0xff) {
5677                                 case 0x00:
5678                                         /*  and'ing with 0 has clears the result */
5679                                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
5680                                         break;
5681                                 case 0xff:
5682                                         /* and'ing with 0xff is a nop when the result and left are the same */
5683                                         break;
5684                                         
5685                                 default:
5686                                         {
5687                                                 int p = my_powof2( (~lit) & 0xff );
5688                                                 if(p>=0) {
5689                                                         /* only one bit is set in the literal, so use a bcf instruction */
5690                                                         emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5691                                                         
5692                                                 } else {
5693                                                         if(know_W != (int)(lit&0xff))
5694                                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5695                                                         know_W = lit &0xff;
5696                                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5697                                                 }
5698                                         }    
5699                                 }
5700                         } else {
5701                                 if (AOP_TYPE(left) == AOP_ACC) {
5702                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5703                                 } else {        
5704                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5705                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5706                                         
5707                                 }
5708                         }
5709                 }
5710                 
5711         } else {
5712                 // left & result in different registers
5713                 if(AOP_TYPE(result) == AOP_CRY){
5714                         // result = bit
5715                         // if(size), result in bit
5716                         // if(!size && ifx), conditional oper: if(left & right)
5717                         symbol *tlbl = newiTempLabel(NULL);
5718                         int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5719                         if(size)
5720                                 pic14_emitcode("setb","c");
5721                         while(sizer--){
5722                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5723                                 pic14_emitcode("anl","a,%s",
5724                                         aopGet(AOP(left),offset,FALSE,FALSE));
5725                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5726                                 offset++;
5727                         }
5728                         if(size){
5729                                 CLRC;
5730                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5731                                 pic14_outBitC(result);
5732                         } else if(ifx)
5733                                 jmpTrueOrFalse(ifx, tlbl);
5734                 } else {
5735                         for(;(size--);offset++) {
5736                                 // normal case
5737                                 // result = left & right
5738                                 if(AOP_TYPE(right) == AOP_LIT){
5739                                         int t = (lit >> (offset*8)) & 0x0FFL;
5740                                         switch(t) { 
5741                                         case 0x00:
5742                                                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5743                                                 break;
5744                                         case 0xff:
5745                                                 if(AOP_TYPE(left) != AOP_ACC) {
5746                                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5747                                                 }
5748                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5749                                                 break;
5750                                         default:
5751                                                 if(AOP_TYPE(left) == AOP_ACC) {
5752                                                         emitpcode(POC_ANDLW, popGetLit(t));
5753                                                 } else {
5754                                                         emitpcode(POC_MOVLW, popGetLit(t));
5755                                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5756                                                 }
5757                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5758                                         }
5759                                         continue;
5760                                 }
5761                                 
5762                                 if (AOP_TYPE(left) == AOP_ACC) {
5763                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5764                                 } else {
5765                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5766                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5767                                 }
5768                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5769                         }
5770                 }
5771         }
5772         
5773 release :
5774         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5775         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5776         freeAsmop(result,NULL,ic,TRUE);     
5777 }
5778
5779 /*-----------------------------------------------------------------*/
5780 /* genOr  - code for or                                            */
5781 /*-----------------------------------------------------------------*/
5782 static void genOr (iCode *ic, iCode *ifx)
5783 {
5784         operand *left, *right, *result;
5785         int size, offset=0;
5786         unsigned long lit = 0L;
5787         
5788         FENTRY;
5789         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5790         
5791         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5792         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5793         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5794         
5795         DEBUGpic14_AopType(__LINE__,left,right,result);
5796         
5797         /* if left is a literal & right is not then exchange them */
5798         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5799                 AOP_NEEDSACC(left)) {
5800                 operand *tmp = right ;
5801                 right = left;
5802                 left = tmp;
5803         }
5804         
5805         /* if result = right then exchange them */
5806         if(pic14_sameRegs(AOP(result),AOP(right))){
5807                 operand *tmp = right ;
5808                 right = left;
5809                 left = tmp;
5810         }
5811         
5812         /* if right is bit then exchange them */
5813         if (AOP_TYPE(right) == AOP_CRY &&
5814                 AOP_TYPE(left) != AOP_CRY){
5815                 operand *tmp = right ;
5816                 right = left;
5817                 left = tmp;
5818         }
5819         
5820         DEBUGpic14_AopType(__LINE__,left,right,result);
5821         
5822         if(AOP_TYPE(right) == AOP_LIT)
5823                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5824         
5825         size = AOP_SIZE(result);
5826         
5827         // if(bit | yy)
5828         // xx = bit | yy;
5829         if (AOP_TYPE(left) == AOP_CRY){
5830                 if(AOP_TYPE(right) == AOP_LIT){
5831                         // c = bit & literal;
5832                         if(lit){
5833                                 // lit != 0 => result = 1
5834                                 if(AOP_TYPE(result) == AOP_CRY){
5835                                         if(size)
5836                                                 emitpcode(POC_BSF, popGet(AOP(result),0));
5837                                         //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5838                                         //   AOP(result)->aopu.aop_dir,
5839                                         //   AOP(result)->aopu.aop_dir);
5840                                         else if(ifx)
5841                                                 continueIfTrue(ifx);
5842                                         goto release;
5843                                 }
5844                         } else {
5845                                 // lit == 0 => result = left
5846                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5847                                         goto release;
5848                                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5849                         }
5850                 } else {
5851                         if (AOP_TYPE(right) == AOP_CRY){
5852                                 if(pic14_sameRegs(AOP(result),AOP(left))){
5853                                         // c = bit | bit;
5854                                         emitpcode(POC_BCF,   popGet(AOP(result),0));
5855                                         emitpcode(POC_BTFSC, popGet(AOP(right),0));
5856                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5857                                         
5858                                         pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5859                                                 AOP(result)->aopu.aop_dir,
5860                                                 AOP(result)->aopu.aop_dir);
5861                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5862                                                 AOP(right)->aopu.aop_dir,
5863                                                 AOP(right)->aopu.aop_dir);
5864                                         pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5865                                                 AOP(result)->aopu.aop_dir,
5866                                                 AOP(result)->aopu.aop_dir);
5867                                 } else {
5868                                         if( AOP_TYPE(result) == AOP_ACC) {
5869                                                 emitpcode(POC_MOVLW, popGetLit(0));
5870                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5871                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5872                                                 emitpcode(POC_MOVLW, popGetLit(1));
5873                                                 
5874                                         } else {
5875                                                 
5876                                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5877                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5878                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5879                                                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5880                                                 
5881                                                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5882                                                         AOP(result)->aopu.aop_dir,
5883                                                         AOP(result)->aopu.aop_dir);
5884                                                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5885                                                         AOP(right)->aopu.aop_dir,
5886                                                         AOP(right)->aopu.aop_dir);
5887                                                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5888                                                         AOP(left)->aopu.aop_dir,
5889                                                         AOP(left)->aopu.aop_dir);
5890                                                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5891                                                         AOP(result)->aopu.aop_dir,
5892                                                         AOP(result)->aopu.aop_dir);
5893                                         }
5894                                 }
5895                         } else {
5896                                 // c = bit | val;
5897                                 symbol *tlbl = newiTempLabel(NULL);
5898                                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5899                                 
5900                                 
5901                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5902                                 if( AOP_TYPE(right) == AOP_ACC) {
5903                                         emitpcode(POC_IORLW, popGetLit(0));
5904                                         emitSKPNZ;
5905                                         emitpcode(POC_BTFSC, popGet(AOP(left),0));
5906                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5907                                 }
5908                                 
5909                                 
5910                                 
5911                                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5912                                         pic14_emitcode(";XXX setb","c");
5913                                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5914                                         AOP(left)->aopu.aop_dir,tlbl->key+100);
5915                                 pic14_toBoolean(right);
5916                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5917                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5918                                         jmpTrueOrFalse(ifx, tlbl);
5919                                         goto release;
5920                                 } else {
5921                                         CLRC;
5922                                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5923                                 }
5924                         }
5925                 }
5926                 // bit = c
5927                 // val = c
5928                 if(size)
5929                         pic14_outBitC(result);
5930                 // if(bit | ...)
5931                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5932                         genIfxJump(ifx, "c");           
5933                 goto release ;
5934         }
5935
5936         // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5937         // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5938         if((AOP_TYPE(right) == AOP_LIT) &&
5939           (AOP_TYPE(result) == AOP_CRY) &&
5940           (AOP_TYPE(left) != AOP_CRY)){
5941                 if(lit){
5942                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5943                         // result = 1
5944                         if(size)
5945                                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5946                         else 
5947                                 continueIfTrue(ifx);
5948                         goto release;
5949                 } else {
5950                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5951                         // lit = 0, result = boolean(left)
5952                         if(size)
5953                                 pic14_emitcode(";XXX setb","c");
5954                         pic14_toBoolean(right);
5955                         if(size){
5956                                 symbol *tlbl = newiTempLabel(NULL);
5957                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5958                                 CLRC;
5959                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5960                         } else {
5961                                 genIfxJump (ifx,"a");
5962                                 goto release;
5963                         }
5964                 }
5965                 pic14_outBitC(result);
5966                 goto release ;
5967         }
5968
5969         /* if left is same as result */
5970         if(pic14_sameRegs(AOP(result),AOP(left))){
5971                 int know_W = -1;
5972                 for(;size--; offset++,lit>>=8) {
5973                         if(AOP_TYPE(right) == AOP_LIT){
5974                                 if((lit & 0xff) == 0)
5975                                         /*  or'ing with 0 has no effect */
5976                                         continue;
5977                                 else {
5978                                         int p = my_powof2(lit & 0xff);
5979                                         if(p>=0) {
5980                                                 /* only one bit is set in the literal, so use a bsf instruction */
5981                                                 emitpcode(POC_BSF,
5982                                                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5983                                         } else {
5984                                                 if(know_W != (int)(lit & 0xff))
5985                                                         emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5986                                                 know_W = lit & 0xff;
5987                                                 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5988                                         }
5989                                         
5990                                 }
5991                         } else {
5992                                 if (AOP_TYPE(left) == AOP_ACC) {
5993                                         emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5994                                         pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5995                                 } else {        
5996                                         emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5997                                         emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5998                                         
5999                                         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6000                                         pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
6001                                         
6002                                 }
6003                         }
6004                 }
6005         } else {
6006                 // left & result in different registers
6007                 if(AOP_TYPE(result) == AOP_CRY){
6008                         // result = bit
6009                         // if(size), result in bit
6010                         // if(!size && ifx), conditional oper: if(left | right)
6011                         symbol *tlbl = newiTempLabel(NULL);
6012                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6013                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6014                         
6015                         
6016                         if(size)
6017                                 pic14_emitcode(";XXX setb","c");
6018                         while(sizer--){
6019                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6020                                 pic14_emitcode(";XXX orl","a,%s",
6021                                         aopGet(AOP(left),offset,FALSE,FALSE));
6022                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6023                                 offset++;
6024                         }
6025                         if(size){
6026                                 CLRC;
6027                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6028                                 pic14_outBitC(result);
6029                         } else if(ifx)
6030                                 jmpTrueOrFalse(ifx, tlbl);
6031                 } else for(;(size--);offset++){
6032                         // normal case
6033                         // result = left | right
6034                         if(AOP_TYPE(right) == AOP_LIT){
6035                                 int t = (lit >> (offset*8)) & 0x0FFL;
6036                                 switch(t) { 
6037                                 case 0x00:
6038                                         if (AOP_TYPE(left) != AOP_ACC) {
6039                                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
6040                                         }
6041                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6042                                         
6043                                         break;
6044                                 default:
6045                                         if (AOP_TYPE(left) == AOP_ACC) {
6046                                                 emitpcode(POC_IORLW,  popGetLit(t));
6047                                         } else {
6048                                                 emitpcode(POC_MOVLW,  popGetLit(t));
6049                                                 emitpcode(POC_IORFW,  popGet(AOP(left),offset));
6050                                         }
6051                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));        
6052                                 }
6053                                 continue;
6054                         }
6055                         
6056                         // faster than result <- left, anl result,right
6057                         // and better if result is SFR
6058                         if (AOP_TYPE(left) == AOP_ACC) {
6059                                 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6060                         } else {
6061                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6062                                 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6063                         }
6064                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6065                 }
6066         }
6067
6068 release :
6069         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6070         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6071         freeAsmop(result,NULL,ic,TRUE);     
6072 }
6073
6074 /*-----------------------------------------------------------------*/
6075 /* genXor - code for xclusive or                                   */
6076 /*-----------------------------------------------------------------*/
6077 static void genXor (iCode *ic, iCode *ifx)
6078 {
6079         operand *left, *right, *result;
6080         int size, offset=0;
6081         unsigned long lit = 0L;
6082         
6083         FENTRY;
6084         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6085         
6086         aopOp((left = IC_LEFT(ic)),ic,FALSE);
6087         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6088         aopOp((result=IC_RESULT(ic)),ic,TRUE);
6089         
6090         /* if left is a literal & right is not ||
6091         if left needs acc & right does not */
6092         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6093                 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6094                 operand *tmp = right ;
6095                 right = left;
6096                 left = tmp;
6097         }
6098         
6099         /* if result = right then exchange them */
6100         if(pic14_sameRegs(AOP(result),AOP(right))){
6101                 operand *tmp = right ;
6102                 right = left;
6103                 left = tmp;
6104         }
6105         
6106         /* if right is bit then exchange them */
6107         if (AOP_TYPE(right) == AOP_CRY &&
6108                 AOP_TYPE(left) != AOP_CRY){
6109                 operand *tmp = right ;
6110                 right = left;
6111                 left = tmp;
6112         }
6113         if(AOP_TYPE(right) == AOP_LIT)
6114                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6115         
6116         size = AOP_SIZE(result);
6117         
6118         // if(bit ^ yy)
6119         // xx = bit ^ yy;
6120         if (AOP_TYPE(left) == AOP_CRY){
6121                 if(AOP_TYPE(right) == AOP_LIT){
6122                         // c = bit & literal;
6123                         if(lit>>1){
6124                                 // lit>>1  != 0 => result = 1
6125                                 if(AOP_TYPE(result) == AOP_CRY){
6126                                         if(size)
6127                                         {emitpcode(POC_BSF,  popGet(AOP(result),offset));
6128                                         pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6129                                         else if(ifx)
6130                                                 continueIfTrue(ifx);
6131                                         goto release;
6132                                 }
6133                                 pic14_emitcode("setb","c");
6134                         } else{
6135                                 // lit == (0 or 1)
6136                                 if(lit == 0){
6137                                         // lit == 0, result = left
6138                                         if(size && pic14_sameRegs(AOP(result),AOP(left)))
6139                                                 goto release;
6140                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6141                                 } else{
6142                                         // lit == 1, result = not(left)
6143                                         if(size && pic14_sameRegs(AOP(result),AOP(left))){
6144                                                 emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
6145                                                 emitpcode(POC_XORWF,  popGet(AOP(result),offset));
6146                                                 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6147                                                 goto release;
6148                                         } else {
6149                                                 assert ( !"incomplete genXor" );
6150                                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6151                                                 pic14_emitcode("cpl","c");
6152                                         }
6153                                 }
6154                         }
6155                         
6156                 } else {
6157                         // right != literal
6158                         symbol *tlbl = newiTempLabel(NULL);
6159                         if (AOP_TYPE(right) == AOP_CRY){
6160                                 // c = bit ^ bit;
6161                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6162                         }
6163                         else{
6164                                 int sizer = AOP_SIZE(right);
6165                                 // c = bit ^ val
6166                                 // if val>>1 != 0, result = 1
6167                                 pic14_emitcode("setb","c");
6168                                 while(sizer){
6169                                         MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6170                                         if(sizer == 1)
6171                                                 // test the msb of the lsb
6172                                                 pic14_emitcode("anl","a,#0xfe");
6173                                         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6174                                         sizer--;
6175                                 }
6176                                 // val = (0,1)
6177                                 pic14_emitcode("rrc","a");
6178                         }
6179                         pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6180                         pic14_emitcode("cpl","c");
6181                         pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6182                 }
6183                 // bit = c
6184                 // val = c
6185                 if(size)
6186                         pic14_outBitC(result);
6187                 // if(bit | ...)
6188                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6189                         genIfxJump(ifx, "c");           
6190                 goto release ;
6191         }
6192         
6193         if(pic14_sameRegs(AOP(result),AOP(left))){
6194                 /* if left is same as result */
6195                 for(;size--; offset++) {
6196                         if(AOP_TYPE(right) == AOP_LIT){
6197                                 int t  = (lit >> (offset*8)) & 0x0FFL;
6198                                 if(t == 0x00L)
6199                                         continue;
6200                                 else
6201                                         if (IS_AOP_PREG(left)) {
6202                                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6203                                                 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6204                                                 aopPut(AOP(result),"a",offset);
6205                                         } else {
6206                                                 emitpcode(POC_MOVLW, popGetLit(t));
6207                                                 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6208                                                 pic14_emitcode("xrl","%s,%s",
6209                                                         aopGet(AOP(left),offset,FALSE,TRUE),
6210                                                         aopGet(AOP(right),offset,FALSE,FALSE));
6211                                         }
6212                         } else {
6213                                 if (AOP_TYPE(left) == AOP_ACC)
6214                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6215                                 else {
6216                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6217                                         emitpcode(POC_XORWF,popGet(AOP(left),offset));
6218                                         /*
6219                                         if (IS_AOP_PREG(left)) {
6220                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6221                                         aopPut(AOP(result),"a",offset);
6222                                         } else
6223                                         pic14_emitcode("xrl","%s,a",
6224                                         aopGet(AOP(left),offset,FALSE,TRUE));
6225                                         */
6226                                 }
6227                         }
6228                 }
6229         } else {
6230                 // left & result in different registers
6231                 if(AOP_TYPE(result) == AOP_CRY){
6232                         // result = bit
6233                         // if(size), result in bit
6234                         // if(!size && ifx), conditional oper: if(left ^ right)
6235                         symbol *tlbl = newiTempLabel(NULL);
6236                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6237                         if(size)
6238                                 pic14_emitcode("setb","c");
6239                         while(sizer--){
6240                                 if((AOP_TYPE(right) == AOP_LIT) &&
6241                                         (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6242                                         MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6243                                 } else {
6244                                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6245                                         pic14_emitcode("xrl","a,%s",
6246                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6247                                 }
6248                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6249                                 offset++;
6250                         }
6251                         if(size){
6252                                 CLRC;
6253                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6254                                 pic14_outBitC(result);
6255                         } else if(ifx)
6256                                 jmpTrueOrFalse(ifx, tlbl);
6257                 } else for(;(size--);offset++){
6258                         // normal case
6259                         // result = left & right
6260                         if(AOP_TYPE(right) == AOP_LIT){
6261                                 int t = (lit >> (offset*8)) & 0x0FFL;
6262                                 switch(t) { 
6263                                 case 0x00:
6264                                         if (AOP_TYPE(left) != AOP_ACC) {
6265                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6266                                         }
6267                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6268                                         pic14_emitcode("movf","%s,w",
6269                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6270                                         pic14_emitcode("movwf","%s",
6271                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6272                                         break;
6273                                 case 0xff:
6274                                         if (AOP_TYPE(left) == AOP_ACC) {
6275                                                 emitpcode(POC_XORLW, popGetLit(t));
6276                                         } else {
6277                                                 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6278                                         }
6279                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6280                                         break;
6281                                 default:
6282                                         if (AOP_TYPE(left) == AOP_ACC) {
6283                                                 emitpcode(POC_XORLW, popGetLit(t));
6284                                         } else {
6285                                                 emitpcode(POC_MOVLW, popGetLit(t));
6286                                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6287                                         }
6288                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6289                                         pic14_emitcode("movlw","0x%x",t);
6290                                         pic14_emitcode("xorwf","%s,w",
6291                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6292                                         pic14_emitcode("movwf","%s",
6293                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6294                                         
6295                                 }
6296                                 continue;
6297                         }
6298                         
6299                         // faster than result <- left, anl result,right
6300                         // and better if result is SFR
6301                         if (AOP_TYPE(left) == AOP_ACC) {
6302                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6303                         } else {
6304                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6305                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6306                         }
6307                         if ( AOP_TYPE(result) != AOP_ACC){
6308                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6309                         }
6310                 }
6311         }
6312         
6313 release :
6314         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6315         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6316         freeAsmop(result,NULL,ic,TRUE);     
6317 }
6318
6319 /*-----------------------------------------------------------------*/
6320 /* genInline - write the inline code out                           */
6321 /*-----------------------------------------------------------------*/
6322 static void genInline (iCode *ic)
6323 {
6324   char *buffer, *bp, *bp1;
6325
6326   FENTRY;
6327   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6328
6329   _G.inLine += (!options.asmpeep);
6330
6331   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6332   strcpy(buffer,IC_INLINE(ic));
6333
6334   /* emit each line as a code */
6335   while (*bp) {
6336     if (*bp == '\n') {
6337       *bp++ = '\0';
6338       
6339       if(*bp1)
6340         addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6341       bp1 = bp;
6342     } else {
6343       if (*bp == ':') {
6344         bp++;
6345         *bp = '\0';
6346         bp++;
6347
6348         /* print label, use this special format with NULL directive
6349          * to denote that the argument should not be indented with tab */
6350         addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6351
6352         bp1 = bp;
6353       } else
6354         bp++;
6355     }
6356   }
6357   if ((bp1 != bp) && *bp1)
6358     addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6359
6360   Safe_free(buffer);
6361
6362   _G.inLine -= (!options.asmpeep);
6363 }
6364
6365 /*-----------------------------------------------------------------*/
6366 /* genRRC - rotate right with carry                                */
6367 /*-----------------------------------------------------------------*/
6368 static void genRRC (iCode *ic)
6369 {
6370         operand *left , *result ;
6371         int size, offset = 0, same;
6372         
6373         FENTRY;
6374         /* rotate right with carry */
6375         left = IC_LEFT(ic);
6376         result=IC_RESULT(ic);
6377         aopOp (left,ic,FALSE);
6378         aopOp (result,ic,FALSE);
6379         
6380         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6381         
6382         same = pic14_sameRegs(AOP(result),AOP(left));
6383         
6384         size = AOP_SIZE(result);    
6385         
6386         /* get the lsb and put it into the carry */
6387         emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6388         
6389         offset = 0 ;
6390         
6391         while(size--) {
6392                 
6393                 if(same) {
6394                         emitpcode(POC_RRF, popGet(AOP(left),offset));
6395                 } else {
6396                         emitpcode(POC_RRFW, popGet(AOP(left),offset));
6397                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6398                 }
6399                 
6400                 offset++;
6401         }
6402         
6403         freeAsmop(left,NULL,ic,TRUE);
6404         freeAsmop(result,NULL,ic,TRUE);
6405 }
6406
6407 /*-----------------------------------------------------------------*/
6408 /* genRLC - generate code for rotate left with carry               */
6409 /*-----------------------------------------------------------------*/
6410 static void genRLC (iCode *ic)
6411 {    
6412         operand *left , *result ;
6413         int size, offset = 0;
6414         int same;
6415         
6416         FENTRY;
6417         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6418         /* rotate right with carry */
6419         left = IC_LEFT(ic);
6420         result=IC_RESULT(ic);
6421         aopOp (left,ic,FALSE);
6422         aopOp (result,ic,FALSE);
6423         
6424         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6425         
6426         same = pic14_sameRegs(AOP(result),AOP(left));
6427         
6428         /* move it to the result */
6429         size = AOP_SIZE(result);    
6430         
6431         /* get the msb and put it into the carry */
6432         emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6433         
6434         offset = 0 ;
6435         
6436         while(size--) {
6437                 
6438                 if(same) {
6439                         emitpcode(POC_RLF, popGet(AOP(left),offset));
6440                 } else {
6441                         emitpcode(POC_RLFW, popGet(AOP(left),offset));
6442                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6443                 }
6444                 
6445                 offset++;
6446         }
6447         
6448         
6449         freeAsmop(left,NULL,ic,TRUE);
6450         freeAsmop(result,NULL,ic,TRUE);
6451 }
6452
6453 /*-----------------------------------------------------------------*/
6454 /* genGetHbit - generates code get highest order bit               */
6455 /*-----------------------------------------------------------------*/
6456 static void genGetHbit (iCode *ic)
6457 {
6458         operand *left, *result;
6459         left = IC_LEFT(ic);
6460         result=IC_RESULT(ic);
6461         aopOp (left,ic,FALSE);
6462         aopOp (result,ic,FALSE);
6463         
6464         FENTRY;
6465         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6466         /* get the highest order byte into a */
6467         MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6468         if(AOP_TYPE(result) == AOP_CRY){
6469                 pic14_emitcode("rlc","a");
6470                 pic14_outBitC(result);
6471         }
6472         else{
6473                 pic14_emitcode("rl","a");
6474                 pic14_emitcode("anl","a,#0x01");
6475                 pic14_outAcc(result);
6476         }
6477         
6478         
6479         freeAsmop(left,NULL,ic,TRUE);
6480         freeAsmop(result,NULL,ic,TRUE);
6481 }
6482
6483 /*-----------------------------------------------------------------*/
6484 /* AccLsh - shift left accumulator by known count                  */
6485 /* MARK: pic14 always rotates through CARRY!                       */
6486 /*-----------------------------------------------------------------*/
6487 static void AccLsh (pCodeOp *pcop,int shCount)
6488 {
6489         FENTRY;
6490         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6491         shCount &= 0x0007;              // shCount : 0..7
6492         switch(shCount){
6493         case 0 :
6494                 return;
6495                 break;
6496         case 1 :
6497                 emitCLRC;
6498                 emitpcode(POC_RLF,pcop);
6499                 return;
6500                 break;
6501         case 2 :
6502                 emitpcode(POC_RLF,pcop);
6503                 emitpcode(POC_RLF,pcop);
6504                 break;
6505         case 3 :
6506                 emitpcode(POC_RLF,pcop);
6507                 emitpcode(POC_RLF,pcop);
6508                 emitpcode(POC_RLF,pcop);
6509                 break;
6510         case 4 :
6511                 emitpcode(POC_SWAPF,pcop);
6512                 break;
6513         case 5 :
6514                 emitpcode(POC_SWAPF,pcop);
6515                 emitpcode(POC_RLF,pcop);
6516                 break;
6517         case 6 :
6518                 emitpcode(POC_SWAPF,pcop);
6519                 emitpcode(POC_RLF,pcop);
6520                 emitpcode(POC_RLF,pcop);
6521                 break;
6522         case 7 :
6523                 emitpcode(POC_RRFW,pcop);
6524                 emitpcode(POC_RRF,pcop);
6525                 break;
6526         }
6527         /* clear invalid bits */
6528         emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6529         emitpcode(POC_ANDWF, pcop);
6530 }
6531
6532 /*-----------------------------------------------------------------*/
6533 /* AccRsh - shift right accumulator by known count                 */
6534 /* MARK: pic14 always rotates through CARRY!                       */
6535 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6536 /*            1: mask out invalid bits (zero-extend)               */
6537 /*            2: sign-extend result (pretty slow)                  */
6538 /*-----------------------------------------------------------------*/
6539 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6540 {
6541         FENTRY;
6542         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6543         shCount &= 0x0007;              // shCount : 0..7
6544         switch(shCount){
6545         case 0 :
6546                 return;
6547                 break;
6548         case 1 :
6549                 /* load sign if needed */
6550                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6551                 else if (mask_mode == 1) emitCLRC;
6552                 emitpcode(POC_RRF,pcop);
6553                 return;
6554                 break;
6555         case 2 :
6556                 /* load sign if needed */
6557                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6558                 emitpcode(POC_RRF,pcop);
6559                 /* load sign if needed */
6560                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6561                 emitpcode(POC_RRF,pcop);
6562                 if (mask_mode == 2) return;
6563                 break;
6564         case 3 :
6565                 /* load sign if needed */
6566                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6567                 emitpcode(POC_RRF,pcop);
6568                 /* load sign if needed */
6569                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6570                 emitpcode(POC_RRF,pcop);
6571                 /* load sign if needed */
6572                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6573                 emitpcode(POC_RRF,pcop);
6574                 if (mask_mode == 2) return;
6575                 break;
6576         case 4 :
6577                 emitpcode(POC_SWAPF,pcop);
6578                 break;
6579         case 5 :
6580                 emitpcode(POC_SWAPF,pcop);
6581                 emitpcode(POC_RRF,pcop);
6582                 break;
6583         case 6 :
6584                 emitpcode(POC_SWAPF,pcop);
6585                 emitpcode(POC_RRF,pcop);
6586                 emitpcode(POC_RRF,pcop);
6587                 break;
6588         case 7 :
6589                 if (mask_mode == 2)
6590                 {
6591                         /* load sign */
6592                         emitpcode(POC_RLFW,pcop);
6593                         emitpcode(POC_CLRF,pcop);
6594                         emitSKPNC;
6595                         emitpcode(POC_COMF,pcop);
6596                         return;
6597                 } else {
6598                         emitpcode(POC_RLFW,pcop);
6599                         emitpcode(POC_RLF,pcop);
6600                 }
6601                 break;
6602         }
6603
6604         if (mask_mode == 0)
6605         {
6606                 /* leave invalid bits undefined */
6607                 return;
6608         }
6609         
6610         /* clear invalid bits -- zero-extend */
6611         emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6612         emitpcode(POC_ANDWF, pcop);
6613
6614         if (mask_mode == 2) {
6615           /* sign-extend */
6616           emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6617           emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6618           emitpcode(POC_IORWF, pcop);
6619         }
6620 }
6621
6622 #if 0
6623 /*-----------------------------------------------------------------*/
6624 /* AccSRsh - signed right shift accumulator by known count                 */
6625 /*-----------------------------------------------------------------*/
6626 static void AccSRsh (int shCount)
6627 {
6628         symbol *tlbl ;
6629         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6630         if(shCount != 0){
6631                 if(shCount == 1){
6632                         pic14_emitcode("mov","c,acc.7");
6633                         pic14_emitcode("rrc","a");
6634                 } else if(shCount == 2){
6635                         pic14_emitcode("mov","c,acc.7");
6636                         pic14_emitcode("rrc","a");
6637                         pic14_emitcode("mov","c,acc.7");
6638                         pic14_emitcode("rrc","a");
6639                 } else {
6640                         tlbl = newiTempLabel(NULL);
6641                         /* rotate right accumulator */
6642                         AccRol(8 - shCount);
6643                         /* and kill the higher order bits */
6644                         pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6645                         pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6646                         pic14_emitcode("orl","a,#0x%02x",
6647                                 (unsigned char)~SRMask[shCount]);
6648                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6649                 }
6650         }
6651 }
6652
6653 /*-----------------------------------------------------------------*/
6654 /* shiftR1Left2Result - shift right one byte from left to result   */
6655 /*-----------------------------------------------------------------*/
6656 static void shiftR1Left2ResultSigned (operand *left, int offl,
6657                                                                           operand *result, int offr,
6658                                                                           int shCount)
6659 {
6660         int same;
6661         
6662         FENTRY;
6663         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6664         
6665         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6666         
6667         switch(shCount) {
6668         case 1:
6669                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6670                 if(same) 
6671                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6672                 else {
6673                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6674                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6675                 }
6676                 
6677                 break;
6678         case 2:
6679                 
6680                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6681                 if(same) 
6682                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6683                 else {
6684                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6685                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6686                 }
6687                 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6688                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6689                 
6690                 break;
6691                 
6692         case 3:
6693                 if(same)
6694                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6695                 else {
6696                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6697                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6698                 }
6699                 
6700                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6701                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6702                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6703                 
6704                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6705                 emitpcode(POC_IORLW, popGetLit(0xe0));
6706                 
6707                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6708                 break;
6709                 
6710         case 4:
6711                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6712                 emitpcode(POC_ANDLW,  popGetLit(0x0f));
6713                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6714                 emitpcode(POC_IORLW,  popGetLit(0xf0));
6715                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6716                 break;
6717         case 5:
6718                 if(same) {
6719                         emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6720                 } else {
6721                         emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6722                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6723                 }
6724                 emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6725                 emitpcode(POC_ANDLW,  popGetLit(0x07));
6726                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6727                 emitpcode(POC_IORLW,  popGetLit(0xf8));
6728                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6729                 break;
6730                 
6731         case 6:
6732                 if(same) {
6733                         emitpcode(POC_MOVLW, popGetLit(0x00));
6734                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6735                         emitpcode(POC_MOVLW, popGetLit(0xfe));
6736                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6737                         emitpcode(POC_IORLW, popGetLit(0x01));
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                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6744                         emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6745                 }
6746                 break;
6747                 
6748         case 7:
6749                 if(same) {
6750                         emitpcode(POC_MOVLW, popGetLit(0x00));
6751                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6752                         emitpcode(POC_MOVLW, popGetLit(0xff));
6753                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6754                 } else {
6755                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6756                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6757                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6758                 }
6759                 
6760         default:
6761                 break;
6762         }
6763 }
6764
6765 /*-----------------------------------------------------------------*/
6766 /* shiftR1Left2Result - shift right one byte from left to result   */
6767 /*-----------------------------------------------------------------*/
6768 static void shiftR1Left2Result (operand *left, int offl,
6769                                                                 operand *result, int offr,
6770                                                                 int shCount, int sign)
6771 {
6772         int same;
6773         
6774         FENTRY;
6775         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6776         
6777         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6778         
6779         /* Copy the msb into the carry if signed. */
6780         if(sign) {
6781                 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6782                 return;
6783         }
6784         
6785         
6786         
6787         switch(shCount) {
6788         case 1:
6789                 emitCLRC;
6790                 if(same) 
6791                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6792                 else {
6793                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6794                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6795                 }
6796                 break;
6797         case 2:
6798                 emitCLRC;
6799                 if(same) {
6800                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6801                 } else {
6802                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6803                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6804                 }
6805                 emitCLRC;
6806                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6807                 
6808                 break;
6809         case 3:
6810                 if(same)
6811                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6812                 else {
6813                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6814                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6815                 }
6816                 
6817                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6818                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6819                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6820                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6821                 break;
6822                 
6823         case 4:
6824                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6825                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6826                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6827                 break;
6828                 
6829         case 5:
6830                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6831                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6832                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6833                 emitCLRC;
6834                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6835                 
6836                 break;
6837         case 6:
6838                 
6839                 emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6840                 emitpcode(POC_ANDLW, popGetLit(0x80));
6841                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6842                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6843                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6844                 break;
6845                 
6846         case 7:
6847                 
6848                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6849                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6850                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6851                 
6852                 break;
6853                 
6854         default:
6855                 break;
6856         }
6857 }
6858
6859 /*-----------------------------------------------------------------*/
6860 /* shiftL1Left2Result - shift left one byte from left to result    */
6861 /*-----------------------------------------------------------------*/
6862 static void shiftL1Left2Result (operand *left, int offl,
6863                                                                 operand *result, int offr, int shCount)
6864 {
6865         int same;
6866         
6867         //    char *l;
6868         FENTRY;
6869         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6870         
6871         same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6872         DEBUGpic14_emitcode ("; ***","same =  %d",same);
6873         //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6874         //    MOVA(l);
6875         /* shift left accumulator */
6876         //AccLsh(shCount); // don't comment out just yet...
6877         //    aopPut(AOP(result),"a",offr);
6878         
6879         switch(shCount) {
6880         case 1:
6881                 /* Shift left 1 bit position */
6882                 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6883                 if(same) {
6884                         emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6885                 } else {
6886                         emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6887                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6888                 }
6889                 break;
6890         case 2:
6891                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6892                 emitpcode(POC_ANDLW,popGetLit(0x7e));
6893                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6894                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6895                 break;
6896         case 3:
6897                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6898                 emitpcode(POC_ANDLW,popGetLit(0x3e));
6899                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6900                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6901                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6902                 break;
6903         case 4:
6904                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6905                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6906                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6907                 break;
6908         case 5:
6909                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6910                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6911                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6912                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6913                 break;
6914         case 6:
6915                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6916                 emitpcode(POC_ANDLW, popGetLit(0x30));
6917                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6918                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6919                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6920                 break;
6921         case 7:
6922                 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6923                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6924                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6925                 break;
6926                 
6927         default:
6928                 DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6929         }
6930         
6931 }
6932 #endif
6933
6934 /*-----------------------------------------------------------------*/
6935 /* movLeft2Result - move byte from left to result                  */
6936 /*-----------------------------------------------------------------*/
6937 static void movLeft2Result (operand *left, int offl,
6938                                                         operand *result, int offr)
6939 {
6940         char *l;
6941         FENTRY;
6942         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6943         if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6944                 l = aopGet(AOP(left),offl,FALSE,FALSE);
6945                 
6946                 if (*l == '@' && (IS_AOP_PREG(result))) {
6947                         pic14_emitcode("mov","a,%s",l);
6948                         aopPut(AOP(result),"a",offr);
6949                 } else {
6950                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6951                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6952                 }
6953         }
6954 }
6955
6956 /*-----------------------------------------------------------------*/
6957 /* shiftLeft_Left2ResultLit - shift left by known count            */
6958 /*-----------------------------------------------------------------*/
6959
6960 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6961 {
6962         int size, same, offr, i;
6963
6964         size = AOP_SIZE(left);
6965         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6966         
6967         same = pic14_sameRegs (AOP(left), AOP(result));
6968         
6969         offr = shCount / 8;
6970         shCount = shCount & 0x07;
6971
6972         size -= offr;
6973
6974         switch (shCount)
6975         {
6976         case 0: /* takes 0 or 2N cycles (for offr==0) */
6977                 if (!same || offr) {
6978                         for (i=size-1; i >= 0; i--)
6979                                 movLeft2Result (left, i, result, offr + i);
6980                 } // if
6981                 break;
6982                 
6983         case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6984                 if (same && offr) {
6985                         shiftLeft_Left2ResultLit (left, result, 8 * offr);
6986                         shiftLeft_Left2ResultLit (result, result, shCount);
6987                         return; /* prevent clearing result again */
6988                 } else {
6989                         emitCLRC;
6990                         for (i=0; i < size; i++) {
6991                                 if (same && !offr) {
6992                                         emitpcode (POC_RLF, popGet (AOP(left), i));
6993                                 } else {
6994                                         emitpcode (POC_RLFW, popGet (AOP(left), i));
6995                                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6996                                 } // if
6997                         } // for
6998                 } // if (offr)
6999                 break;
7000                 
7001         case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
7002                 /* works in-place/with offr as well */
7003                 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
7004                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7005                 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
7006
7007                 for (i = size - 2; i >= 0; i--)
7008                 {
7009                         emitpcode (POC_SWAPFW, popGet (AOP(left), i));
7010                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7011                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7012                         emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
7013                         emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
7014                 } // for i
7015                 break;
7016                 
7017         case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7018                 /* works in-place/with offr as well */
7019                 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7020                 for (i = size-2; i >= 0; i--) {
7021                         emitpcode (POC_RRFW, popGet (AOP(left), i));
7022                         emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7023                 } // for i
7024                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7025                 emitpcode (POC_RRF, popGet (AOP(result), offr));
7026                 break;
7027         
7028         default:
7029                 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7030                 shiftLeft_Left2ResultLit (result, result, 1);
7031                 return; /* prevent clearing result again */
7032                 break;
7033         } // switch
7034
7035         while (0 < offr--)
7036         {
7037                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7038         } // while
7039 }
7040
7041 /*-----------------------------------------------------------------*/
7042 /* shiftRight_Left2ResultLit - shift right by known count          */
7043 /*-----------------------------------------------------------------*/
7044
7045 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7046 {
7047         int size, same, offr, i;
7048
7049         size = AOP_SIZE(left);
7050         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7051         
7052         same = pic14_sameRegs (AOP(left), AOP(result));
7053         
7054         offr = shCount / 8;
7055         shCount = shCount & 0x07;
7056
7057         size -= offr;
7058
7059         if (size)
7060         {
7061                 switch (shCount)
7062                 {
7063                 case 0: /* takes 0 or 2N cycles (for offr==0) */
7064                         if (!same || offr) {
7065                                 for (i=0; i < size; i++)
7066                                         movLeft2Result (left, i + offr, result, i);
7067                         } // if
7068                         break;
7069                         
7070                 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7071                         emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7072                         if (same && offr) {
7073                                 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7074                                 shiftRight_Left2ResultLit (result, result, shCount, sign);
7075                                 return; /* prevent sign-extending result again */
7076                         } else {
7077                                 emitCLRC;
7078                                 if (sign) {
7079                                         emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7080                                         emitSETC;
7081                                 }
7082                                 for (i = size-1; i >= 0; i--) {
7083                                         if (same && !offr) {
7084                                                 emitpcode (POC_RRF, popGet (AOP(left), i));
7085                                         } else {
7086                                                 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7087                                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7088                                         }
7089                                 } // for i
7090                         } // if (offr)
7091                         break;
7092                         
7093                 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7094                         /* works in-place/with offr as well */
7095                         emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7096                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7097                         emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7098
7099                         for (i = 1; i < size; i++)
7100                         {
7101                                 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7102                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7103                                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7104                                 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7105                                 emitpcode (POC_XORWF, popGet (AOP(result), i));
7106                         } // for i
7107
7108                         if (sign)
7109                         {
7110                                 emitpcode (POC_MOVLW, popGetLit (0xF0));
7111                                 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7112                                 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7113                         } // if
7114                         break;
7115                         
7116                 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7117                         /* works in-place/with offr as well */
7118                         emitpcode (POC_RLFW, popGet (AOP(left), offr));
7119                         for (i = 0; i < size-1; i++) {
7120                                 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7121                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7122                         } // for i
7123                         emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7124                         if (!sign) {
7125                                 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7126                         } else {
7127                                 emitSKPNC;
7128                                 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7129                         }
7130                         break;
7131                 
7132                 default:
7133                         shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7134                         shiftRight_Left2ResultLit (result, result, 1, sign);
7135                         return; /* prevent sign extending result again */
7136                         break;
7137                 } // switch
7138         } // if
7139
7140         addSign (result, size, sign);
7141 }
7142
7143 #if 0
7144 /*-----------------------------------------------------------------*/
7145 /* shiftL2Left2Result - shift left two bytes from left to result   */
7146 /*-----------------------------------------------------------------*/
7147 static void shiftL2Left2Result (operand *left, int offl,
7148                                                                 operand *result, int offr, int shCount)
7149 {
7150         FENTRY;
7151         
7152         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7153         
7154         if(pic14_sameRegs(AOP(result), AOP(left))) {
7155                 switch(shCount) {
7156                 case 0:
7157                         break;
7158                 case 1:
7159                 case 2:
7160                 case 3:
7161                         
7162                         emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7163                         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7164                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7165                         
7166                         while(--shCount) {
7167                                 emitCLRC;
7168                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7169                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7170                         }
7171                         
7172                         break;
7173                 case 4:
7174                 case 5:
7175                         emitpcode(POC_MOVLW, popGetLit(0x0f));
7176                         emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7177                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7178                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7179                         emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7180                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7181                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7182                         if(shCount >=5) {
7183                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7184                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7185                         }
7186                         break;
7187                 case 6:
7188                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7189                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7190                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7191                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7192                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7193                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7194                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7195                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7196                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7197                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7198                         break;
7199                 case 7:
7200                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7201                         emitpcode(POC_RRFW, popGet(AOP(result),offr));
7202                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7203                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7204                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7205                 }
7206                 
7207         } else {
7208                 switch(shCount) {
7209                 case 0:
7210                         break;
7211                 case 1:
7212                 case 2:
7213                 case 3:
7214                 /* note, use a mov/add for the shift since the mov has a
7215                         chance of getting optimized out */
7216                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7217                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7218                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7219                         emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
7220                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7221                         
7222                         while(--shCount) {
7223                                 emitCLRC;
7224                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7225                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7226                         }
7227                         break;
7228                         
7229                 case 4:
7230                 case 5:
7231                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7232                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7233                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7234                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7235                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7236                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7237                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7238                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7239                         
7240                         
7241                         if(shCount == 5) {
7242                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7243                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7244                         }
7245                         break;
7246                 case 6:
7247                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7248                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7249                         emitpcode(POC_RRFW, popGet(AOP(result),offl));
7250                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
7251                         
7252                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7253                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7254                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7255                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7256                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7257                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7258                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7259                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7260                         break;
7261                 case 7:
7262                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7263                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7264                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7265                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7266                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7267                 }
7268         }
7269         
7270 }
7271
7272 /*-----------------------------------------------------------------*/
7273 /* shiftR2Left2Result - shift right two bytes from left to result  */
7274 /*-----------------------------------------------------------------*/
7275 static void shiftR2Left2Result (operand *left, int offl,
7276                                                                 operand *result, int offr,
7277                                                                 int shCount, int sign)
7278 {
7279         int same=0;
7280         
7281         FENTRY;
7282         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7283         same = pic14_sameRegs(AOP(result), AOP(left));
7284         
7285         if(same && ((offl + MSB16) == offr)){
7286                 same=1;
7287                 /* don't crash result[offr] */
7288                 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7289                 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7290         }
7291         /* else {
7292         movLeft2Result(left,offl, result, offr);
7293         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7294         }
7295         */
7296         /* a:x >> shCount (x = lsb(result))*/
7297         /*
7298         if(sign)
7299         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7300         else {
7301         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7302         */
7303         switch(shCount) {
7304         case 0:
7305                 break;
7306         case 1:
7307         case 2:
7308         case 3:
7309                 if(sign)
7310                         emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7311                 else
7312                         emitCLRC;
7313                 
7314                 if(same) {
7315                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7316                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7317                 } else {
7318                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7319                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7320                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7321                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7322                 }
7323                 
7324                 while(--shCount) {
7325                         if(sign)
7326                                 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7327                         else
7328                                 emitCLRC;
7329                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7330                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7331                 }
7332                 break;
7333         case 4:
7334         case 5:
7335                 if(same) {
7336                         
7337                         emitpcode(POC_MOVLW, popGetLit(0xf0));
7338                         emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7339                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7340                         
7341                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7342                         emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7343                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7344                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7345                 } else {
7346                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7347                         emitpcode(POC_ANDLW, popGetLit(0x0f));
7348                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7349                         
7350                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7351                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7352                         emitpcode(POC_ANDLW, popGetLit(0xf0));
7353                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7354                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7355                 }
7356                 
7357                 if(shCount >=5) {
7358                         emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7359                         emitpcode(POC_RRF, popGet(AOP(result),offr));
7360                 }
7361                 
7362                 if(sign) {
7363                         emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7364                         emitpcode(POC_BTFSC, 
7365                                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7366                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7367                 }
7368                 
7369                 break;
7370                 
7371         case 6:
7372                 if(same) {
7373                         
7374                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7375                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7376                         
7377                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7378                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7379                         emitpcode(POC_RLFW, popGet(AOP(result),offr));
7380                         emitpcode(POC_ANDLW,popGetLit(0x03));
7381                         if(sign) {
7382                                 emitpcode(POC_BTFSC, 
7383                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7384                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7385                         }
7386                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7387                         emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7388                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7389                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7390                 } else {
7391                         emitpcode(POC_RLFW, popGet(AOP(left),offl));
7392                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7393                         emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7394                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7395                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7396                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7397                         emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7398                         emitpcode(POC_ANDLW,popGetLit(0x03));
7399                         if(sign) {
7400                                 emitpcode(POC_BTFSC, 
7401                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7402                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7403                         }
7404                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7405                         //emitpcode(POC_RLF,  popGet(AOP(result),offr));
7406                         
7407                         
7408                 }
7409                 
7410                 break;
7411         case 7:
7412                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7413                 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7414                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7415                 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7416                 if(sign) {
7417                         emitSKPNC;
7418                         emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7419                 } else 
7420                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7421   }
7422 }
7423
7424 /*-----------------------------------------------------------------*/
7425 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7426 /*-----------------------------------------------------------------*/
7427 static void shiftLLeftOrResult (operand *left, int offl,
7428                                                                 operand *result, int offr, int shCount)
7429 {
7430         FENTRY;
7431         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7432         
7433         /* shift left accumulator */
7434         AccLsh(left,offl,shCount);
7435         /* or with result */
7436         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7437         assert ( !"broken (modifies left, fails for left==result))" );
7438 }
7439
7440 /*-----------------------------------------------------------------*/
7441 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7442 /*-----------------------------------------------------------------*/
7443 static void shiftRLeftOrResult (operand *left, int offl,
7444                                                                 operand *result, int offr, int shCount)
7445 {
7446         FENTRY;
7447         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7448         
7449         /* shift right accumulator */
7450         AccRsh(left,offl,shCount);
7451         /* or with result */
7452         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7453         assert ( !"broken (modifies left, fails for left==result))" );
7454 }
7455
7456 /*-----------------------------------------------------------------*/
7457 /* genlshOne - left shift a one byte quantity by known count       */
7458 /*-----------------------------------------------------------------*/
7459 static void genlshOne (operand *result, operand *left, int shCount)
7460 {       
7461         FENTRY;
7462         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7463         shiftL1Left2Result(left, LSB, result, LSB, shCount);
7464 }
7465
7466 /*-----------------------------------------------------------------*/
7467 /* genlshTwo - left shift two bytes by known amount != 0           */
7468 /*-----------------------------------------------------------------*/
7469 static void genlshTwo (operand *result,operand *left, int shCount)
7470 {
7471         int size;
7472         
7473         FENTRY;
7474         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7475         size = pic14_getDataSize(result);
7476         
7477         /* if shCount >= 8 */
7478         if (shCount >= 8) {
7479                 shCount -= 8 ;
7480                 
7481                 if (size > 1){
7482                         if (shCount)
7483                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7484                         else 
7485                                 movLeft2Result(left, LSB, result, MSB16);
7486                 }
7487                 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7488         }
7489         
7490         /*  1 <= shCount <= 7 */
7491         else {  
7492                 if(size == 1)
7493                         shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7494                 else 
7495                         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7496         }
7497 }
7498
7499 /*-----------------------------------------------------------------*/
7500 /* shiftLLong - shift left one long from left to result            */
7501 /* offl = LSB or MSB16                                             */
7502 /*-----------------------------------------------------------------*/
7503 static void shiftLLong (operand *left, operand *result, int offr )
7504 {
7505         char *l;
7506         int size = AOP_SIZE(result);
7507         
7508         FENTRY;
7509         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7510         if(size >= LSB+offr){
7511                 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7512                 MOVA(l);
7513                 pic14_emitcode("add","a,acc");
7514                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7515                         size >= MSB16+offr && offr != LSB )
7516                         pic14_emitcode("xch","a,%s",
7517                         aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7518                 else      
7519                         aopPut(AOP(result),"a",LSB+offr);
7520         }
7521         
7522         if(size >= MSB16+offr){
7523                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7524                         l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7525                         MOVA(l);
7526                 }
7527                 pic14_emitcode("rlc","a");
7528                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7529                         size >= MSB24+offr && offr != LSB)
7530                         pic14_emitcode("xch","a,%s",
7531                         aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7532                 else      
7533                         aopPut(AOP(result),"a",MSB16+offr);
7534         }
7535         
7536         if(size >= MSB24+offr){
7537                 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7538                         l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7539                         MOVA(l);
7540                 }
7541                 pic14_emitcode("rlc","a");
7542                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7543                         size >= MSB32+offr && offr != LSB )
7544                         pic14_emitcode("xch","a,%s",
7545                         aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7546                 else      
7547                         aopPut(AOP(result),"a",MSB24+offr);
7548         }
7549         
7550         if(size > MSB32+offr){
7551                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7552                         l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7553                         MOVA(l);  
7554                 }
7555                 pic14_emitcode("rlc","a");
7556                 aopPut(AOP(result),"a",MSB32+offr);
7557         }
7558         if(offr != LSB)
7559                 aopPut(AOP(result),zero,LSB);       
7560 }
7561
7562 /*-----------------------------------------------------------------*/
7563 /* genlshFour - shift four byte by a known amount != 0             */
7564 /*-----------------------------------------------------------------*/
7565 static void genlshFour (operand *result, operand *left, int shCount)
7566 {
7567         int size;
7568         
7569         FENTRY;
7570         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7571         size = AOP_SIZE(result);
7572         
7573         /* if shifting more that 3 bytes */
7574         if (shCount >= 24 ) {
7575                 shCount -= 24;
7576                 if (shCount)
7577                 /* lowest order of left goes to the highest
7578                 order of the destination */
7579                 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7580                 else
7581                         movLeft2Result(left, LSB, result, MSB32);
7582                 aopPut(AOP(result),zero,LSB);
7583                 aopPut(AOP(result),zero,MSB16);
7584                 aopPut(AOP(result),zero,MSB32);
7585                 return;
7586         }
7587         
7588         /* more than two bytes */
7589         else if ( shCount >= 16 ) {
7590                 /* lower order two bytes goes to higher order two bytes */
7591                 shCount -= 16;
7592                 /* if some more remaining */
7593                 if (shCount)
7594                         shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7595                 else {
7596                         movLeft2Result(left, MSB16, result, MSB32);
7597                         movLeft2Result(left, LSB, result, MSB24);
7598                 }
7599                 aopPut(AOP(result),zero,MSB16);
7600                 aopPut(AOP(result),zero,LSB);
7601                 return;
7602         }    
7603         
7604         /* if more than 1 byte */
7605         else if ( shCount >= 8 ) {
7606                 /* lower order three bytes goes to higher order  three bytes */
7607                 shCount -= 8;
7608                 if(size == 2){
7609                         if(shCount)
7610                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7611                         else
7612                                 movLeft2Result(left, LSB, result, MSB16);
7613                 }
7614                 else{   /* size = 4 */
7615                         if(shCount == 0){
7616                                 movLeft2Result(left, MSB24, result, MSB32);
7617                                 movLeft2Result(left, MSB16, result, MSB24);
7618                                 movLeft2Result(left, LSB, result, MSB16);
7619                                 aopPut(AOP(result),zero,LSB);
7620                         }
7621                         else if(shCount == 1)
7622                                 shiftLLong(left, result, MSB16);
7623                         else{
7624                                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7625                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7626                                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7627                                 aopPut(AOP(result),zero,LSB);
7628                         }
7629                 }
7630         }
7631         
7632         /* 1 <= shCount <= 7 */
7633         else if(shCount <= 2){
7634                 shiftLLong(left, result, LSB);
7635                 if(shCount == 2)
7636                         shiftLLong(result, result, LSB);
7637         }
7638         /* 3 <= shCount <= 7, optimize */
7639         else{
7640                 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7641                 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7642                 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7643         }
7644 }
7645 #endif
7646
7647 #if 0
7648 /*-----------------------------------------------------------------*/
7649 /* genLeftShiftLiteral - left shifting by known count              */
7650 /*-----------------------------------------------------------------*/
7651 static void genLeftShiftLiteral (operand *left,
7652                                                                  operand *right,
7653                                                                  operand *result,
7654                                                                  iCode *ic)
7655 {    
7656         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7657         //int size;
7658         
7659         FENTRY;
7660         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7661         freeAsmop(right,NULL,ic,TRUE);
7662         
7663         aopOp(left,ic,FALSE);
7664         aopOp(result,ic,FALSE);
7665
7666         size = getSize(operandType(result));
7667         
7668 #if VIEW_SIZE
7669         pic14_emitcode("; shift left ","result %d, left %d",size,
7670                 AOP_SIZE(left));
7671 #endif
7672         
7673         /* I suppose that the left size >= result size */
7674         if(shCount == 0){
7675                 while(size--){
7676                         movLeft2Result(left, size, result, size);
7677                 }
7678         }
7679         
7680         else if(shCount >= (size * 8))
7681                 while(size--)
7682                         aopPut(AOP(result),zero,size);
7683                 else{
7684                         switch (size) {
7685                         case 1:
7686                                 genlshOne (result,left,shCount);
7687                                 break;
7688                                 
7689                         case 2:
7690                         case 3:
7691                                 genlshTwo (result,left,shCount);
7692                                 break;
7693                                 
7694                         case 4:
7695                                 genlshFour (result,left,shCount);
7696                                 break;
7697                         }
7698                 }
7699                 freeAsmop(left,NULL,ic,TRUE);
7700                 freeAsmop(result,NULL,ic,TRUE);
7701 }
7702 #endif
7703
7704 /*-----------------------------------------------------------------*
7705 * genMultiAsm - repeat assembly instruction for size of register.
7706 * if endian == 1, then the high byte (i.e base address + size of 
7707 * register) is used first else the low byte is used first;
7708 *-----------------------------------------------------------------*/
7709 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7710 {
7711         
7712         int offset = 0;
7713         
7714         FENTRY;
7715         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7716         
7717         if(!reg)
7718                 return;
7719         
7720         if(!endian) {
7721                 endian = 1;
7722         } else {
7723                 endian = -1;
7724                 offset = size-1;
7725         }
7726         
7727         while(size--) {
7728                 emitpcode(poc,    popGet(AOP(reg),offset));
7729                 offset += endian;
7730         }
7731         
7732 }
7733
7734 #if 0
7735 /*-----------------------------------------------------------------*/
7736 /* genLeftShift - generates code for left shifting                 */
7737 /*-----------------------------------------------------------------*/
7738 static void genLeftShift (iCode *ic)
7739 {
7740         operand *left,*right, *result;
7741         int size, offset;
7742         unsigned long lit = 0L;
7743         char *l;
7744         symbol *tlbl , *tlbl1;
7745         pCodeOp *pctemp;
7746         
7747         FENTRY;
7748         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7749         
7750         right = IC_RIGHT(ic);
7751         left  = IC_LEFT(ic);
7752         result = IC_RESULT(ic);
7753         
7754         aopOp(right,ic,FALSE);
7755         aopOp(left,ic,FALSE);
7756         aopOp(result,ic,FALSE);
7757         
7758         
7759         /* if the shift count is known then do it 
7760         as efficiently as possible */
7761         if (AOP_TYPE(right) == AOP_LIT) {
7762                 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7763                 return ;
7764         }
7765         
7766         /* shift count is unknown then we have to form 
7767         a loop get the loop count in B : Note: we take
7768         only the lower order byte since shifting
7769         more that 32 bits make no sense anyway, ( the
7770         largest size of an object can be only 32 bits ) */  
7771         
7772         /* this code fails for RIGHT == RESULT */
7773         assert (!pic14_sameRegs (AOP(right), AOP(result)));
7774         
7775         /* now move the left to the result if they are not the
7776         same */
7777         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7778                 AOP_SIZE(result) > 1) {
7779                 
7780                 size = AOP_SIZE(result);
7781                 offset=0;
7782                 while (size--) {
7783                         l = aopGet(AOP(left),offset,FALSE,TRUE);
7784                         if (*l == '@' && (IS_AOP_PREG(result))) {
7785                                 
7786                                 pic14_emitcode("mov","a,%s",l);
7787                                 aopPut(AOP(result),"a",offset);
7788                         } else {
7789                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7790                                 emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7791                                 //aopPut(AOP(result),l,offset);
7792                         }
7793                         offset++;
7794                 }
7795         }
7796         
7797         if(AOP_TYPE(left) == AOP_LIT)
7798                 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7799
7800         size = AOP_SIZE(result);
7801         
7802         /* if it is only one byte then */
7803         if (size == 1) {
7804                 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7805                         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7806                         emitpcode(POC_ANDLW,  popGetLit(0xf0));
7807                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7808                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7809                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7810                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7811                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7812                         emitpcode(POC_RLFW,   popGet(AOP(result),0));
7813                         emitpcode(POC_ANDLW,  popGetLit(0xfe));
7814                         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7815                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7816                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7817                 } else {
7818                         
7819                         tlbl = newiTempLabel(NULL);
7820                         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7821                                 mov2w (AOP(left), 0);
7822                                 emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7823                         }
7824                         
7825                         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7826                         emitpcode(POC_RRF,    popGet(AOP(result),0));
7827                         emitpLabel(tlbl->key);
7828                         emitpcode(POC_RLF,    popGet(AOP(result),0));
7829                         emitpcode(POC_ADDLW,  popGetLit(1));
7830                         emitSKPC;
7831                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7832                 }
7833                 goto release ;
7834         }
7835         
7836         if (pic14_sameRegs(AOP(left),AOP(result))) {
7837                 
7838                 tlbl = newiTempLabel(NULL);
7839                 emitpcode(POC_COMFW,  popGet(AOP(right),0));
7840                 genMultiAsm(POC_RRF, result, size,1);
7841                 emitpLabel(tlbl->key);
7842                 genMultiAsm(POC_RLF, result, size,0);
7843                 emitpcode(POC_ADDLW,  popGetLit(1));
7844                 emitSKPC;
7845                 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7846                 goto release;
7847         }
7848         
7849         //tlbl = newiTempLabel(NULL);
7850         //offset = 0 ;   
7851         //tlbl1 = newiTempLabel(NULL);
7852         
7853         //reAdjustPreg(AOP(result));    
7854         
7855         //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7856         //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7857         //l = aopGet(AOP(result),offset,FALSE,FALSE);
7858         //MOVA(l);
7859         //pic14_emitcode("add","a,acc");         
7860         //aopPut(AOP(result),"a",offset++);
7861         //while (--size) {
7862         //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7863         //  MOVA(l);
7864         //  pic14_emitcode("rlc","a");         
7865         //  aopPut(AOP(result),"a",offset++);
7866         //}
7867         //reAdjustPreg(AOP(result));
7868         
7869         //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7870         //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7871         
7872         
7873         tlbl = newiTempLabel(NULL);
7874         tlbl1= newiTempLabel(NULL);
7875         
7876         size = AOP_SIZE(result);
7877         offset = 1;
7878         
7879         pctemp = popGetTempReg();  /* grab a temporary working register. */
7880         
7881         emitpcode(POC_MOVFW, popGet(AOP(right),0));
7882         
7883         /* offset should be 0, 1 or 3 */
7884         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7885         emitSKPNZ;
7886         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7887         
7888         emitpcode(POC_MOVWF, pctemp);
7889         
7890         
7891         emitpLabel(tlbl->key);
7892         
7893         emitCLRC;
7894         emitpcode(POC_RLF,  popGet(AOP(result),0));
7895         while(--size)
7896                 emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7897         
7898         emitpcode(POC_DECFSZ,  pctemp);
7899         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7900         emitpLabel(tlbl1->key);
7901         
7902         popReleaseTempReg(pctemp);
7903         
7904         
7905 release:
7906         freeAsmop (right,NULL,ic,TRUE);
7907         freeAsmop(left,NULL,ic,TRUE);
7908         freeAsmop(result,NULL,ic,TRUE);
7909 }
7910 #endif
7911
7912 #if 0
7913 /*-----------------------------------------------------------------*/
7914 /* genrshOne - right shift a one byte quantity by known count      */
7915 /*-----------------------------------------------------------------*/
7916 static void genrshOne (operand *result, operand *left,
7917                                            int shCount, int sign)
7918 {
7919         FENTRY;
7920         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7921         shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7922 }
7923
7924 /*-----------------------------------------------------------------*/
7925 /* genrshTwo - right shift two bytes by known amount != 0          */
7926 /*-----------------------------------------------------------------*/
7927 static void genrshTwo (operand *result,operand *left,
7928                                            int shCount, int sign)
7929 {
7930         FENTRY;
7931         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7932         /* if shCount >= 8 */
7933         if (shCount >= 8) {
7934                 shCount -= 8 ;
7935                 if (shCount)
7936                         shiftR1Left2Result(left, MSB16, result, LSB,
7937                         shCount, sign);
7938                 else
7939                         movLeft2Result(left, MSB16, result, LSB);
7940                 
7941                 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7942                 
7943                 if(sign) {
7944                         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7945                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7946                 }
7947         }
7948         
7949         /*  1 <= shCount <= 7 */
7950         else
7951                 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7952 }
7953
7954 /*-----------------------------------------------------------------*/
7955 /* shiftRLong - shift right one long from left to result           */
7956 /* offl = LSB or MSB16                                             */
7957 /*-----------------------------------------------------------------*/
7958 static void shiftRLong (operand *left, int offl,
7959                                                 operand *result, int sign)
7960 {
7961         int size, same;
7962         
7963         FENTRY;
7964         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7965         
7966         size = AOP_SIZE(left);
7967         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7968         
7969         if (sign)
7970                 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7971         else
7972                 emitCLRC;
7973
7974         assert (offl >= 0 && offl < size);
7975
7976         same = pic14_sameRegs (AOP(left), AOP(result));
7977
7978         /* perform the shift */
7979         while (size--)
7980         {
7981                 if (same && !offl) {
7982                         emitpcode (POC_RRF, popGet (AOP(result), size));
7983                 } else {
7984                         emitpcode (POC_RRFW, popGet (AOP(left), size));
7985                         emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7986                 }
7987         } // while
7988
7989         addSign (result, AOP_SIZE(left) - offl, sign);
7990 }
7991
7992 /*-----------------------------------------------------------------*/
7993 /* genrshFour - shift four byte by a known amount != 0             */
7994 /*-----------------------------------------------------------------*/
7995 static void genrshFour (operand *result, operand *left,
7996                                                 int shCount, int sign)
7997 {
7998         FENTRY;
7999         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8000         /* if shifting more that 3 bytes */
8001         if(shCount >= 24 ) {
8002                 shCount -= 24;
8003                 if(shCount)
8004                         shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8005                 else
8006                         movLeft2Result(left, MSB32, result, LSB);
8007                 
8008                 addSign(result, MSB16, sign);
8009         }
8010         else if(shCount >= 16){
8011                 shCount -= 16;
8012                 if(shCount)
8013                         shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8014                 else{
8015                         movLeft2Result(left, MSB24, result, LSB);
8016                         movLeft2Result(left, MSB32, result, MSB16);
8017                 }
8018                 addSign(result, MSB24, sign);
8019         }
8020         else if(shCount >= 8){
8021                 shCount -= 8;
8022                 if(shCount == 1)
8023                         shiftRLong(left, MSB16, result, sign);
8024                 else if(shCount == 0){
8025                         movLeft2Result(left, MSB16, result, LSB);
8026                         movLeft2Result(left, MSB24, result, MSB16);
8027                         movLeft2Result(left, MSB32, result, MSB24);
8028                         addSign(result, MSB32, sign);
8029                 }
8030                 else{
8031                         shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8032                         shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8033                         /* the last shift is signed */
8034                         shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8035                         addSign(result, MSB32, sign);
8036                 }
8037         }
8038         else{   /* 1 <= shCount <= 7 */
8039                 if(shCount <= 2){
8040                         shiftRLong(left, LSB, result, sign);
8041                         if(shCount == 2)
8042                                 shiftRLong(result, LSB, result, sign);
8043                 }
8044                 else{
8045                         shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8046                         shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8047                         shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8048                 }
8049         }
8050 }
8051
8052 /*-----------------------------------------------------------------*/
8053 /* genRightShiftLiteral - right shifting by known count            */
8054 /*-----------------------------------------------------------------*/
8055 static void genRightShiftLiteral (operand *left,
8056                                                                   operand *right,
8057                                                                   operand *result,
8058                                                                   iCode *ic,
8059                                                                   int sign)
8060 {    
8061         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8062         int lsize,res_size;
8063         
8064         FENTRY;
8065         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8066         freeAsmop(right,NULL,ic,TRUE);
8067         
8068         aopOp(left,ic,FALSE);
8069         aopOp(result,ic,FALSE);
8070         
8071 #if VIEW_SIZE
8072         pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8073                 AOP_SIZE(left));
8074 #endif
8075         
8076         lsize = pic14_getDataSize(left);
8077         res_size = pic14_getDataSize(result);
8078         /* test the LEFT size !!! */
8079         
8080         /* I suppose that the left size >= result size */
8081         if(shCount == 0){
8082                 while(res_size--)
8083                         movLeft2Result(left, res_size, result, res_size);
8084         }
8085         
8086         else if(shCount >= (lsize * 8)){
8087                 
8088                 if(res_size == 1) {
8089                         emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8090                         if(sign) {
8091                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8092                                 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8093                         }
8094                 } else {
8095                         
8096                         if(sign) {
8097                                 emitpcode(POC_MOVLW, popGetLit(0));
8098                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8099                                 emitpcode(POC_MOVLW, popGetLit(0xff));
8100                                 while(res_size--)
8101                                         emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8102                                 
8103                         } else {
8104                                 
8105                                 while(res_size--)
8106                                         emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8107                         }
8108                 }
8109         } else {
8110                 
8111                 switch (res_size) {
8112                 case 1:
8113                         genrshOne (result,left,shCount,sign);
8114                         break;
8115                         
8116                 case 2:
8117                         genrshTwo (result,left,shCount,sign);
8118                         break;
8119                         
8120                 case 4:
8121                         genrshFour (result,left,shCount,sign);
8122                         break;
8123                 default :
8124                         break;
8125                 }
8126                 
8127         }
8128
8129         freeAsmop(left,NULL,ic,TRUE);
8130         freeAsmop(result,NULL,ic,TRUE);
8131 }
8132 #endif
8133
8134 #if 0
8135 /*-----------------------------------------------------------------*/
8136 /* genSignedRightShift - right shift of signed number              */
8137 /*-----------------------------------------------------------------*/
8138 static void genSignedRightShift (iCode *ic)
8139 {
8140         operand *right, *left, *result;
8141         int size, offset;
8142         //  char *l;
8143         symbol *tlbl, *tlbl1 ;
8144         pCodeOp *pctemp;
8145         
8146         //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8147         
8148         /* we do it the hard way put the shift count in b
8149         and loop thru preserving the sign */
8150         FENTRY;
8151         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8152         
8153         right = IC_RIGHT(ic);
8154         left  = IC_LEFT(ic);
8155         result = IC_RESULT(ic);
8156         
8157         aopOp(right,ic,FALSE);  
8158         aopOp(left,ic,FALSE);
8159         aopOp(result,ic,FALSE);
8160         
8161         
8162         if ( AOP_TYPE(right) == AOP_LIT) {
8163                 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8164                 //genRightShiftLiteral (left,right,result,ic,1);
8165                 return ;
8166         }
8167         /* shift count is unknown then we have to form 
8168         a loop get the loop count in B : Note: we take
8169         only the lower order byte since shifting
8170         more that 32 bits make no sense anyway, ( the
8171         largest size of an object can be only 32 bits ) */  
8172         
8173         //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8174         //pic14_emitcode("inc","b");
8175         //freeAsmop (right,NULL,ic,TRUE);
8176         //aopOp(left,ic,FALSE);
8177         //aopOp(result,ic,FALSE);
8178         
8179         /* now move the left to the result if they are not the
8180         same */
8181         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
8182                 AOP_SIZE(result) > 1) {
8183                 
8184                 size = AOP_SIZE(result);
8185                 offset=0;
8186                 while (size--) { 
8187                         /*
8188                         l = aopGet(AOP(left),offset,FALSE,TRUE);
8189                         if (*l == '@' && IS_AOP_PREG(result)) {
8190                                 pic14_emitcode("mov","a,%s",l);
8191                                 aopPut(AOP(result),"a",offset);
8192                         } else
8193                         aopPut(AOP(result),l,offset);
8194                         */
8195                         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
8196                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
8197                         
8198                         offset++;
8199                 }
8200         }
8201         
8202         /* mov the highest order bit to OVR */    
8203         tlbl = newiTempLabel(NULL);
8204         tlbl1= newiTempLabel(NULL);
8205         
8206         size = AOP_SIZE(result);
8207         offset = size - 1;
8208         
8209         pctemp = popGetTempReg();  /* grab a temporary working register. */
8210         
8211         emitpcode(POC_MOVFW, popGet(AOP(right),0));
8212         
8213         /* offset should be 0, 1 or 3 */
8214         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8215         emitSKPNZ;
8216         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
8217         
8218         emitpcode(POC_MOVWF, pctemp);
8219         
8220         
8221         emitpLabel(tlbl->key);
8222         
8223         emitpcode(POC_RLFW,  popGet(AOP(result),offset));
8224         emitpcode(POC_RRF,   popGet(AOP(result),offset));
8225         
8226         while(--size) {
8227                 emitpcode(POC_RRF,   popGet(AOP(result),--offset));
8228         }
8229         
8230         emitpcode(POC_DECFSZ,  pctemp);
8231         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8232         emitpLabel(tlbl1->key);
8233         
8234         popReleaseTempReg(pctemp);
8235 #if 0
8236         size = AOP_SIZE(result);
8237         offset = size - 1;
8238         pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8239         pic14_emitcode("rlc","a");
8240         pic14_emitcode("mov","ov,c");
8241         /* if it is only one byte then */
8242         if (size == 1) {
8243                 l = aopGet(AOP(left),0,FALSE,FALSE);
8244                 MOVA(l);
8245                 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8246                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8247                 pic14_emitcode("mov","c,ov");
8248                 pic14_emitcode("rrc","a");
8249                 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8250                 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8251                 aopPut(AOP(result),"a",0);
8252                 goto release ;
8253         }
8254         
8255         reAdjustPreg(AOP(result));
8256         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8257         pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
8258         pic14_emitcode("mov","c,ov");
8259         while (size--) {
8260                 l = aopGet(AOP(result),offset,FALSE,FALSE);
8261                 MOVA(l);
8262                 pic14_emitcode("rrc","a");         
8263                 aopPut(AOP(result),"a",offset--);
8264         }
8265         reAdjustPreg(AOP(result));
8266         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8267         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8268         
8269 release:
8270 #endif
8271         
8272         freeAsmop(left,NULL,ic,TRUE);
8273         freeAsmop(result,NULL,ic,TRUE);
8274         freeAsmop(right,NULL,ic,TRUE);
8275 }
8276 #endif
8277
8278 /*-----------------------------------------------------------------*/
8279 /* loadSignToC - load the operand's sign bit into CARRY            */
8280 /*-----------------------------------------------------------------*/
8281
8282 static void loadSignToC (operand *op)
8283 {
8284         FENTRY;
8285         assert (op && AOP(op) && AOP_SIZE(op));
8286
8287         emitCLRC;
8288         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8289         emitSETC;
8290 }
8291
8292 /*-----------------------------------------------------------------*/
8293 /* genRightShift - generate code for right shifting                */
8294 /*-----------------------------------------------------------------*/
8295 static void genGenericShift (iCode *ic, int shiftRight)
8296 {
8297         operand *right, *left, *result;
8298         sym_link *retype ;
8299         int size;
8300         symbol *tlbl, *tlbl1, *inverselbl;
8301         
8302         FENTRY;
8303         /* if signed then we do it the hard way preserve the
8304         sign bit moving it inwards */
8305         retype = getSpec(operandType(IC_RESULT(ic)));
8306         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8307         
8308         /* signed & unsigned types are treated the same : i.e. the
8309         signed is NOT propagated inwards : quoting from the
8310         ANSI - standard : "for E1 >> E2, is equivalent to division
8311         by 2**E2 if unsigned or if it has a non-negative value,
8312         otherwise the result is implementation defined ", MY definition
8313         is that the sign does not get propagated */
8314         
8315         right = IC_RIGHT(ic);
8316         left  = IC_LEFT(ic);
8317         result = IC_RESULT(ic);
8318         
8319         aopOp(right,ic,FALSE);
8320         aopOp(left,ic,FALSE);
8321         aopOp(result,ic,FALSE);
8322         
8323         /* if the shift count is known then do it 
8324         as efficiently as possible */
8325         if (AOP_TYPE(right) == AOP_LIT) {
8326                 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8327                 if (lit < 0)
8328                 {
8329                         lit = -lit;
8330                         shiftRight = !shiftRight;
8331                 }
8332                 
8333                 if (shiftRight)
8334                         shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8335                 else
8336                         shiftLeft_Left2ResultLit (left, result, lit);
8337                 //genRightShiftLiteral (left,right,result,ic, 0);
8338                 return ;
8339         }
8340         
8341         /* shift count is unknown then we have to form 
8342         a loop get the loop count in B : Note: we take
8343         only the lower order byte since shifting
8344         more that 32 bits make no sense anyway, ( the
8345         largest size of an object can be only 32 bits ) */  
8346
8347         /* we must not overwrite the shift counter */
8348         assert (!pic14_sameRegs(AOP(right),AOP(result)));
8349         
8350         /* now move the left to the result if they are not the
8351         same */
8352         if (!pic14_sameRegs(AOP(left),AOP(result)))
8353         {
8354                 size = min(AOP_SIZE(result), AOP_SIZE(left));
8355                 while (size--) {
8356                         mov2w(AOP(left), size);
8357                         movwf(AOP(result), size);
8358                 }
8359                 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8360         }
8361         
8362         tlbl = newiTempLabel(NULL);
8363         tlbl1= newiTempLabel(NULL);
8364         inverselbl = NULL;
8365         size = AOP_SIZE(result);
8366
8367         mov2w(AOP(right),0);
8368         if (!SPEC_USIGN(operandType(right)))
8369         {
8370                 inverselbl = newiTempLabel(NULL);
8371                 /* signed shift count -- invert shift direction for c<0 */
8372                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8373                 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8374         } // if
8375         emitpcode(POC_SUBLW, popGetLit(0));     /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8376         /* check for `a = b >> c' with `-c == 0' */
8377         emitSKPNZ;
8378         emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8379         emitpLabel(tlbl->key);
8380         /* propagate the sign bit inwards for SIGNED result */
8381         if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8382         genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8383         emitpcode(POC_ADDLW,  popGetLit(1));    /* clears CARRY (unless W==0 afterwards) */
8384         emitSKPC;
8385         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8386
8387         if (!SPEC_USIGN(operandType(right)))
8388         {
8389                 symbol *inv_loop = newiTempLabel(NULL);
8390
8391                 shiftRight = !shiftRight;       /* invert shift direction */
8392                 
8393                 /* we came here from the code above -- we are done */
8394                 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8395                 
8396                 /* emit code for shifting N<0 steps, count is already in W */
8397                 emitpLabel(inverselbl->key);
8398                 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8399                 emitpLabel(inv_loop->key);
8400                 /* propagate the sign bit inwards for SIGNED result */
8401                 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8402                 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8403                 emitpcode(POC_ADDLW, popGetLit(1));
8404                 emitSKPC;
8405                 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8406         } // if
8407         
8408         emitpLabel(tlbl1->key);
8409         
8410         freeAsmop(left,NULL,ic,TRUE);
8411         freeAsmop (right,NULL,ic,TRUE);
8412         freeAsmop(result,NULL,ic,TRUE);
8413 }
8414
8415 static void genRightShift (iCode *ic)
8416 {
8417         genGenericShift(ic, 1);
8418 }
8419
8420 static void genLeftShift (iCode *ic)
8421 {
8422         genGenericShift(ic, 0);
8423 }
8424
8425 /*-----------------------------------------------------------------*/
8426 /* SetIrp - Set IRP bit                                            */
8427 /*-----------------------------------------------------------------*/
8428 void SetIrp(operand *result) {
8429         FENTRY;
8430         if (AOP_TYPE(result) == AOP_LIT) {
8431                 unsigned lit = (unsigned)operandLitValue(result);
8432                 if (lit&0x100)
8433                         emitSETIRP;
8434                 else
8435                         emitCLRIRP;
8436         } else {
8437                 if (PCOP(AOP(result))->type == PO_LITERAL) {
8438                         int addrs = PCOL(AOP(result))->lit;
8439                         if (addrs & 0x100)
8440                                 emitSETIRP;
8441                         else
8442                                 emitCLRIRP;
8443                 } else {
8444                         emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8445                         if(AOP_SIZE(result) > 1) {
8446                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8447                                 emitSETIRP;
8448                         }
8449                 }
8450         }
8451 }
8452
8453 static void
8454 setup_fsr (operand *ptr)
8455 {
8456   mov2w_op(ptr, 0);
8457   emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8458
8459   /* also setup-up IRP */
8460   SetIrp (ptr);
8461 }
8462
8463 /*-----------------------------------------------------------------*/
8464 /* emitPtrByteGet - emits code to get a byte into WREG from an     */
8465 /*                  arbitrary pointer (__code, __data, generic)    */
8466 /*-----------------------------------------------------------------*/
8467 static void
8468 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8469 {
8470     FENTRY;
8471     switch (p_type)
8472     {
8473     case POINTER:
8474     case FPOINTER:
8475       if (!alreadyAddressed) setup_fsr (src);
8476       emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8477       break;
8478     
8479     case CPOINTER:
8480       assert( AOP_SIZE(src) == 2 );
8481       mov2w_op(src, 0);
8482       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8483       mov2w_op(src, 1);
8484       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8485       emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE));   /* GPOINTER tag for __code space */
8486       call_libraryfunc ("__gptrget1");
8487       break;
8488     
8489     case GPOINTER:
8490       assert( AOP_SIZE(src) == 3 );
8491       mov2w_op(src, 0);
8492       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8493       mov2w_op(src, 1);
8494       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8495       mov2w_op(src, 2);
8496       call_libraryfunc ("__gptrget1");
8497       break;
8498     
8499     default:
8500       assert( !"unhandled pointer type" );
8501       break;
8502     }
8503 }
8504
8505 /*-----------------------------------------------------------------*/
8506 /* emitPtrByteSet - emits code to set a byte from src through a    */
8507 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR).       */
8508 /*-----------------------------------------------------------------*/
8509 static void
8510 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8511 {
8512     FENTRY;
8513     switch (p_type)
8514     {
8515     case POINTER:
8516     case FPOINTER:
8517       if (!alreadyAddressed) setup_fsr (dst);
8518       emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8519       break;
8520     
8521     case CPOINTER:
8522       assert( !"trying to assign to __code pointer" );
8523       break;
8524     
8525     case GPOINTER:
8526       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8527       mov2w_op(dst, 0);
8528       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8529       mov2w_op(dst, 1);
8530       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8531       mov2w_op(dst, 2);
8532       call_libraryfunc ("__gptrput1");
8533       break;
8534
8535     default:
8536       assert( !"unhandled pointer type" );
8537       break;
8538     }
8539 }
8540
8541 /*-----------------------------------------------------------------*/
8542 /* genUnpackBits - generates code for unpacking bits               */
8543 /*-----------------------------------------------------------------*/
8544 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8545 {    
8546   int rsize;            /* result size */
8547   sym_link *etype;      /* bitfield type information */
8548   int blen;             /* bitfield length */
8549   int bstr;             /* bitfield starting bit within byte */
8550
8551   FENTRY;
8552   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8553   etype = getSpec(operandType(result));
8554   rsize = getSize (operandType (result));
8555   blen = SPEC_BLEN (etype);
8556   bstr = SPEC_BSTR (etype);
8557
8558   /* single bit field case */
8559   if (blen == 1) {
8560     if (ifx) { /* that is for an if statement */
8561       pCodeOp *pcop;
8562       resolvedIfx rIfx;
8563       resolveIfx(&rIfx,ifx);
8564       if (ptype == -1) /* direct */
8565         pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8566       else
8567         pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8568       emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8569       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8570       ifx->generated=1;
8571     } else {
8572       int i;
8573       assert (!pic14_sameRegs (AOP(result), AOP(left)));
8574       for (i=0; i < AOP_SIZE(result); i++)
8575         emitpcode (POC_CLRF, popGet (AOP(result), i));
8576
8577       switch (ptype)
8578       {
8579       case -1:
8580         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8581         /* adjust result below */
8582         break;
8583         
8584       case POINTER:
8585       case FPOINTER:
8586       case GPOINTER:
8587       case CPOINTER:
8588         emitPtrByteGet (left, ptype, FALSE);
8589         emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8590         emitSKPZ;
8591         /* adjust result below */
8592         break;
8593         
8594       default:
8595         assert( !"unhandled pointer type" );
8596       } // switch
8597
8598       /* move sign-/zero extended bit to result */
8599       if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8600         emitpcode (POC_INCF, popGet (AOP(result), 0));
8601       } else {
8602         emitpcode (POC_DECF, popGet (AOP(result), 0));
8603       }
8604       addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8605     }
8606     return;
8607   }
8608   else if (blen <= 8 && ((blen + bstr) <= 8))
8609   {
8610     /* blen > 1 */
8611     int i;
8612
8613     for (i=0; i < AOP_SIZE(result); i++)
8614       emitpcode (POC_CLRF, popGet (AOP(result), i));
8615
8616     switch (ptype)
8617     {
8618     case -1:
8619       mov2w(AOP(left), 0);
8620       break;
8621       
8622     case POINTER:
8623     case FPOINTER:
8624     case GPOINTER:
8625     case CPOINTER:
8626       emitPtrByteGet (left, ptype, FALSE);
8627       break;
8628       
8629     default:
8630       assert( !"unhandled pointer type" );
8631     } // switch
8632
8633     if (blen < 8)
8634       emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8635     movwf(AOP(result), 0);
8636     AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8637
8638     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8639     {
8640       /* signed bitfield */
8641       assert (bstr + blen > 0);
8642       emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8643       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8644       emitpcode(POC_IORWF, popGet(AOP(result),0));
8645     }
8646     addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8647     return;
8648   }
8649
8650   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8651 }
8652
8653 #if 1
8654 /*-----------------------------------------------------------------*/
8655 /* genDataPointerGet - generates code when ptr offset is known     */
8656 /*-----------------------------------------------------------------*/
8657 static void genDataPointerGet (operand *left, 
8658         operand *result, 
8659         iCode *ic)
8660 {
8661         int size , offset = 0;
8662                 
8663         FENTRY;
8664         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8665         
8666         
8667         /* optimization - most of the time, left and result are the same
8668         * address, but different types. for the pic code, we could omit
8669         * the following
8670         */
8671         aopOp(result,ic,TRUE);
8672         
8673         if (pic14_sameRegs (AOP(left), AOP(result)))
8674                 return;
8675         
8676         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8677         
8678         //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8679         
8680         size = AOP_SIZE(result);
8681         if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8682         
8683         offset = 0;
8684         while (size--) {
8685                 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8686                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8687                 offset++;
8688         }
8689         
8690         freeAsmop(left,NULL,ic,TRUE);
8691         freeAsmop(result,NULL,ic,TRUE);
8692 }
8693 #endif
8694
8695 /*-----------------------------------------------------------------*/
8696 /* genNearPointerGet - pic14_emitcode for near pointer fetch       */
8697 /*-----------------------------------------------------------------*/
8698 static void genNearPointerGet (operand *left, 
8699                                                            operand *result, 
8700                                                            iCode *ic)
8701 {
8702         asmop *aop = NULL;
8703         sym_link *ltype = operandType(left);
8704         sym_link *rtype = operandType(result);
8705         sym_link *retype= getSpec(rtype);      /* bitfield type information */
8706         int direct = 0;
8707
8708         FENTRY;
8709         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8710         
8711         
8712         aopOp(left,ic,FALSE);
8713         
8714         /* if left is rematerialisable and
8715         result is not bit variable type and
8716         the left is pointer to data space i.e
8717         lower 128 bytes of space */
8718         if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8719                 !IS_BITVAR(retype)         &&
8720                 PIC_IS_DATA_PTR(ltype)) {
8721                 genDataPointerGet (left,result,ic);
8722                 return ;
8723         }
8724         
8725         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8726         aopOp (result,ic,FALSE);
8727         
8728         /* Check if can access directly instead of via a pointer */
8729         if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8730                 && AOP_SIZE(result) == 1)
8731         {
8732                 direct = 1;
8733         }
8734
8735         if (IS_BITFIELD(getSpec(operandType(result)))) 
8736         {
8737                 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8738                 goto release;
8739         }
8740         
8741         /* If the pointer value is not in a the FSR then need to put it in */
8742         /* Must set/reset IRP bit for use with FSR. */
8743         if (!direct)
8744           setup_fsr (left);
8745         
8746 //      sym_link *etype;
8747         /* if bitfield then unpack the bits */
8748         {
8749                 /* we have can just get the values */
8750                 int size = AOP_SIZE(result);
8751                 int offset = 0 ;  
8752                 
8753                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8754                 
8755                 while(size--) {
8756                         if (direct)
8757                                 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8758                         else
8759                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8760                         if (AOP_TYPE(result) == AOP_LIT) {
8761                                 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8762                         } else {
8763                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8764                         }
8765                         if (size && !direct)
8766                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8767                         offset++;
8768                 }
8769         }
8770         
8771         /* now some housekeeping stuff */
8772         if (aop) {
8773                 /* we had to allocate for this iCode */
8774                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8775                 freeAsmop(NULL,aop,ic,TRUE);
8776         } else { 
8777                 /* we did not allocate which means left
8778                 already in a pointer register, then
8779                 if size > 0 && this could be used again
8780                 we have to point it back to where it 
8781                 belongs */
8782                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8783                 if (AOP_SIZE(result) > 1 &&
8784                         !OP_SYMBOL(left)->remat &&
8785                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8786                         ic->depth )) {
8787                         int size = AOP_SIZE(result) - 1;
8788                         while (size--)
8789                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8790                 }
8791         }
8792         
8793 release:
8794         /* done */
8795         freeAsmop(left,NULL,ic,TRUE);
8796         freeAsmop(result,NULL,ic,TRUE);
8797
8798 }
8799
8800 #if 0
8801 /*-----------------------------------------------------------------*/
8802 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8803 /*-----------------------------------------------------------------*/
8804 static void genPagedPointerGet (operand *left, 
8805                                                                 operand *result, 
8806                                                                 iCode *ic)
8807 {
8808         asmop *aop = NULL;
8809         regs *preg = NULL ;
8810         char *rname ;
8811         sym_link *rtype, *retype;    
8812         
8813         FENTRY;
8814         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8815         
8816         rtype = operandType(result);
8817         retype= getSpec(rtype);
8818         
8819         aopOp(left,ic,FALSE);
8820         
8821         /* if the value is already in a pointer register
8822         then don't need anything more */
8823         if (!AOP_INPREG(AOP(left))) {
8824                 /* otherwise get a free pointer register */
8825                 aop = newAsmop(0);
8826                 preg = getFreePtr(ic,&aop,FALSE);
8827                 pic14_emitcode("mov","%s,%s",
8828                         preg->name,
8829                         aopGet(AOP(left),0,FALSE,TRUE));
8830                 rname = preg->name ;
8831         } else
8832                 rname = aopGet(AOP(left),0,FALSE,FALSE);
8833         
8834         freeAsmop(left,NULL,ic,TRUE);
8835         aopOp (result,ic,FALSE);
8836         
8837         /* if bitfield then unpack the bits */
8838         if (IS_BITFIELD(retype)) 
8839                 genUnpackBits (result,left,rname,PPOINTER,0);
8840         else {
8841                 /* we have can just get the values */
8842                 int size = AOP_SIZE(result);
8843                 int offset = 0 ;  
8844                 
8845                 while (size--) {
8846                         
8847                         pic14_emitcode("movx","a,@%s",rname);
8848                         aopPut(AOP(result),"a",offset);
8849                         
8850                         offset++ ;
8851                         
8852                         if (size)
8853                                 pic14_emitcode("inc","%s",rname);
8854                 }
8855         }
8856         
8857         /* now some housekeeping stuff */
8858         if (aop) {
8859                 /* we had to allocate for this iCode */
8860                 freeAsmop(NULL,aop,ic,TRUE);
8861         } else { 
8862         /* we did not allocate which means left
8863         already in a pointer register, then
8864         if size > 0 && this could be used again
8865         we have to point it back to where it 
8866                 belongs */
8867                 if (AOP_SIZE(result) > 1 &&
8868                         !OP_SYMBOL(left)->remat &&
8869                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8870                         ic->depth )) {
8871                         int size = AOP_SIZE(result) - 1;
8872                         while (size--)
8873                                 pic14_emitcode("dec","%s",rname);
8874                 }
8875         }
8876         
8877         /* done */
8878         freeAsmop(result,NULL,ic,TRUE);
8879         
8880         
8881 }
8882
8883 /*-----------------------------------------------------------------*/
8884 /* genFarPointerGet - gget value from far space                    */
8885 /*-----------------------------------------------------------------*/
8886 static void genFarPointerGet (operand *left,
8887                                                           operand *result, iCode *ic)
8888 {
8889         int size, offset ;
8890         sym_link *retype = getSpec(operandType(result));
8891         
8892         FENTRY;
8893         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8894         
8895         aopOp(left,ic,FALSE);
8896         
8897         /* if the operand is already in dptr 
8898         then we do nothing else we move the value to dptr */
8899         if (AOP_TYPE(left) != AOP_STR) {
8900                 /* if this is remateriazable */
8901                 if (AOP_TYPE(left) == AOP_IMMD)
8902                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8903                 else { /* we need to get it byte by byte */
8904                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8905                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8906                         if (options.model == MODEL_FLAT24)
8907                         {
8908                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8909                         }
8910                 }
8911         }
8912         /* so dptr know contains the address */
8913         freeAsmop(left,NULL,ic,TRUE);
8914         aopOp(result,ic,FALSE);
8915         
8916         /* if bit then unpack */
8917         if (IS_BITFIELD(retype)) 
8918                 genUnpackBits(result,left,"dptr",FPOINTER,0);
8919         else {
8920                 size = AOP_SIZE(result);
8921                 offset = 0 ;
8922                 
8923                 while (size--) {
8924                         pic14_emitcode("movx","a,@dptr");
8925                         aopPut(AOP(result),"a",offset++);
8926                         if (size)
8927                                 pic14_emitcode("inc","dptr");
8928                 }
8929         }
8930         
8931         freeAsmop(result,NULL,ic,TRUE);
8932 }
8933 #endif
8934
8935 #if 0
8936 /*-----------------------------------------------------------------*/
8937 /* genCodePointerGet - get value from code space                  */
8938 /*-----------------------------------------------------------------*/
8939 static void genCodePointerGet (operand *left,
8940                                                            operand *result, iCode *ic)
8941 {
8942         int size, offset ;
8943         sym_link *retype = getSpec(operandType(result));
8944         
8945         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8946         
8947         aopOp(left,ic,FALSE);
8948         
8949         /* if the operand is already in dptr 
8950         then we do nothing else we move the value to dptr */
8951         if (AOP_TYPE(left) != AOP_STR) {
8952                 /* if this is remateriazable */
8953                 if (AOP_TYPE(left) == AOP_IMMD)
8954                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8955                 else { /* we need to get it byte by byte */
8956                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8957                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8958                         if (options.model == MODEL_FLAT24)
8959                         {
8960                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8961                         }
8962                 }
8963         }
8964         /* so dptr know contains the address */
8965         freeAsmop(left,NULL,ic,TRUE);
8966         aopOp(result,ic,FALSE);
8967         
8968         /* if bit then unpack */
8969         if (IS_BITFIELD(retype)) 
8970                 genUnpackBits(result,left,"dptr",CPOINTER,0);
8971         else {
8972                 size = AOP_SIZE(result);
8973                 offset = 0 ;
8974                 
8975                 while (size--) {
8976                         pic14_emitcode("clr","a");
8977                         pic14_emitcode("movc","a,@a+dptr");
8978                         aopPut(AOP(result),"a",offset++);
8979                         if (size)
8980                                 pic14_emitcode("inc","dptr");
8981                 }
8982         }
8983         
8984         freeAsmop(result,NULL,ic,TRUE);
8985 }
8986 #endif
8987 /*-----------------------------------------------------------------*/
8988 /* genGenPointerGet - gget value from generic pointer space        */
8989 /*-----------------------------------------------------------------*/
8990 static void genGenPointerGet (operand *left,
8991                                                           operand *result, iCode *ic)
8992 {
8993         FENTRY;
8994         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8995         aopOp(left,ic,FALSE);
8996         aopOp(result,ic,FALSE);
8997         
8998         
8999         DEBUGpic14_AopType(__LINE__,left,NULL,result);
9000
9001         if (IS_BITFIELD(getSpec(operandType(result))))
9002         {
9003           genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
9004           return;
9005         }
9006
9007         {
9008           /* emit call to __gptrget */
9009           char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
9010           int size = AOP_SIZE(result);
9011           int idx = 0;
9012
9013           assert (size > 0 && size <= 4);
9014
9015           /* pass arguments */
9016           assert (AOP_SIZE(left) == 3);
9017           mov2w(AOP(left), 0);
9018           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9019           mov2w(AOP(left), 1);
9020           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9021           mov2w(AOP(left), 2);
9022           call_libraryfunc (func[size]);
9023           
9024           /* save result */
9025           movwf (AOP(result), --size);
9026           while (size--) {
9027             emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
9028             movwf (AOP(result), size);
9029           } // while
9030         }
9031         
9032         freeAsmop(left,NULL,ic,TRUE);
9033         freeAsmop(result,NULL,ic,TRUE);
9034         
9035 }
9036
9037 /*-----------------------------------------------------------------*/
9038 /* genConstPointerGet - get value from const generic pointer space */
9039 /*-----------------------------------------------------------------*/
9040 static void genConstPointerGet (operand *left,
9041                                                                 operand *result, iCode *ic)
9042 {
9043         //sym_link *retype = getSpec(operandType(result));
9044         #if 0
9045         symbol *albl, *blbl;//, *clbl;
9046         pCodeOp *pcop;
9047         #endif
9048         PIC_OPCODE poc;
9049         int i, size, lit;
9050         
9051         FENTRY;
9052         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9053         aopOp(left,ic,FALSE);
9054         aopOp(result,ic,FALSE);
9055         
9056         size = AOP_SIZE(result);
9057         
9058         DEBUGpic14_AopType(__LINE__,left,NULL,result);
9059         
9060         DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9061
9062         lit = op_isLitLike (left);
9063         poc = lit ? POC_MOVLW : POC_MOVFW;
9064
9065         if (IS_BITFIELD(getSpec(operandType(result))))
9066         {
9067                 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9068                 goto release;
9069         }
9070
9071         {
9072                 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9073                 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9074                 assert (size > 0 && size <= 4);
9075                 
9076                 mov2w_op(left, 0);
9077                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9078                 mov2w_op(left, 1);
9079                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9080                 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9081                 call_libraryfunc (func[size]);
9082
9083                 movwf(AOP(result),size-1);
9084                 for (i = 1; i < size; i++)
9085                 {
9086                         emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9087                         movwf(AOP(result),size - 1 - i);
9088                 } // for
9089         }
9090         
9091 release:
9092         freeAsmop(left,NULL,ic,TRUE);
9093         freeAsmop(result,NULL,ic,TRUE);
9094         
9095 }
9096 /*-----------------------------------------------------------------*/
9097 /* genPointerGet - generate code for pointer get                   */
9098 /*-----------------------------------------------------------------*/
9099 static void genPointerGet (iCode *ic)
9100 {
9101         operand *left, *result ;
9102         sym_link *type, *etype;
9103         int p_type = -1;
9104         
9105         FENTRY;
9106         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9107         
9108         left = IC_LEFT(ic);
9109         result = IC_RESULT(ic) ;
9110         
9111         /* depending on the type of pointer we need to
9112         move it to the correct pointer register */
9113         type = operandType(left);
9114         etype = getSpec(type);
9115         
9116         if (IS_PTR_CONST(type))
9117                 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9118         
9119         /* if left is of type of pointer then it is simple */
9120         if (IS_PTR(type) && !IS_FUNC(type->next)) 
9121                 p_type = DCL_TYPE(type);
9122         else {
9123                 /* we have to go by the storage class */
9124                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9125                 
9126                 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9127                 
9128                 if (SPEC_OCLS(etype)->codesp ) {
9129                         DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9130                         //p_type = CPOINTER ; 
9131                 }
9132                 else
9133                         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9134                                 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9135                         /*p_type = FPOINTER ;*/ 
9136                         else
9137                                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9138                                         DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9139                                 /*        p_type = PPOINTER; */
9140                                 else
9141                                         if (SPEC_OCLS(etype) == idata )
9142                                                 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9143                                         /*      p_type = IPOINTER; */
9144                                         else
9145                                                 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9146                                         /*      p_type = POINTER ; */
9147         }
9148         
9149         /* now that we have the pointer type we assign
9150         the pointer values */
9151         switch (p_type) {
9152                 
9153         case POINTER: 
9154         case FPOINTER:
9155         //case IPOINTER:
9156                 genNearPointerGet (left,result,ic);
9157                 break;
9158 /*
9159         case PPOINTER:
9160                 genPagedPointerGet(left,result,ic);
9161                 break;
9162                 
9163         case FPOINTER:
9164                 genFarPointerGet (left,result,ic);
9165                 break;
9166 */              
9167         case CPOINTER:
9168                 genConstPointerGet (left,result,ic);
9169                 break;
9170                 
9171         case GPOINTER:
9172                 genGenPointerGet (left,result,ic);
9173                 break;
9174         default:
9175                 assert ( !"unhandled pointer type" );
9176                 break;
9177         }
9178         
9179 }
9180
9181 /*-----------------------------------------------------------------*/
9182 /* genPackBits - generates code for packed bit storage             */
9183 /*-----------------------------------------------------------------*/
9184 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9185 {
9186   int blen;             /* bitfield length */
9187   int bstr;             /* bitfield starting bit within byte */
9188   int litval;           /* source literal value (if AOP_LIT) */
9189   unsigned char mask;   /* bitmask within current byte */
9190
9191   FENTRY;
9192   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9193
9194   blen = SPEC_BLEN (etype);
9195   bstr = SPEC_BSTR (etype);
9196
9197   /* If the bitfield length is less than a byte and does not cross byte boundaries */
9198   if ((blen <= 8) && ((bstr + blen) <= 8))
9199   {
9200     mask = ((unsigned char) (0xFF << (blen + bstr)) |
9201             (unsigned char) (0xFF >> (8 - bstr)));
9202
9203     if (AOP_TYPE (right) == AOP_LIT)
9204     {
9205       /* Case with a bitfield length <8 and literal source */
9206       int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9207       if (blen == 1) {
9208         pCodeOp *pcop;
9209         
9210         switch (p_type)
9211         {
9212         case -1:
9213           if (AOP(result)->type == AOP_PCODE)
9214             pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9215           else
9216             pcop = popGet(AOP(result),0);
9217           emitpcode(lit?POC_BSF:POC_BCF,pcop);
9218           break;
9219         
9220         case POINTER:
9221         case FPOINTER:
9222           setup_fsr (result);
9223           emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9224           break;
9225         
9226         case CPOINTER:
9227           assert( !"trying to assign to bitfield via pointer to __code space" );
9228           break;
9229         
9230         case GPOINTER:
9231           emitPtrByteGet(result, p_type, FALSE);
9232           if (lit) {
9233             emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9234           } else {
9235             emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9236           }
9237           emitPtrByteSet(result, p_type, TRUE);
9238           break;
9239         
9240         default:
9241           assert( !"unhandled pointer type" );
9242           break;
9243         } // switch (p_type)
9244       } else {
9245         /* blen > 1 */
9246         litval = lit << bstr;
9247         litval &= (~mask) & 0x00ff;
9248         
9249         switch (p_type)
9250         {
9251         case -1:
9252           mov2w (AOP(result), 0);
9253           if ((litval|mask) != 0x00ff)
9254             emitpcode(POC_ANDLW, popGetLit (mask));
9255           if (litval != 0x00)
9256             emitpcode(POC_IORLW, popGetLit (litval));
9257           movwf (AOP(result), 0);
9258           break;
9259         
9260         case POINTER:
9261         case FPOINTER:
9262         case GPOINTER:
9263           emitPtrByteGet(result, p_type, FALSE);
9264           if ((litval|mask) != 0x00ff)
9265             emitpcode(POC_ANDLW, popGetLit (mask));
9266           if (litval != 0x00)
9267             emitpcode(POC_IORLW, popGetLit (litval));
9268           emitPtrByteSet(result, p_type, TRUE);
9269           break;
9270         
9271         case CPOINTER:
9272           assert( !"trying to assign to bitfield via pointer to __code space" );
9273           break;
9274         
9275         default:
9276           assert( !"unhandled pointer type" );
9277           break;
9278         } // switch
9279       } // if (blen > 1)
9280     }
9281     else
9282     {
9283       /* right is no literal */
9284       if (blen==1) {
9285         switch (p_type)
9286         {
9287         case -1:
9288           /* Note more efficient code, of pre clearing bit then only setting it if required,
9289            * can only be done if it is known that the result is not a SFR */
9290           emitpcode(POC_RRFW,popGet(AOP(right),0));
9291           emitSKPC;
9292           emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9293           emitSKPNC;
9294           emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9295           break;
9296         
9297         case POINTER:
9298         case FPOINTER:
9299         case GPOINTER:
9300           emitPtrByteGet (result, p_type, FALSE);
9301           emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9302           emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9303           emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9304           emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9305           emitPtrByteSet (result, p_type, TRUE);
9306           break;
9307         
9308         case CPOINTER:
9309           assert( !"trying to assign to bitfield via pointer to __code space" );
9310           break;
9311         
9312         default:
9313           assert( !"unhandled pointer type" );
9314           break;
9315         } // switch
9316         return;
9317       } else {
9318         /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9319         pCodeOp *temp = popGetTempReg ();
9320
9321         mov2w (AOP(right), 0);
9322         if (blen < 8) {
9323           emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9324         }
9325         emitpcode(POC_MOVWF, temp);
9326         if (bstr) {
9327           AccLsh (temp, bstr);
9328         }
9329         
9330         switch (p_type)
9331         {
9332         case -1:
9333           mov2w (AOP(result), 0);
9334           emitpcode(POC_ANDLW, popGetLit (mask));
9335           emitpcode(POC_IORFW, temp);
9336           movwf (AOP(result), 0);
9337           break;
9338         
9339         case POINTER:
9340         case FPOINTER:
9341         case GPOINTER:
9342           emitPtrByteGet (result, p_type, FALSE);
9343           emitpcode(POC_ANDLW, popGetLit (mask));
9344           emitpcode(POC_IORFW, temp);
9345           emitPtrByteSet (result, p_type, TRUE);
9346           break;
9347         
9348         case CPOINTER:
9349           assert( !"trying to assign to bitfield via pointer to __code space" );
9350           break;
9351         
9352         default:
9353           assert( !"unhandled pointer type" );
9354           break;
9355         } // switch
9356
9357         popReleaseTempReg (temp);
9358       } // if (blen > 1)
9359     } // if (AOP(right)->type != AOP_LIT)
9360     return;
9361   } // if (blen <= 8 && ((blen + bstr) <= 8))
9362
9363   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9364 }
9365
9366 unsigned long
9367 bitpatternFromVal (value *val)
9368 {
9369   union {
9370     float d;
9371     uint32_t l;
9372   } float_long;
9373
9374   assert (sizeof (float) == sizeof (uint32_t));
9375
9376   //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));
9377
9378   switch (SPEC_NOUN(val->type))
9379   {
9380   case V_INT:
9381   case V_CHAR:
9382     return (unsigned long)floatFromVal (val);
9383     
9384   case V_FLOAT:
9385   case V_DOUBLE:
9386     float_long.d = floatFromVal (val);
9387     return float_long.l;
9388     
9389   default:
9390     assert( !"unhandled value type" );
9391     break;
9392   }
9393
9394   float_long.d = floatFromVal (val);
9395   return float_long.l;
9396 }
9397
9398 /*-----------------------------------------------------------------*/
9399 /* genDataPointerSet - remat pointer to data space                 */
9400 /*-----------------------------------------------------------------*/
9401 static void genDataPointerSet(operand *right,
9402         operand *result,
9403         iCode *ic)
9404 {
9405         int size, offset = 0 ;
9406         int ressize;
9407         
9408         FENTRY;
9409         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9410         aopOp(right,ic,FALSE);
9411         aopOp(result,ic,FALSE);
9412         
9413         assert (IS_SYMOP(result));
9414         assert (IS_PTR(OP_SYM_TYPE(result)));
9415         
9416         size = AOP_SIZE(right);
9417         ressize = getSize(OP_SYM_ETYPE(result));
9418         if (size > ressize) size = ressize;
9419         //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9420         
9421         //assert( !"what's going on here?" );
9422
9423         /*
9424         if ( AOP_TYPE(result) == AOP_PCODE) {
9425         fprintf(stderr,"genDataPointerSet   %s, %d\n",
9426         AOP(result)->aopu.pcop->name,
9427         PCOI(AOP(result)->aopu.pcop)->offset);
9428         }
9429         */
9430         
9431         // tsd, was l+1 - the underline `_' prefix was being stripped
9432         while (size--) {
9433                 emitpComment ("%s:%u: size=%d/%d, offset=%i", __FILE__,__LINE__, size, ressize, offset);
9434                 
9435                 if (AOP_TYPE(right) == AOP_LIT) {
9436                         /* XXX: might be float... */
9437                         unsigned int lit = bitpatternFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9438                         lit = lit >> (8*offset);
9439                         //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9440                         if(lit&0xff) {
9441                                 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9442                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9443                         } else {
9444                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9445                         }
9446                 } else {
9447                         //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9448                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9449                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9450                 }
9451                 
9452                 offset++;
9453         }
9454         
9455         freeAsmop(right,NULL,ic,TRUE);
9456         freeAsmop(result,NULL,ic,TRUE);
9457 }
9458
9459 /*-----------------------------------------------------------------*/
9460 /* genNearPointerSet - pic14_emitcode for near pointer put         */
9461 /*-----------------------------------------------------------------*/
9462 static void genNearPointerSet (operand *right,
9463                                                            operand *result, 
9464                                                            iCode *ic)
9465 {
9466         asmop *aop = NULL;
9467         sym_link *ptype = operandType(result);
9468         sym_link *retype = getSpec(operandType(right));
9469         sym_link *letype = getSpec(ptype);
9470         int direct = 0;
9471         
9472         
9473         FENTRY;
9474         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9475         aopOp(result,ic,FALSE);
9476         
9477 #if 1
9478         /* if the result is rematerializable &
9479         in data space & not a bit variable */
9480         //if (AOP_TYPE(result) == AOP_IMMD &&
9481         if (AOP_TYPE(result) == AOP_PCODE &&
9482                 PIC_IS_DATA_PTR(ptype) &&
9483                 !IS_BITVAR (retype) &&
9484                 !IS_BITVAR (letype)) {
9485                 genDataPointerSet (right,result,ic);
9486                 freeAsmop(result,NULL,ic,TRUE);
9487                 return;
9488         }
9489 #endif
9490
9491         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9492         aopOp(right,ic,FALSE);
9493         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9494         
9495         /* Check if can access directly instead of via a pointer */
9496         if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9497                 direct = 1;
9498         }
9499         
9500         if (IS_BITFIELD (letype))
9501         {
9502           genPackBits (letype, result, right, direct?-1:POINTER);
9503           return;
9504         }
9505         
9506         /* If the pointer value is not in a the FSR then need to put it in */
9507         /* Must set/reset IRP bit for use with FSR. */
9508         /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9509         if (!direct)
9510                 setup_fsr (result);
9511
9512         {
9513                 /* we have can just get the values */
9514                 int size = AOP_SIZE(right);
9515                 int offset = 0 ;    
9516                 
9517                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9518                 while (size--) {
9519                         char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9520                         if (*l == '@' ) {
9521                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9522                         } else {
9523                                 if (AOP_TYPE(right) == AOP_LIT) {
9524                                         emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9525                                 } else {
9526                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9527                                 }
9528                                 if (direct)
9529                                         emitpcode(POC_MOVWF,popGet(AOP(result),0));
9530                                 else
9531                                         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9532                         }
9533                         if (size && !direct)
9534                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9535                         offset++;
9536                 }
9537         }
9538         
9539         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9540         /* now some housekeeping stuff */
9541         if (aop) {
9542                 /* we had to allocate for this iCode */
9543                 freeAsmop(NULL,aop,ic,TRUE);
9544         } else { 
9545                 /* we did not allocate which means left
9546                 already in a pointer register, then
9547                 if size > 0 && this could be used again
9548                 we have to point it back to where it 
9549                 belongs */
9550                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9551                 if (AOP_SIZE(right) > 1 &&
9552                         !OP_SYMBOL(result)->remat &&
9553                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9554                         ic->depth )) {
9555                         int size = AOP_SIZE(right) - 1;
9556                         while (size--)
9557                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9558                 }
9559         }
9560         
9561         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9562         /* done */
9563
9564         freeAsmop(right,NULL,ic,TRUE);
9565         freeAsmop(result,NULL,ic,TRUE);
9566 }
9567
9568 #if 0
9569 /*-----------------------------------------------------------------*/
9570 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
9571 /*-----------------------------------------------------------------*/
9572 static void genPagedPointerSet (operand *right,
9573                                                                 operand *result, 
9574                                                                 iCode *ic)
9575 {
9576         asmop *aop = NULL;
9577         regs *preg = NULL ;
9578         char *rname , *l;
9579         sym_link *retype;
9580         
9581         FENTRY;
9582         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9583         
9584         retype= getSpec(operandType(right));
9585         
9586         aopOp(result,ic,FALSE);
9587         
9588         /* if the value is already in a pointer register
9589         then don't need anything more */
9590         if (!AOP_INPREG(AOP(result))) {
9591                 /* otherwise get a free pointer register */
9592                 aop = newAsmop(0);
9593                 preg = getFreePtr(ic,&aop,FALSE);
9594                 pic14_emitcode("mov","%s,%s",
9595                         preg->name,
9596                         aopGet(AOP(result),0,FALSE,TRUE));
9597                 rname = preg->name ;
9598         } else
9599                 rname = aopGet(AOP(result),0,FALSE,FALSE);
9600         
9601         freeAsmop(result,NULL,ic,TRUE);
9602         aopOp (right,ic,FALSE);
9603         
9604         /* if bitfield then unpack the bits */
9605         if (IS_BITFIELD(retype)) 
9606                 genPackBits (retype,result,right,rname,PPOINTER);
9607         else {
9608                 /* we have can just get the values */
9609                 int size = AOP_SIZE(right);
9610                 int offset = 0 ;  
9611                 
9612                 while (size--) {
9613                         l = aopGet(AOP(right),offset,FALSE,TRUE);
9614                         
9615                         MOVA(l);
9616                         pic14_emitcode("movx","@%s,a",rname);
9617                         
9618                         if (size)
9619                                 pic14_emitcode("inc","%s",rname);
9620                         
9621                         offset++;
9622                 }
9623         }
9624         
9625         /* now some housekeeping stuff */
9626         if (aop) {
9627                 /* we had to allocate for this iCode */
9628                 freeAsmop(NULL,aop,ic,TRUE);
9629         } else { 
9630         /* we did not allocate which means left
9631         already in a pointer register, then
9632         if size > 0 && this could be used again
9633         we have to point it back to where it 
9634                 belongs */
9635                 if (AOP_SIZE(right) > 1 &&
9636                         !OP_SYMBOL(result)->remat &&
9637                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9638                         ic->depth )) {
9639                         int size = AOP_SIZE(right) - 1;
9640                         while (size--)
9641                                 pic14_emitcode("dec","%s",rname);
9642                 }
9643         }
9644         
9645         /* done */
9646         freeAsmop(right,NULL,ic,TRUE);
9647         
9648         
9649 }
9650
9651 /*-----------------------------------------------------------------*/
9652 /* genFarPointerSet - set value from far space                     */
9653 /*-----------------------------------------------------------------*/
9654 static void genFarPointerSet (operand *right,
9655                                                           operand *result, iCode *ic)
9656 {
9657         int size, offset ;
9658         sym_link *retype = getSpec(operandType(right));
9659         
9660         FENTRY;
9661         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9662         aopOp(result,ic,FALSE);
9663         
9664         /* if the operand is already in dptr 
9665         then we do nothing else we move the value to dptr */
9666         if (AOP_TYPE(result) != AOP_STR) {
9667                 /* if this is remateriazable */
9668                 if (AOP_TYPE(result) == AOP_IMMD)
9669                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9670                 else { /* we need to get it byte by byte */
9671                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9672                         pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9673                         if (options.model == MODEL_FLAT24)
9674                         {
9675                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9676                         }
9677                 }
9678         }
9679         /* so dptr know contains the address */
9680         freeAsmop(result,NULL,ic,TRUE);
9681         aopOp(right,ic,FALSE);
9682         
9683         /* if bit then unpack */
9684         if (IS_BITFIELD(retype)) 
9685                 genPackBits(retype,result,right,"dptr",FPOINTER);
9686         else {
9687                 size = AOP_SIZE(right);
9688                 offset = 0 ;
9689                 
9690                 while (size--) {
9691                         char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9692                         MOVA(l);
9693                         pic14_emitcode("movx","@dptr,a");
9694                         if (size)
9695                                 pic14_emitcode("inc","dptr");
9696                 }
9697         }
9698         
9699         freeAsmop(right,NULL,ic,TRUE);
9700 }
9701 #endif
9702
9703 /*-----------------------------------------------------------------*/
9704 /* genGenPointerSet - set value from generic pointer space         */
9705 /*-----------------------------------------------------------------*/
9706 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9707 {
9708         sym_link *retype = getSpec(operandType(result));
9709         
9710         FENTRY;
9711         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9712         aopOp(right,ic,FALSE);
9713         aopOp(result,ic,FALSE);
9714
9715         
9716         DEBUGpic14_AopType(__LINE__,right,NULL,result);
9717
9718         if (IS_BITFIELD(retype))
9719         {
9720           genPackBits (retype, result, right, GPOINTER);
9721           return;
9722         }
9723
9724         {
9725           /* emit call to __gptrput */
9726           char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9727           int size = AOP_SIZE(right);
9728           int idx = 0;
9729
9730           assert (size == getSize(OP_SYM_ETYPE(result)));
9731           assert (size > 0 && size <= 4);
9732
9733           /* pass arguments */
9734           /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9735           {
9736             int off = size;
9737             idx = 2;
9738             while (off--)
9739             {
9740               mov2w_op (right, off);
9741               emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9742             }
9743             idx = 0;
9744           }
9745           /* - address */
9746           assert (AOP_SIZE(result) == 3);
9747           mov2w(AOP(result), 0);
9748           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9749           mov2w(AOP(result), 1);
9750           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9751           mov2w(AOP(result), 2);
9752           call_libraryfunc (func[size]);
9753         }
9754         
9755         freeAsmop(right,NULL,ic,TRUE);
9756         freeAsmop(result,NULL,ic,TRUE);
9757 }
9758
9759 /*-----------------------------------------------------------------*/
9760 /* genPointerSet - stores the value into a pointer location        */
9761 /*-----------------------------------------------------------------*/
9762 static void genPointerSet (iCode *ic)
9763 {    
9764         operand *right, *result ;
9765         sym_link *type, *etype;
9766         int p_type;
9767         
9768         FENTRY;
9769         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9770         
9771         right = IC_RIGHT(ic);
9772         result = IC_RESULT(ic) ;
9773         
9774         /* depending on the type of pointer we need to
9775         move it to the correct pointer register */
9776         type = operandType(result);
9777         etype = getSpec(type);
9778         /* if left is of type of pointer then it is simple */
9779         if (IS_PTR(type) && !IS_FUNC(type->next)) {
9780                 p_type = DCL_TYPE(type);
9781         }
9782         else {
9783                 /* we have to go by the storage class */
9784                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9785                 
9786                 /*  if (SPEC_OCLS(etype)->codesp ) { */
9787                 /*      p_type = CPOINTER ;  */
9788                 /*  } */
9789                 /*  else */
9790                 /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9791                 /*    p_type = FPOINTER ; */
9792                 /*      else */
9793                 /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9794                 /*        p_type = PPOINTER ; */
9795                 /*    else */
9796                 /*        if (SPEC_OCLS(etype) == idata ) */
9797                 /*      p_type = IPOINTER ; */
9798                 /*        else */
9799                 /*      p_type = POINTER ; */
9800         }
9801         
9802         /* now that we have the pointer type we assign
9803         the pointer values */
9804         switch (p_type) {
9805                 
9806         case POINTER:
9807         case FPOINTER:
9808         //case IPOINTER:
9809                 genNearPointerSet (right,result,ic);
9810                 break;
9811 /*
9812         case PPOINTER:
9813                 genPagedPointerSet (right,result,ic);
9814                 break;
9815                 
9816         case FPOINTER:
9817                 genFarPointerSet (right,result,ic);
9818                 break;
9819 */
9820         case GPOINTER:
9821                 genGenPointerSet (right,result,ic);
9822                 break;
9823                 
9824         default:
9825                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9826                         "genPointerSet: illegal pointer type");
9827         }
9828 }
9829
9830 /*-----------------------------------------------------------------*/
9831 /* genIfx - generate code for Ifx statement                        */
9832 /*-----------------------------------------------------------------*/
9833 static void genIfx (iCode *ic, iCode *popIc)
9834 {
9835         operand *cond = IC_COND(ic);
9836         int isbit =0;
9837         
9838         FENTRY;
9839         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9840         
9841         aopOp(cond,ic,FALSE);
9842         
9843         /* get the value into acc */
9844         if (AOP_TYPE(cond) != AOP_CRY)
9845                 pic14_toBoolean(cond);
9846         else
9847                 isbit = 1;
9848         
9849         /* if there was something to be popped then do it */
9850         if (popIc)
9851                 genIpop(popIc);
9852         
9853         if (isbit)
9854         {
9855                 /* This assumes that CARRY is set iff cond is true */
9856                 if (IC_TRUE(ic))
9857                 {
9858                         assert (!IC_FALSE(ic));
9859                         emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9860                         //emitSKPNC;
9861                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9862                 } else {
9863                         assert (IC_FALSE(ic));
9864                         emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9865                         //emitSKPC;
9866                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9867                 }
9868                 if (0)
9869                 {
9870                         static int hasWarned = 0;
9871                         if (!hasWarned)
9872                         {
9873                                 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9874                                 hasWarned = 1;
9875                         }
9876                 }
9877         }
9878         else
9879         {
9880                 /* now Z is set iff !cond */
9881                 if (IC_TRUE(ic))
9882                 {
9883                         assert (!IC_FALSE(ic));
9884                         emitSKPZ;
9885                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9886                 } else {
9887                         emitSKPNZ;
9888                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9889                 }
9890         }
9891         
9892         ic->generated = 1;
9893         
9894         /* the result is now in the accumulator */
9895         freeAsmop(cond,NULL,ic,TRUE);
9896 }
9897
9898 /*-----------------------------------------------------------------*/
9899 /* genAddrOf - generates code for address of                       */
9900 /*-----------------------------------------------------------------*/
9901 static void genAddrOf (iCode *ic)
9902 {
9903         operand *right, *result, *left;
9904         int size, offset ;
9905         
9906         FENTRY;
9907         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9908         
9909         
9910         //aopOp(IC_RESULT(ic),ic,FALSE);
9911         
9912         aopOp((left=IC_LEFT(ic)),ic,FALSE);
9913         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9914         aopOp((result=IC_RESULT(ic)),ic,TRUE);
9915         
9916         DEBUGpic14_AopType(__LINE__,left,right,result);
9917         assert (IS_SYMOP (left));
9918         
9919         /* sanity check: generic pointers to code space are not yet supported,
9920          * pionters to codespace must not be assigned addresses of __data values. */
9921  #if 0
9922         fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9923         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)));
9924         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)));
9925         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)));
9926         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)));
9927 #endif
9928
9929         if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9930           fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9931                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9932                 OP_SYMBOL(left)->name);
9933         } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9934           fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9935                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9936                 OP_SYMBOL(left)->name);
9937         }
9938         
9939         size = AOP_SIZE(IC_RESULT(ic));
9940         if (IS_GENPTR(OP_SYM_TYPE(result))) {
9941                 /* strip tag */
9942                 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9943         }
9944         offset = 0;
9945         
9946         while (size--) {
9947                 /* fixing bug #863624, reported from (errolv) */
9948                 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9949                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9950                 
9951 #if 0
9952                 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9953                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9954 #endif
9955                 offset++;
9956         }
9957
9958         if (IS_GENPTR(OP_SYM_TYPE(result)))
9959         {
9960                 /* provide correct tag */
9961                 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9962                 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9963                 movwf (AOP(result), 2);
9964         }
9965         
9966         freeAsmop(left,NULL,ic,FALSE);
9967         freeAsmop(result,NULL,ic,TRUE);
9968         
9969 }
9970
9971 #if 0
9972 /*-----------------------------------------------------------------*/
9973 /* genFarFarAssign - assignment when both are in far space         */
9974 /*-----------------------------------------------------------------*/
9975 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9976 {
9977         int size = AOP_SIZE(right);
9978         int offset = 0;
9979         char *l ;
9980         /* first push the right side on to the stack */
9981         while (size--) {
9982                 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9983                 MOVA(l);
9984                 pic14_emitcode ("push","acc");
9985         }
9986         
9987         freeAsmop(right,NULL,ic,FALSE);
9988         /* now assign DPTR to result */
9989         aopOp(result,ic,FALSE);
9990         size = AOP_SIZE(result);
9991         while (size--) {
9992                 pic14_emitcode ("pop","acc");
9993                 aopPut(AOP(result),"a",--offset);
9994         }
9995         freeAsmop(result,NULL,ic,FALSE);
9996         
9997 }
9998 #endif
9999
10000 /*-----------------------------------------------------------------*/
10001 /* genAssign - generate code for assignment                        */
10002 /*-----------------------------------------------------------------*/
10003 static void genAssign (iCode *ic)
10004 {
10005         operand *result, *right;
10006         int size, offset,know_W;
10007         unsigned long lit = 0L;
10008         
10009         result = IC_RESULT(ic);
10010         right  = IC_RIGHT(ic) ;
10011         
10012         FENTRY;
10013         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10014         
10015         /* if they are the same */
10016         if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10017                 return ;
10018         
10019         aopOp(right,ic,FALSE);
10020         aopOp(result,ic,TRUE);
10021         
10022         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10023         
10024         /* if they are the same registers */
10025         if (pic14_sameRegs(AOP(right),AOP(result)))
10026                 goto release;
10027
10028         /* special case: assign from __code */
10029         if (!IS_ITEMP(right)                            /* --> iTemps never reside in __code */
10030                 && IS_SYMOP (right)                     /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
10031                 && !IS_FUNC(OP_SYM_TYPE(right))         /* --> we would want its address instead of the first instruction */
10032                 && !IS_CODEPTR(OP_SYM_TYPE(right))      /* --> get symbols address instread */
10033                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
10034         {
10035           emitpComment ("genAssign from CODESPACE");
10036           genConstPointerGet (right, result, ic);
10037           goto release;
10038         }
10039         
10040         /* just for symmetry reasons... */
10041         if (!IS_ITEMP(result)
10042                 && IS_SYMOP (result)
10043                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
10044         {
10045           assert ( !"cannot write to CODESPACE" );
10046         }
10047
10048         /* if the result is a bit */
10049         if (AOP_TYPE(result) == AOP_CRY) {
10050                 
10051         /* if the right size is a literal then
10052                 we know what the value is */
10053                 if (AOP_TYPE(right) == AOP_LIT) {
10054                         
10055                         emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10056                                 popGet(AOP(result),0));
10057                         
10058                         if (((int) operandLitValue(right))) 
10059                                 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10060                                 AOP(result)->aopu.aop_dir,
10061                                 AOP(result)->aopu.aop_dir);
10062                         else
10063                                 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10064                                 AOP(result)->aopu.aop_dir,
10065                                 AOP(result)->aopu.aop_dir);
10066                         goto release;
10067                 }
10068                 
10069                 /* the right is also a bit variable */
10070                 if (AOP_TYPE(right) == AOP_CRY) {
10071                         emitpcode(POC_BCF,    popGet(AOP(result),0));
10072                         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10073                         emitpcode(POC_BSF,    popGet(AOP(result),0));
10074                         
10075                         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10076                                 AOP(result)->aopu.aop_dir,
10077                                 AOP(result)->aopu.aop_dir);
10078                         pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10079                                 AOP(right)->aopu.aop_dir,
10080                                 AOP(right)->aopu.aop_dir);
10081                         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10082                                 AOP(result)->aopu.aop_dir,
10083                                 AOP(result)->aopu.aop_dir);
10084                         goto release ;
10085                 }
10086                 
10087                 /* we need to or */
10088                 emitpcode(POC_BCF,    popGet(AOP(result),0));
10089                 pic14_toBoolean(right);
10090                 emitSKPZ;
10091                 emitpcode(POC_BSF,    popGet(AOP(result),0));
10092                 //aopPut(AOP(result),"a",0);
10093                 goto release ;
10094         }
10095         
10096         /* bit variables done */
10097         /* general case */
10098         size = AOP_SIZE(result);
10099         offset = 0 ;
10100         if(AOP_TYPE(right) == AOP_LIT)
10101                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10102         
10103         if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10104                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10105                 if(aopIdx(AOP(result),0) == 4) {
10106                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10107                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10108                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10109                         goto release;
10110                 } else
10111                         DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10112         }
10113         
10114         know_W=-1;
10115         while (size--) {
10116                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10117                 if(AOP_TYPE(right) == AOP_LIT) {
10118                         if(lit&0xff) {
10119                                 if(know_W != (int)(lit&0xff))
10120                                         emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10121                                 know_W = lit&0xff;
10122                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10123                         } else
10124                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10125                         
10126                         lit >>= 8;
10127                         
10128                 } else if (AOP_TYPE(right) == AOP_CRY) {
10129                         emitpcode(POC_CLRF, popGet(AOP(result),offset));
10130                         if(offset == 0) {
10131                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10132                                 emitpcode(POC_INCF, popGet(AOP(result),0));
10133                         }
10134                 } else {
10135                         mov2w_op (right, offset);
10136                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10137                 }
10138                 
10139                 offset++;
10140         }
10141         
10142         
10143 release:
10144         freeAsmop (right,NULL,ic,FALSE);
10145         freeAsmop (result,NULL,ic,TRUE);
10146 }   
10147
10148 /*-----------------------------------------------------------------*/
10149 /* genJumpTab - genrates code for jump table                       */
10150 /*-----------------------------------------------------------------*/
10151 static void genJumpTab (iCode *ic)
10152 {
10153         symbol *jtab;
10154         char *l;
10155         
10156         FENTRY;
10157         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10158         
10159         aopOp(IC_JTCOND(ic),ic,FALSE);
10160         /* get the condition into accumulator */
10161         l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10162         MOVA(l);
10163         /* multiply by three */
10164         pic14_emitcode("add","a,acc");
10165         pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10166         
10167         jtab = newiTempLabel(NULL);
10168         pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10169         pic14_emitcode("jmp","@a+dptr");
10170         pic14_emitcode("","%05d_DS_:",jtab->key+100);
10171         
10172         emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10173         emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10174         emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10175         emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10176         emitSKPNC;
10177         emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10178         emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10179         emitpLabel(jtab->key);
10180         
10181         freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10182         
10183         /* now generate the jump labels */
10184         for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10185         jtab = setNextItem(IC_JTLABELS(ic))) {
10186                 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10187                 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10188                 
10189         }
10190         
10191 }
10192
10193 /*-----------------------------------------------------------------*/
10194 /* genMixedOperation - gen code for operators between mixed types  */
10195 /*-----------------------------------------------------------------*/
10196 /*
10197 TSD - Written for the PIC port - but this unfortunately is buggy.
10198 This routine is good in that it is able to efficiently promote 
10199 types to different (larger) sizes. Unfortunately, the temporary
10200 variables that are optimized out by this routine are sometimes
10201 used in other places. So until I know how to really parse the 
10202 iCode tree, I'm going to not be using this routine :(.
10203 */
10204 static int genMixedOperation (iCode *ic)
10205 {
10206         FENTRY;
10207 #if 0
10208         operand *result = IC_RESULT(ic);
10209         sym_link *ctype = operandType(IC_LEFT(ic));
10210         operand *right = IC_RIGHT(ic);
10211         int ret = 0;
10212         int big,small;
10213         int offset;
10214         
10215         iCode *nextic;
10216         operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10217         
10218         pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10219         
10220         nextic = ic->next;
10221         if(!nextic)
10222                 return 0;
10223         
10224         nextright = IC_RIGHT(nextic);
10225         nextleft  = IC_LEFT(nextic);
10226         nextresult = IC_RESULT(nextic);
10227         
10228         aopOp(right,ic,FALSE);
10229         aopOp(result,ic,FALSE);
10230         aopOp(nextright,  nextic, FALSE);
10231         aopOp(nextleft,   nextic, FALSE);
10232         aopOp(nextresult, nextic, FALSE);
10233         
10234         if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10235                 
10236                 operand *t = right;
10237                 right = nextright;
10238                 nextright = t; 
10239                 
10240                 pic14_emitcode(";remove right +","");
10241                 
10242         } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10243         /*
10244         operand *t = right;
10245         right = nextleft;
10246         nextleft = t; 
10247                 */
10248                 pic14_emitcode(";remove left +","");
10249         } else
10250                 return 0;
10251         
10252         big = AOP_SIZE(nextleft);
10253         small = AOP_SIZE(nextright);
10254         
10255         switch(nextic->op) {
10256                 
10257         case '+':
10258                 pic14_emitcode(";optimize a +","");
10259                 /* if unsigned or not an integral type */
10260                 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10261                         pic14_emitcode(";add a bit to something","");
10262                 } else {
10263                         
10264                         pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10265                         
10266                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10267                                 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10268                                 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10269                         } else
10270                                 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10271                         
10272                         offset = 0;
10273                         while(--big) {
10274                                 
10275                                 offset++;
10276                                 
10277                                 if(--small) {
10278                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10279                                                 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10280                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10281                                         }
10282                                         
10283                                         pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10284                                         emitSKPNC;
10285                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10286                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10287                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10288                                         pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10289                                         pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10290                                         
10291                                 } else {
10292                                         pic14_emitcode("rlf","known_zero,w");
10293                                         
10294                                         /*
10295                                         if right is signed
10296                                         btfsc  right,7
10297                                         addlw ff
10298                                         */
10299                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10300                                                 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10301                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10302                                         } else {
10303                                                 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10304                                         }
10305                                 }
10306                         }
10307                         ret = 1;
10308                 }
10309         }
10310         ret = 1;
10311         
10312 release:
10313         freeAsmop(right,NULL,ic,TRUE);
10314         freeAsmop(result,NULL,ic,TRUE);
10315         freeAsmop(nextright,NULL,ic,TRUE);
10316         freeAsmop(nextleft,NULL,ic,TRUE);
10317         if(ret)
10318                 nextic->generated = 1;
10319         
10320         return ret;
10321 #else
10322         return 0;
10323 #endif
10324 }
10325 /*-----------------------------------------------------------------*/
10326 /* genCast - gen code for casting                                  */
10327 /*-----------------------------------------------------------------*/
10328 static void genCast (iCode *ic)
10329 {
10330         operand *result = IC_RESULT(ic);
10331         sym_link *restype = operandType(result);
10332         sym_link *rtype = operandType(IC_RIGHT(ic));
10333         operand *right = IC_RIGHT(ic);
10334         int size, offset ;
10335         
10336         FENTRY;
10337         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10338         /* if they are equivalent then do nothing */
10339         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10340                 return ;
10341         
10342         aopOp(right,ic,FALSE) ;
10343         aopOp(result,ic,FALSE);
10344         
10345         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10346         
10347         /* if the result is a bit */
10348         if (AOP_TYPE(result) == AOP_CRY) {
10349                 assert(!"assigning to bit variables is not supported");
10350         }
10351         
10352         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10353                 int offset = 1;
10354                 size = AOP_SIZE(result);
10355                 
10356                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10357                 
10358                 emitpcode(POC_CLRF,   popGet(AOP(result),0));
10359                 emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10360                 emitpcode(POC_INCF,   popGet(AOP(result),0));
10361                 
10362                 while (size--)
10363                         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
10364                 
10365                 goto release;
10366         }
10367         
10368         if (IS_PTR(restype))
10369         {
10370           operand *result = IC_RESULT(ic);
10371           //operand *left = IC_LEFT(ic);
10372           operand *right = IC_RIGHT(ic);
10373           int tag = 0xff;
10374           
10375           /* copy common part */
10376           int max, size = AOP_SIZE(result);
10377           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10378           DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10379
10380           /* warn if we discard generic opinter tag */
10381           if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10382           {
10383             //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10384           } // if
10385
10386           max = size;
10387           while (size--)
10388           {
10389             mov2w_op (right, size);
10390             movwf (AOP(result), size);
10391           } // while
10392
10393           /* upcast into generic pointer type? */
10394           if (IS_GENPTR(restype)
10395                 && (size < AOP_SIZE(result))
10396                 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10397           {
10398             //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10399             if (IS_PTR(rtype))
10400             {
10401               switch (DCL_TYPE(rtype))
10402               {
10403               case POINTER:     /* __data */
10404               case FPOINTER:    /* __data */
10405                 assert (AOP_SIZE(right) == 2);
10406                 tag = GPTRTAG_DATA;
10407                 break;
10408
10409               case CPOINTER:    /* __code */
10410                 assert (AOP_SIZE(right) == 2);
10411                 tag = GPTRTAG_CODE;
10412                 break;
10413                 
10414               case GPOINTER:    /* unknown destination, __data or __code */
10415                 /* assume __data space (address of immediate) */
10416                 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10417                 if (AOP(right)->code)
10418                   tag = GPTRTAG_CODE;
10419                 else
10420                   tag = GPTRTAG_DATA;
10421                 break;
10422                 
10423               default:
10424                 assert (!"unhandled pointer type");
10425               } // switch
10426             } else {
10427               /* convert other values into pointers to __data space */
10428               tag = GPTRTAG_DATA;
10429             }
10430
10431             assert (AOP_SIZE(result) == 3);
10432             if (tag == 0) {
10433               emitpcode(POC_CLRF, popGet(AOP(result), 2));
10434             } else {
10435               emitpcode(POC_MOVLW, popGetLit(tag));
10436               movwf(AOP(result), 2);
10437             }
10438           } else {
10439             addSign(result, max, 0);
10440           } // if
10441           goto release;
10442         }
10443         
10444         /* if they are the same size : or less */
10445         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10446                 
10447                 /* if they are in the same place */
10448                 if (pic14_sameRegs(AOP(right),AOP(result)))
10449                         goto release;
10450                 
10451                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10452                 if (IS_PTR_CONST(rtype))
10453                         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10454                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10455                         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10456                 
10457                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10458                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10459                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
10460                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10461                         emitpcode(POC_MOVWF, popGet(AOP(result),1));
10462                         if(AOP_SIZE(result) <2)
10463                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10464                         
10465                 } else {
10466                         
10467                         /* if they in different places then copy */
10468                         size = AOP_SIZE(result);
10469                         offset = 0 ;
10470                         while (size--) {
10471                                 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10472                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10473                                 
10474                                 //aopPut(AOP(result),
10475                                 // aopGet(AOP(right),offset,FALSE,FALSE),
10476                                 // offset);
10477                                 
10478                                 offset++;
10479                         }
10480                 }
10481                 goto release;
10482         }
10483         
10484         /* so we now know that the size of destination is greater
10485         than the size of the source.
10486         Now, if the next iCode is an operator then we might be
10487         able to optimize the operation without performing a cast.
10488         */
10489         if(0 && genMixedOperation(ic)) {
10490                 /* XXX: cannot optimize: must copy regs! */
10491                 goto release;
10492         }
10493         
10494         /* we move to result for the size of source */
10495         size = AOP_SIZE(right);
10496         offset = 0 ;
10497         while (size--) {
10498                 emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
10499                 emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
10500                 offset++;
10501         }
10502
10503         addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10504
10505 release:
10506         freeAsmop(right,NULL,ic,TRUE);
10507         freeAsmop(result,NULL,ic,TRUE);
10508         
10509 }
10510
10511 /*-----------------------------------------------------------------*/
10512 /* genDjnz - generate decrement & jump if not zero instrucion      */
10513 /*-----------------------------------------------------------------*/
10514 static int genDjnz (iCode *ic, iCode *ifx)
10515 {
10516         symbol *lbl, *lbl1;
10517         FENTRY;
10518         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10519         
10520         if (!ifx)
10521                 return 0;
10522         
10523                 /* if the if condition has a false label
10524         then we cannot save */
10525         if (IC_FALSE(ifx))
10526                 return 0;
10527         
10528                 /* if the minus is not of the form 
10529         a = a - 1 */
10530         if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10531                 !IS_OP_LITERAL(IC_RIGHT(ic)))
10532                 return 0;
10533         
10534         if (operandLitValue(IC_RIGHT(ic)) != 1)
10535                 return 0;
10536         
10537                 /* if the size of this greater than one then no
10538         saving */
10539         if (getSize(operandType(IC_RESULT(ic))) > 1)
10540                 return 0;
10541         
10542         /* otherwise we can save BIG */
10543         lbl = newiTempLabel(NULL);
10544         lbl1= newiTempLabel(NULL);
10545         
10546         aopOp(IC_RESULT(ic),ic,FALSE);
10547         
10548         if (IS_AOP_PREG(IC_RESULT(ic))) {
10549                 pic14_emitcode("dec","%s",
10550                         aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10551                 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10552                 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10553         } else {  
10554                 
10555                 
10556                 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10557                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10558                 
10559                 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10560                 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10561                 
10562         }
10563         /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10564         /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10565         /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10566         /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10567         
10568         
10569         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10570         ifx->generated = 1;
10571         return 1;
10572 }
10573
10574 /*-----------------------------------------------------------------*/
10575 /* genReceive - generate code for a receive iCode                  */
10576 /*-----------------------------------------------------------------*/
10577 static void genReceive (iCode *ic)
10578 {
10579         FENTRY;
10580         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10581         
10582         if (isOperandInFarSpace(IC_RESULT(ic)) &&
10583                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10584                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10585                 
10586                 int size = getSize(operandType(IC_RESULT(ic)));
10587                 int offset =  fReturnSizePic - size;
10588                 while (size--) {
10589                         pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10590                                 fReturn[fReturnSizePic - offset - 1] : "acc"));
10591                         offset++;
10592                 }
10593                 aopOp(IC_RESULT(ic),ic,FALSE);
10594                 size = AOP_SIZE(IC_RESULT(ic));
10595                 offset = 0;
10596                 while (size--) {
10597                         pic14_emitcode ("pop","acc");
10598                         aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10599                 }
10600                 
10601         } else {
10602                 _G.accInUse++;
10603                 aopOp(IC_RESULT(ic),ic,FALSE);
10604                 _G.accInUse--;
10605                 assignResultValue(IC_RESULT(ic));
10606         }
10607         
10608         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10609 }
10610
10611 /*-----------------------------------------------------------------*/
10612 /* genDummyRead - generate code for dummy read of volatiles        */
10613 /*-----------------------------------------------------------------*/
10614 static void
10615 genDummyRead (iCode * ic)
10616 {
10617         FENTRY;
10618         pic14_emitcode ("; genDummyRead","");
10619         pic14_emitcode ("; not implemented","");
10620         
10621         ic = ic;
10622 }
10623
10624 /*-----------------------------------------------------------------*/
10625 /* genpic14Code - generate code for pic14 based controllers        */
10626 /*-----------------------------------------------------------------*/
10627 /*
10628 * At this point, ralloc.c has gone through the iCode and attempted
10629 * to optimize in a way suitable for a PIC. Now we've got to generate
10630 * PIC instructions that correspond to the iCode.
10631 *
10632 * Once the instructions are generated, we'll pass through both the
10633 * peep hole optimizer and the pCode optimizer.
10634 *-----------------------------------------------------------------*/
10635
10636 void genpic14Code (iCode *lic)
10637 {
10638         iCode *ic;
10639         int cln = 0;
10640         const char *cline;
10641         
10642         FENTRY;
10643         lineHead = lineCurr = NULL;
10644         
10645         pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10646         addpBlock(pb);
10647         
10648         /* if debug information required */
10649         if (options.debug && currFunc) { 
10650                 if (currFunc) {
10651                         debugFile->writeFunction (currFunc, lic);
10652                 }
10653         }
10654         
10655         
10656         for (ic = lic ; ic ; ic = ic->next ) {
10657                 
10658                 //DEBUGpic14_emitcode(";ic","");
10659                 //fprintf (stderr, "in ic loop\n");
10660                 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10661                 //ic->lineno, printCLine(ic->filename, ic->lineno));
10662                 
10663                 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10664                   cln = ic->lineno;
10665                   //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10666                   cline = printCLine (ic->filename, ic->lineno);
10667                   if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10668                   addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10669                   //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10670                 }
10671                 
10672                 if (options.iCodeInAsm) {
10673                   emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10674                 }
10675                 /* if the result is marked as
10676                 spilt and rematerializable or code for
10677                 this has already been generated then
10678                 do nothing */
10679                 if (resultRemat(ic) || ic->generated ) 
10680                         continue ;
10681                 
10682                 /* depending on the operation */
10683                 switch (ic->op) {
10684                 case '!' :
10685                         genNot(ic);
10686                         break;
10687                         
10688                 case '~' :
10689                         genCpl(ic);
10690                         break;
10691                         
10692                 case UNARYMINUS:
10693                         genUminus (ic);
10694                         break;
10695                         
10696                 case IPUSH:
10697                         genIpush (ic);
10698                         break;
10699                         
10700                 case IPOP:
10701                         /* IPOP happens only when trying to restore a 
10702                         spilt live range, if there is an ifx statement
10703                         following this pop then the if statement might
10704                         be using some of the registers being popped which
10705                         would destory the contents of the register so
10706                         we need to check for this condition and handle it */
10707                         if (ic->next            && 
10708                                 ic->next->op == IFX &&
10709                                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10710                                 genIfx (ic->next,ic);
10711                         else
10712                                 genIpop (ic);
10713                         break; 
10714                         
10715                 case CALL:
10716                         genCall (ic);
10717                         break;
10718                         
10719                 case PCALL:
10720                         genPcall (ic);
10721                         break;
10722                         
10723                 case FUNCTION:
10724                         genFunction (ic);
10725                         break;
10726                         
10727                 case ENDFUNCTION:
10728                         genEndFunction (ic);
10729                         break;
10730                         
10731                 case RETURN:
10732                         genRet (ic);
10733                         break;
10734                         
10735                 case LABEL:
10736                         genLabel (ic);
10737                         break;
10738                         
10739                 case GOTO:
10740                         genGoto (ic);
10741                         break;
10742                         
10743                 case '+' :
10744                         genPlus (ic) ;
10745                         break;
10746                         
10747                 case '-' :
10748                         if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10749                                 genMinus (ic);
10750                         break;
10751                         
10752                 case '*' :
10753                         genMult (ic);
10754                         break;
10755                         
10756                 case '/' :
10757                         genDiv (ic) ;
10758                         break;
10759                         
10760                 case '%' :
10761                         genMod (ic);
10762                         break;
10763                         
10764                 case '>' :
10765                         genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));         
10766                         break;
10767                         
10768                 case '<' :
10769                         genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10770                         break;
10771                         
10772                 case LE_OP:
10773                 case GE_OP:
10774                 case NE_OP:
10775                         
10776                         /* note these two are xlated by algebraic equivalence
10777                         during parsing SDCC.y */
10778                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10779                                 "got '>=' or '<=' shouldn't have come here");
10780                         break;  
10781                         
10782                 case EQ_OP:
10783                         genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10784                         break;      
10785                         
10786                 case AND_OP:
10787                         genAndOp (ic);
10788                         break;
10789                         
10790                 case OR_OP:
10791                         genOrOp (ic);
10792                         break;
10793                         
10794                 case '^' :
10795                         genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10796                         break;
10797                         
10798                 case '|' :
10799                         genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10800                         break;
10801                         
10802                 case BITWISEAND:
10803                         genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10804                         break;
10805                         
10806                 case INLINEASM:
10807                         genInline (ic);
10808                         break;
10809                         
10810                 case RRC:
10811                         genRRC (ic);
10812                         break;
10813                         
10814                 case RLC:
10815                         genRLC (ic);
10816                         break;
10817                         
10818                 case GETHBIT:
10819                         genGetHbit (ic);
10820                         break;
10821                         
10822                 case LEFT_OP:
10823                         genLeftShift (ic);
10824                         break;
10825                         
10826                 case RIGHT_OP:
10827                         genRightShift (ic);
10828                         break;
10829                         
10830                 case GET_VALUE_AT_ADDRESS:
10831                         genPointerGet(ic);
10832                         break;
10833                         
10834                 case '=' :
10835                         if (POINTER_SET(ic))
10836                                 genPointerSet(ic);
10837                         else
10838                                 genAssign(ic);
10839                         break;
10840                         
10841                 case IFX:
10842                         genIfx (ic,NULL);
10843                         break;
10844                         
10845                 case ADDRESS_OF:
10846                         genAddrOf (ic);
10847                         break;
10848                         
10849                 case JUMPTABLE:
10850                         genJumpTab (ic);
10851                         break;
10852                         
10853                 case CAST:
10854                         genCast (ic);
10855                         break;
10856                         
10857                 case RECEIVE:
10858                         genReceive(ic);
10859                         break;
10860                         
10861                 case SEND:
10862                         addSet(&_G.sendSet,ic);
10863                         break;
10864                         
10865                 case DUMMY_READ_VOLATILE:
10866                         genDummyRead (ic);
10867                         break;
10868                         
10869                 default :
10870                         fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10871                         ic = ic;
10872                         break;
10873                 }
10874         }
10875
10876         
10877         /* now we are ready to call the
10878         peep hole optimizer */
10879         if (!options.nopeep) {
10880                 peepHole (&lineHead);
10881         }
10882         /* now do the actual printing */
10883         printLine (lineHead,codeOutFile);
10884         
10885 #ifdef PCODE_DEBUG
10886         DFPRINTF((stderr,"printing pBlock\n\n"));
10887         printpBlock(stdout,pb);
10888 #endif
10889         
10890         return;
10891 }
10892
10893 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10894  * (meaning: representing its own address) or not (referencing its contents).
10895  * This can only be decided based on the operand's type. */
10896 int
10897 aop_isLitLike (asmop *aop)
10898 {
10899   assert (aop);
10900   if (aop->type == AOP_LIT) return 1;
10901 if (aop->type == AOP_IMMD) return 1;
10902   if ((aop->type == AOP_PCODE) &&
10903                 ((aop->aopu.pcop->type == PO_LITERAL)))
10904   {
10905     /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10906      * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10907     return 1;
10908   }
10909   return 0;
10910 }
10911
10912 int
10913 op_isLitLike (operand *op)
10914 {
10915   assert (op);
10916   if (aop_isLitLike (AOP(op))) return 1;
10917   if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10918   if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;
10919   return 0;
10920 }