* src/pic/device.{c,h}: added pic14_getPIC()
[fw/sdcc] / src / pic / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for pic
3   
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8     cont'd   -  Raphael Neider <rneider AT web.de> (2005)
9   
10   This program is free software; you can redistribute it and/or modify it
11   under the terms of the GNU General Public License as published by the
12   Free Software Foundation; either version 2, or (at your option) any
13   later version.
14   
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License for more details.
19   
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23   
24   In other words, you are welcome to use, share and improve this program.
25   You are forbidden to forbid anyone else to use, share and improve
26   what you give them.   Help stamp out software-hoarding!
27   
28   Notes:
29   000123 mlh  Moved aopLiteral to SDCCglue.c to help the split
30       Made everything static
31 -------------------------------------------------------------------------*/
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include "SDCCglobl.h"
38 #include "newalloc.h" 
39
40 #include "common.h"
41 #include "SDCCpeeph.h"
42 #include "ralloc.h"
43 #include "pcode.h"
44 #include "gen.h"
45 #include "glue.h"
46
47 /* When changing these, you must also update the assembler template
48  * in device/lib/libsdcc/macros.inc */
49 #define GPTRTAG_DATA    0x00
50 #define GPTRTAG_CODE    0x80
51
52 /* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
53 #define PIC_IS_DATA_PTR(x)      (IS_DATA_PTR(x) || IS_FARPTR(x))
54 #define PIC_IS_FARPTR(x)        (PIC_IS_DATA_PTR(x))
55
56 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
57 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
58 void genMult8X8_8 (operand *, operand *,operand *);
59 extern void printpBlock(FILE *of, pBlock *pb);
60
61 static int labelOffset=0;
62 extern int debug_verbose;
63 extern int pic14_hasInterrupt;
64 //static int optimized_for_speed = 0;
65
66 /* max_key keeps track of the largest label number used in 
67 a function. This is then used to adjust the label offset
68 for the next function.
69 */
70 static int max_key=0;
71 static int GpsuedoStkPtr=0;
72 static int pic14_inISR = 0;
73
74 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
75 extern char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
76 const char *AopType(short type);
77
78 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
79
80 /* this is the down and dirty file with all kinds of 
81 kludgy & hacky stuff. This is what it is all about
82 CODE GENERATION for a specific MCU . some of the
83 routines may be reusable, will have to see */
84
85 static char *zero = "#0x00";
86 static char *one  = "#0x01";
87 static char *spname = "sp";
88
89 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
90 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
91 static char **fReturn = fReturnpic14;
92
93 //static char *accUse[] = {"a","b"};
94
95 //static short rbank = -1;
96
97 static struct {
98         short r0Pushed;
99         short r1Pushed;
100         short accInUse;
101         short inLine;
102         short debugLine;
103         short nRegsSaved;
104         set *sendSet;
105 } _G;
106
107 /* Resolved ifx structure. This structure stores information
108 about an iCode ifx that makes it easier to generate code.
109 */
110 typedef struct resolvedIfx {
111         symbol *lbl;     /* pointer to a label */
112         int condition;   /* true or false ifx */
113         int generated;   /* set true when the code associated with the ifx
114                           * is generated */
115 } resolvedIfx;
116
117 extern int pic14_ptrRegReq ;
118 extern int pic14_nRegs;
119 extern FILE *codeOutFile;
120 static void saverbank (int, iCode *,bool);
121
122 static lineNode *lineHead = NULL;
123 static lineNode *lineCurr = NULL;
124
125 #if 0
126 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
127 0xE0, 0xC0, 0x80, 0x00};
128 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
129 0x07, 0x03, 0x01, 0x00};
130 #endif
131
132 static  pBlock *pb;
133
134 /*-----------------------------------------------------------------*/
135 /*      my_powof2(n) - If `n' is an integaer power of 2, then the          */
136 /*                                 exponent of 2 is returned, otherwise -1 is      */
137 /*                                 returned.                                                                       */
138 /* note that this is similar to the function `powof2' in SDCCsymt  */
139 /* if(n == 2^y)                                                                                                    */
140 /*       return y;                                                                                                         */
141 /* return -1;                                                                                                      */
142 /*-----------------------------------------------------------------*/
143 static int my_powof2 (unsigned long num)
144 {
145         if(num) {
146                 if( (num & (num-1)) == 0) {
147                         int nshifts = -1;
148                         while(num) {
149                                 num>>=1;
150                                 nshifts++;
151                         }
152                         return nshifts;
153                 }
154         }
155         
156         return -1;
157 }
158
159 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
160 {
161         
162         DEBUGpic14_emitcode ("; ","line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
163                 line_no,
164                 ((result) ? AopType(AOP_TYPE(result)) : "-"),
165                 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
166                 ((result) ? AOP_SIZE(result) : 0),
167                 ((left)   ? AopType(AOP_TYPE(left)) : "-"),
168                 ((left)   ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
169                 ((left)   ? AOP_SIZE(left) : 0),
170                 ((right)  ? AopType(AOP_TYPE(right)) : "-"),
171                 ((right)  ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
172                 ((right)  ? AOP_SIZE(right) : 0));
173         
174 }
175
176 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
177 {
178         
179         DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
180                 line_no,
181                 ((result) ? AopType(AOP_TYPE(result)) : "-"),
182                 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
183                 ((left)   ? AopType(AOP_TYPE(left)) : "-"),
184                 ((left)   ? (SPEC_USIGN(operandType(left))       ? 'u' : 's') : '-'),
185                 ((right)  ? AopType(AOP_TYPE(right)) : "-"),
186                 ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
187         
188 }
189
190 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
191 {
192         va_list ap;
193         char lb[INITIAL_INLINEASM];  
194         unsigned char *lbp = (unsigned char *)lb;
195         
196         if(!debug_verbose && !options.debug)
197                 return;
198         
199         va_start(ap,fmt);   
200         
201         if (inst && *inst) {
202                 if (fmt && *fmt)
203                         sprintf(lb,"%s\t",inst);
204                 else
205                         sprintf(lb,"%s",inst);
206                 vsprintf(lb+(strlen(lb)),fmt,ap);
207         }  else
208                 vsprintf(lb,fmt,ap);
209         
210         while (isspace(*lbp)) lbp++;
211         
212         if (lbp && *lbp) 
213                 lineCurr = (lineCurr ?
214                 connectLine(lineCurr,newLineNode(lb)) :
215         (lineHead = newLineNode(lb)));
216         lineCurr->isInline = _G.inLine;
217         lineCurr->isDebug  = _G.debugLine;
218         
219         addpCode2pBlock(pb,newpCodeCharP(lb));
220         
221         va_end(ap);
222 }
223
224 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
225 {
226 #if defined (HAVE_VSNPRINTF)
227   vsnprintf (buf, size, fmt, ap);
228 #elif defined (HAVE_VSPRINTF)
229   vsprintf (buf, size, fmt, ap);
230   if (strlen (buf) >= size)
231   {
232     fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
233   }
234 #elif defined (HAVE_SNPRINTF)
235   snprintf (buf, size, "vs(n)printf required");
236 #elif defined (HAVE_SRINTF)
237   sprintf (buf, "vs(n)printf required");
238   if (strlen (buf) >= size)
239   {
240     fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
241   }
242 #else
243   assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
244 #endif
245 }
246
247 void emitpComment (const char *fmt, ...)
248 {
249   va_list va;
250   char buffer[4096];
251   
252   va_start (va, fmt);
253   if (pb) {
254     Safe_vsnprintf (buffer, 4096, fmt, va);
255     //fprintf (stderr, "%s\n" ,buffer);
256     addpCode2pBlock (pb, newpCodeCharP (buffer));
257 #if 0
258   } else {
259     Safe_vsnprintf (buffer, 4096, fmt, va);
260     fprintf (stderr, "No current pBlock -- discarding comment [%s]\n", buffer);
261 #endif
262   }
263   va_end (va);
264 }
265
266 void emitpLabel(int key)
267 {
268         addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
269 }
270
271 /* gen.h defines a macro emitpcode that should be used to call emitpcode
272  * as this allows for easy debugging (ever asked the question: where was
273  * this instruction geenrated? Here is the answer... */
274 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
275 {
276         if(pcop)
277                 addpCode2pBlock(pb,newpCode(poc,pcop));
278         else {
279                 static int has_warned = 0;
280                 
281                 DEBUGpic14_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
282                 if (!has_warned) {
283                         has_warned = 1;
284                         fprintf( stderr, "WARNING: encountered NULL pcop--this is probably a compiler bug...\n" );
285                 }
286         }
287 }
288
289 void emitpcodeNULLop(PIC_OPCODE poc)
290 {
291         
292         addpCode2pBlock(pb,newpCode(poc,NULL));
293         
294 }
295
296
297 /*-----------------------------------------------------------------*/
298 /* pic14_emitcode - writes the code into a file : for now it is simple    */
299 /*-----------------------------------------------------------------*/
300 void pic14_emitcode (char *inst,char *fmt, ...)
301 {
302         va_list ap;
303         char lb[INITIAL_INLINEASM];  
304         unsigned char *lbp = (unsigned char *)lb;
305         
306         va_start(ap,fmt);   
307         
308         if (inst && *inst) {
309                 if (fmt && *fmt)
310                         sprintf(lb,"%s\t",inst);
311                 else
312                         sprintf(lb,"%s",inst);
313                 vsprintf(lb+(strlen(lb)),fmt,ap);
314         }  else
315                 vsprintf(lb,fmt,ap);
316         
317         while (isspace(*lbp)) lbp++;
318         
319         if (lbp && *lbp) 
320                 lineCurr = (lineCurr ?
321                 connectLine(lineCurr,newLineNode(lb)) :
322         (lineHead = newLineNode(lb)));
323         lineCurr->isInline = _G.inLine;
324         lineCurr->isDebug  = _G.debugLine;
325         
326         if(debug_verbose)
327                 addpCode2pBlock(pb,newpCodeCharP(lb));
328         
329         va_end(ap);
330 }
331
332 /*-----------------------------------------------------------------*/
333 /* pic14_emitDebuggerSymbol - associate the current code location  */
334 /*       with a debugger symbol                                                                            */
335 /*-----------------------------------------------------------------*/
336 void
337 pic14_emitDebuggerSymbol (char * debugSym)
338 {
339         _G.debugLine = 1;
340         pic14_emitcode ("", ";%s ==.", debugSym);
341         _G.debugLine = 0;
342 }
343
344 #if 0
345 /*-----------------------------------------------------------------*/
346 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
347 /*-----------------------------------------------------------------*/
348 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
349 {
350         bool r0iu = FALSE , r1iu = FALSE;
351         bool r0ou = FALSE , r1ou = FALSE;
352         
353         /* the logic: if r0 & r1 used in the instruction
354         then we are in trouble otherwise */
355         
356         /* first check if r0 & r1 are used by this
357         instruction, in which case we are in trouble */
358         if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
359                 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
360         {
361                 goto endOfWorld;          
362         }
363         
364         r0ou = bitVectBitValue(ic->rMask,R0_IDX);
365         r1ou = bitVectBitValue(ic->rMask,R1_IDX);
366         
367         /* if no usage of r0 then return it */
368         if (!r0iu && !r0ou) {
369                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
370                 (*aopp)->type = AOP_R0;
371                 
372                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
373         }
374         
375         /* if no usage of r1 then return it */
376         if (!r1iu && !r1ou) {
377                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
378                 (*aopp)->type = AOP_R1;
379                 
380                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
381         }    
382         
383         /* now we know they both have usage */
384         /* if r0 not used in this instruction */
385         if (!r0iu) {
386                 /* push it if not already pushed */
387                 if (!_G.r0Pushed) {
388                         //pic14_emitcode ("push","%s",
389                         //                pic14_regWithIdx(R0_IDX)->dname);
390                         _G.r0Pushed++ ;
391                 }
392                 
393                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
394                 (*aopp)->type = AOP_R0;
395                 
396                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
397         }
398         
399         /* if r1 not used then */
400         
401         if (!r1iu) {
402                 /* push it if not already pushed */
403                 if (!_G.r1Pushed) {
404                         //pic14_emitcode ("push","%s",
405                         //                pic14_regWithIdx(R1_IDX)->dname);
406                         _G.r1Pushed++ ;
407                 }
408                 
409                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
410                 (*aopp)->type = AOP_R1;
411                 return pic14_regWithIdx(R1_IDX);
412         }
413         
414 endOfWorld :
415         /* I said end of world but not quite end of world yet */
416         /* if this is a result then we can push it on the stack*/
417         if (result) {
418                 (*aopp)->type = AOP_STK;        
419                 return NULL;
420         }
421         
422         /* other wise this is true end of the world */
423         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
424                 "getFreePtr should never reach here");
425         exit(0);
426 }
427 #endif
428
429 /*-----------------------------------------------------------------*/
430 /* newAsmop - creates a new asmOp                                                                  */
431 /*-----------------------------------------------------------------*/
432 asmop *newAsmop (short type)
433 {
434         asmop *aop;
435         
436         aop = Safe_calloc(1,sizeof(asmop));
437         aop->type = type;
438         return aop;
439 }
440
441 static void genSetDPTR(int n)
442 {
443         if (!n)
444         {
445                 pic14_emitcode(";", "Select standard DPTR");
446                 pic14_emitcode("mov", "dps, #0x00");
447         }
448         else
449         {
450                 pic14_emitcode(";", "Select alternate DPTR");
451                 pic14_emitcode("mov", "dps, #0x01");
452         }
453 }
454
455 /*-----------------------------------------------------------------*/
456 /* resolveIfx - converts an iCode ifx into a form more useful for  */
457 /*                              generating code                                                                    */
458 /*-----------------------------------------------------------------*/
459 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
460 {
461         if(!resIfx) 
462                 return;
463         
464         //  DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
465         
466         resIfx->condition = 1;  /* assume that the ifx is true */
467         resIfx->generated = 0;  /* indicate that the ifx has not been used */
468         
469         if(!ifx) {
470                 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL);      / * oops, there is no ifx. so create a label */
471                                                                                         /*
472                                                                                         DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
473                                                                                         __FUNCTION__,__LINE__,resIfx->lbl->key);
474                 */
475         } else {
476                 if(IC_TRUE(ifx)) {
477                         resIfx->lbl = IC_TRUE(ifx);
478                 } else {
479                         resIfx->lbl = IC_FALSE(ifx);
480                         resIfx->condition = 0;
481                 }
482                 /*
483                 if(IC_TRUE(ifx)) 
484                 DEBUGpic14_emitcode("; ***","ifx true is non-null");
485                 if(IC_FALSE(ifx)) 
486                 DEBUGpic14_emitcode("; ***","ifx false is non-null");
487                 */
488         }
489         
490         //  DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
491         
492 }
493 /*-----------------------------------------------------------------*/
494 /* pointerCode - returns the code for a pointer type                       */
495 /*-----------------------------------------------------------------*/
496 #if 0
497 static int pointerCode (sym_link *etype)
498 {
499         
500         return PTR_TYPE(SPEC_OCLS(etype));
501         
502 }
503 #endif
504
505 /*-----------------------------------------------------------------*/
506 /* aopForSym - for a true symbol                                                                   */
507 /*-----------------------------------------------------------------*/
508 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
509 {
510         asmop *aop;
511         memmap *space= SPEC_OCLS(sym->etype);
512         
513         DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
514         /* if already has one */
515         if (sym->aop)
516                 return sym->aop;
517         
518 #if 0
519         /* assign depending on the storage class */
520         /* if it is on the stack or indirectly addressable */
521         /* space we need to assign either r0 or r1 to it         */    
522         if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
523                 sym->aop = aop = newAsmop(0);
524                 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
525                 aop->size = getSize(sym->type);
526                 
527                 /* now assign the address of the variable to 
528                 the pointer register */
529                 if (aop->type != AOP_STK) {
530                         
531                         if (sym->onStack) {
532                                 if ( _G.accInUse )
533                                         pic14_emitcode("push","acc");
534                                 
535                                 pic14_emitcode("mov","a,_bp");
536                                 pic14_emitcode("add","a,#0x%02x",
537                                         ((sym->stack < 0) ?
538                                         ((char)(sym->stack - _G.nRegsSaved )) :
539                                 ((char)sym->stack)) & 0xff);
540                                 pic14_emitcode("mov","%s,a",
541                                         aop->aopu.aop_ptr->name);
542                                 
543                                 if ( _G.accInUse )
544                                         pic14_emitcode("pop","acc");
545                         } else
546                                 pic14_emitcode("mov","%s,#%s",
547                                 aop->aopu.aop_ptr->name,
548                                 sym->rname);
549                         aop->paged = space->paged;
550                 } else
551                         aop->aopu.aop_stk = sym->stack;
552                 return aop;
553         }
554         
555         if (sym->onStack && options.stack10bit)
556         {
557                 /* It's on the 10 bit stack, which is located in
558                 * far data space.
559                 */
560                 
561                 //DEBUGpic14_emitcode(";","%d",__LINE__);
562                 
563                 if ( _G.accInUse )
564                         pic14_emitcode("push","acc");
565                 
566                 pic14_emitcode("mov","a,_bp");
567                 pic14_emitcode("add","a,#0x%02x",
568                         ((sym->stack < 0) ?
569                         ((char)(sym->stack - _G.nRegsSaved )) :
570                 ((char)sym->stack)) & 0xff);
571                 
572                 genSetDPTR(1);
573                 pic14_emitcode ("mov","dpx1,#0x40");
574                 pic14_emitcode ("mov","dph1,#0x00");
575                 pic14_emitcode ("mov","dpl1, a");
576                 genSetDPTR(0);
577                 
578                 if ( _G.accInUse )
579                         pic14_emitcode("pop","acc");
580                 
581                 sym->aop = aop = newAsmop(AOP_DPTR2);
582                 aop->size = getSize(sym->type); 
583                 return aop;
584         }
585 #endif
586
587         //DEBUGpic14_emitcode(";","%d",__LINE__);
588         /* if in bit space */
589         if (IN_BITSPACE(space)) {
590                 sym->aop = aop = newAsmop (AOP_CRY);
591                 aop->aopu.aop_dir = sym->rname ;
592                 aop->size = getSize(sym->type);
593                 //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
594                 return aop;
595         }
596         /* if it is in direct space */
597         if (IN_DIRSPACE(space)) {
598                 sym->aop = aop = newAsmop (AOP_DIR);
599                 aop->aopu.aop_dir = sym->rname ;
600                 aop->size = getSize(sym->type);
601                 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
602                 return aop;
603         }
604         
605         /* special case for a function */
606         if (IS_FUNC(sym->type)) {   
607                 
608                 sym->aop = aop = newAsmop(AOP_PCODE);
609                 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
610                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
611                 PCOI(aop->aopu.pcop)->_function = 1;
612                 PCOI(aop->aopu.pcop)->index = 0;
613                 aop->size = FPTRSIZE; 
614                 /*
615                 sym->aop = aop = newAsmop(AOP_IMMD);    
616                 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
617                 strcpy(aop->aopu.aop_immd,sym->rname);
618                 aop->size = FPTRSIZE; 
619                 */
620                 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
621                 return aop;
622         }
623         
624         if (IS_ARRAY(sym->type)) {
625                 sym->aop = aop = newAsmop(AOP_PCODE);
626                 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
627                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
628                 PCOI(aop->aopu.pcop)->_function = 0;
629                 PCOI(aop->aopu.pcop)->index = 0;
630                 aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
631                 
632                 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
633                 return aop;
634         }
635         
636         /* only remaining is far space */
637         /* in which case DPTR gets the address */
638         sym->aop = aop = newAsmop(AOP_PCODE);
639         
640         aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
641         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
642         PCOI(aop->aopu.pcop)->index = 0;
643         
644         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
645                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
646         
647         allocDirReg (IC_LEFT(ic));
648         
649         aop->size = FPTRSIZE;
650         /*
651         DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
652         sym->aop = aop = newAsmop(AOP_DPTR);
653         pic14_emitcode ("mov","dptr,#%s", sym->rname);
654         aop->size = getSize(sym->type);
655         
656           DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
657         */
658         
659         /* if it is in code space */
660         if (IN_CODESPACE(space))
661                 aop->code = 1;
662         
663         return aop;       
664 }
665
666 /*-----------------------------------------------------------------*/
667 /* aopForRemat - rematerialzes an object                                                   */
668 /*-----------------------------------------------------------------*/
669 static asmop *aopForRemat (operand *op) // x symbol *sym)
670 {
671         symbol *sym = OP_SYMBOL(op);
672         iCode *ic = NULL;
673         asmop *aop = newAsmop(AOP_PCODE);
674         int val = 0;
675         int offset = 0;
676         
677         ic = sym->rematiCode;
678
679         DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
680         if(IS_OP_POINTER(op)) {
681                 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
682         }
683         for (;;) {
684                 if (ic->op == '+') {
685                         val += (int) operandLitValue(IC_RIGHT(ic));
686                 } else if (ic->op == '-') {
687                         val -= (int) operandLitValue(IC_RIGHT(ic));
688                 } else
689                         break;
690                 
691                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
692         }
693         
694         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
695         aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
696         PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
697         PCOI(aop->aopu.pcop)->index = val;
698         
699         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
700                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
701                 val, IS_PTR_CONST(operandType(op)));
702         
703         //      DEBUGpic14_emitcode(";","aop type  %s",AopType(AOP_TYPE(IC_LEFT(ic))));
704         
705         allocDirReg (IC_LEFT(ic));
706         
707         return aop;              
708 }
709
710 int aopIdx (asmop *aop, int offset)
711 {
712         if(!aop)
713                 return -1;
714         
715         if(aop->type !=  AOP_REG)
716                 return -2;
717         
718         return aop->aopu.aop_reg[offset]->rIdx;
719         
720 }
721 /*-----------------------------------------------------------------*/
722 /* regsInCommon - two operands have some registers in common       */
723 /*-----------------------------------------------------------------*/
724 static bool regsInCommon (operand *op1, operand *op2)
725 {
726         symbol *sym1, *sym2;
727         int i;
728         
729         /* if they have registers in common */
730         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
731                 return FALSE ;
732         
733         sym1 = OP_SYMBOL(op1);
734         sym2 = OP_SYMBOL(op2);
735         
736         if (sym1->nRegs == 0 || sym2->nRegs == 0)
737                 return FALSE ;
738         
739         for (i = 0 ; i < sym1->nRegs ; i++) {
740                 int j;
741                 if (!sym1->regs[i])
742                         continue ;
743                 
744                 for (j = 0 ; j < sym2->nRegs ;j++ ) {
745                         if (!sym2->regs[j])
746                                 continue ;
747                         
748                         if (sym2->regs[j] == sym1->regs[i])
749                                 return TRUE ;
750                 }
751         }
752         
753         return FALSE ;
754 }
755
756 /*-----------------------------------------------------------------*/
757 /* operandsEqu - equivalent                                                                        */
758 /*-----------------------------------------------------------------*/
759 static bool operandsEqu ( operand *op1, operand *op2)
760 {
761         symbol *sym1, *sym2;
762         
763         /* if they not symbols */
764         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
765                 return FALSE;
766         
767         sym1 = OP_SYMBOL(op1);
768         sym2 = OP_SYMBOL(op2);
769         
770         /* if both are itemps & one is spilt
771         and the other is not then false */
772         if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
773                 sym1->isspilt != sym2->isspilt )
774                 return FALSE ;
775         
776         /* if they are the same */
777         if (sym1 == sym2)
778                 return TRUE ;
779         
780         if (sym1->rname[0] && sym2->rname[0]
781                 && strcmp (sym1->rname, sym2->rname) == 0)
782                 return TRUE;
783         
784         
785         /* if left is a tmp & right is not */
786         if (IS_ITEMP(op1)  && 
787                 !IS_ITEMP(op2) &&
788                 sym1->isspilt  &&
789                 (sym1->usl.spillLoc == sym2))
790                 return TRUE;
791         
792         if (IS_ITEMP(op2)  && 
793                 !IS_ITEMP(op1) &&
794                 sym2->isspilt  &&
795                 sym1->level > 0 &&
796                 (sym2->usl.spillLoc == sym1))
797                 return TRUE ;
798         
799         return FALSE ;
800 }
801
802 /*-----------------------------------------------------------------*/
803 /* pic14_sameRegs - two asmops have the same registers             */
804 /*-----------------------------------------------------------------*/
805 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
806 {
807         int i;
808         
809         if (aop1 == aop2)
810                 return TRUE ;
811         
812         if (aop1->type != AOP_REG ||
813                 aop2->type != AOP_REG )
814                 return FALSE ;
815         
816         if (aop1->size != aop2->size )
817                 return FALSE ;
818         
819         for (i = 0 ; i < aop1->size ; i++ )
820                 if (aop1->aopu.aop_reg[i] !=
821                         aop2->aopu.aop_reg[i] )
822                         return FALSE ;
823                 
824                 return TRUE ;
825 }
826
827 /*-----------------------------------------------------------------*/
828 /* aopOp - allocates an asmop for an operand  :                    */
829 /*-----------------------------------------------------------------*/
830 void aopOp (operand *op, iCode *ic, bool result)
831 {
832         asmop *aop;
833         symbol *sym;
834         int i;
835         
836         if (!op)
837                 return ;
838         
839         /* if this a literal */
840         if (IS_OP_LITERAL(op)) {
841                 op->aop = aop = newAsmop(AOP_LIT);
842                 aop->aopu.aop_lit = op->operand.valOperand;
843                 aop->size = getSize(operandType(op));
844                 return;
845         }
846         
847         {
848                 sym_link *type = operandType(op);
849                 if(IS_PTR_CONST(type))
850                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
851         }
852         
853         /* if already has a asmop then continue */
854         if (op->aop)
855                 return ;
856         
857         /* if the underlying symbol has a aop */
858         if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
859                 DEBUGpic14_emitcode(";","%d",__LINE__);
860                 op->aop = OP_SYMBOL(op)->aop;
861                 return;
862         }
863         
864         /* if this is a true symbol */
865         if (IS_TRUE_SYMOP(op)) {          
866                 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
867                 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
868                 return ;
869         }
870         
871         /* this is a temporary : this has
872         only four choices :
873         a) register
874         b) spillocation
875         c) rematerialize 
876         d) conditional   
877         e) can be a return use only */
878         
879         sym = OP_SYMBOL(op);
880         
881         
882         /* if the type is a conditional */
883         if (sym->regType == REG_CND) {
884                 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
885                 aop->size = 0;
886                 return;
887         }
888         
889         /* if it is spilt then two situations
890         a) is rematerialize 
891         b) has a spill location */
892         if (sym->isspilt || sym->nRegs == 0) {
893                 
894                 DEBUGpic14_emitcode(";","%d",__LINE__);
895                 /* rematerialize it NOW */
896                 if (sym->remat) {
897                         
898                         sym->aop = op->aop = aop = aopForRemat (op);
899                         aop->size = getSize(sym->type);
900                         //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
901                         return;
902                 }
903                 
904 #if 0
905                 /* WREG is not usable as an ordinary operand with PIC architecture,
906                  * one might introduce a scratch register that can be used to make
907                  * WREG accesible as an operand... disable WREG for now */
908                 if (sym->accuse) {
909                         int i;
910                         aop = op->aop = sym->aop = newAsmop(AOP_ACC);
911                         aop->size = getSize(sym->type);
912                         for ( i = 0 ; i < 2 ; i++ )
913                                 aop->aopu.aop_str[i] = accUse[i];
914                         DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
915                         return;  
916                 }
917 #endif
918                 
919                 if (sym->ruonly ) {
920                         if(sym->isptr) {        // && sym->uptr 
921                                 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
922                                 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
923                                 
924                                 //PCOI(aop->aopu.pcop)->_const = 0;
925                                 //PCOI(aop->aopu.pcop)->index = 0;
926                                 /*
927                                 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
928                                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
929                                 */
930                                 //allocDirReg (IC_LEFT(ic));
931                                 
932                                 aop->size = getSize(sym->type);
933                                 DEBUGpic14_emitcode(";","%d",__LINE__);
934                                 return;
935                                 
936                         } else {
937                                 
938                                 unsigned i;
939                                 
940                                 aop = op->aop = sym->aop = newAsmop(AOP_STR);
941                                 aop->size = getSize(sym->type);
942                                 for ( i = 0 ; i < fReturnSizePic ; i++ )
943                                         aop->aopu.aop_str[i] = fReturn[i];
944                                 
945                                 DEBUGpic14_emitcode(";","%d",__LINE__);
946                                 return;
947                         }
948                 }
949                 
950                 /* else spill location  */
951                 if (sym->usl.spillLoc)
952                 {
953                         asmop *oldAsmOp = NULL;
954
955                         if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
956                         {
957                                 /* force a new aop if sizes differ */
958                                 oldAsmOp = sym->usl.spillLoc->aop;
959                                 sym->usl.spillLoc->aop = NULL;
960                         }
961                         DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
962                                 __FUNCTION__,__LINE__,
963                                 sym->usl.spillLoc->rname,
964                                 sym->rname, sym->usl.spillLoc->offset);
965                 
966                         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
967                         if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
968                         {
969                                 /* Don't reuse the new aop, go with the last one */
970                                 sym->usl.spillLoc->aop = oldAsmOp;
971                         }
972                         //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
973                         aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
974                                 getSize(sym->type), 
975                                 sym->usl.spillLoc->offset);
976                         aop->size = getSize(sym->type);
977                 
978                         return;
979                 }
980         }
981         
982         {
983                 sym_link *type = operandType(op);
984                 if(IS_PTR_CONST(type)) 
985                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
986         }
987         
988         /* must be in a register */
989         DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
990         sym->aop = op->aop = aop = newAsmop(AOP_REG);
991         aop->size = sym->nRegs;
992         for ( i = 0 ; i < sym->nRegs ;i++)
993                 aop->aopu.aop_reg[i] = sym->regs[i];
994 }
995
996 /*-----------------------------------------------------------------*/
997 /* freeAsmop - free up the asmop given to an operand                       */
998 /*----------------------------------------------------------------*/
999 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1000 {       
1001         asmop *aop ;
1002         
1003         if (!op)
1004                 aop = aaop;
1005         else 
1006                 aop = op->aop;
1007         
1008         if (!aop)
1009                 return ;
1010         
1011         if (aop->freed)
1012                 goto dealloc; 
1013         
1014         aop->freed = 1;
1015         
1016         /* depending on the asmop type only three cases need work AOP_RO
1017         , AOP_R1 && AOP_STK */
1018 #if 0
1019         switch (aop->type) {
1020         case AOP_R0 :
1021                 if (_G.r0Pushed ) {
1022                         if (pop) {
1023                                 pic14_emitcode ("pop","ar0");     
1024                                 _G.r0Pushed--;
1025                         }
1026                 }
1027                 bitVectUnSetBit(ic->rUsed,R0_IDX);
1028                 break;
1029                 
1030         case AOP_R1 :
1031                 if (_G.r1Pushed ) {
1032                         if (pop) {
1033                                 pic14_emitcode ("pop","ar1");
1034                                 _G.r1Pushed--;
1035                         }
1036                 }
1037                 bitVectUnSetBit(ic->rUsed,R1_IDX);                      
1038                 break;
1039                 
1040         case AOP_STK :
1041                 {
1042                         int sz = aop->size;      
1043                         int stk = aop->aopu.aop_stk + aop->size;
1044                         bitVectUnSetBit(ic->rUsed,R0_IDX);
1045                         bitVectUnSetBit(ic->rUsed,R1_IDX);                
1046                         
1047                         getFreePtr(ic,&aop,FALSE);
1048                         
1049                         if (options.stack10bit)
1050                         {
1051                                 /* I'm not sure what to do here yet... */
1052                                 /* #STUB */
1053                                 fprintf(stderr, 
1054                                         "*** Warning: probably generating bad code for "
1055                                         "10 bit stack mode.\n");
1056                         }
1057                         
1058                         if (stk) {
1059                                 pic14_emitcode ("mov","a,_bp");
1060                                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1061                                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1062                         } else {
1063                                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1064                         }
1065                         
1066                         while (sz--) {
1067                                 pic14_emitcode("pop","acc");
1068                                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1069                                 if (!sz) break;
1070                                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1071                         }
1072                         op->aop = aop;
1073                         freeAsmop(op,NULL,ic,TRUE);
1074                         if (_G.r0Pushed) {
1075                                 pic14_emitcode("pop","ar0");
1076                                 _G.r0Pushed--;
1077                         }
1078                         
1079                         if (_G.r1Pushed) {
1080                                 pic14_emitcode("pop","ar1");
1081                                 _G.r1Pushed--;
1082                         }         
1083                 }
1084         }
1085 #endif
1086         
1087 dealloc:
1088         /* all other cases just dealloc */
1089         if (op ) {
1090                 op->aop = NULL;
1091                 if (IS_SYMOP(op)) {
1092                         OP_SYMBOL(op)->aop = NULL;      
1093                         /* if the symbol has a spill */
1094                         if (SPIL_LOC(op))
1095                                 SPIL_LOC(op)->aop = NULL;
1096                 }
1097         }
1098 }
1099
1100 /*-----------------------------------------------------------------*/
1101 /* aopGet - for fetching value of the aop                                                  */
1102 /*-----------------------------------------------------------------*/
1103 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1104 {
1105         char *s = buffer ;
1106         char *rs;
1107         
1108         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1109         /* offset is greater than
1110         size then zero */
1111         if (offset > (aop->size - 1) &&
1112                 aop->type != AOP_LIT)
1113                 return zero;
1114         
1115         /* depending on type */
1116         switch (aop->type) {
1117                 
1118         case AOP_R0:
1119         case AOP_R1:
1120                 DEBUGpic14_emitcode(";","%d",__LINE__);
1121                 /* if we need to increment it */           
1122                 while (offset > aop->coff) {            
1123                         pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);    
1124                         aop->coff++;
1125                 }
1126                 
1127                 while (offset < aop->coff) {
1128                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1129                         aop->coff--;
1130                 }
1131                 
1132                 aop->coff = offset ;
1133                 if (aop->paged) {
1134                         pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1135                         return (dname ? "acc" : "a");
1136                 }               
1137                 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1138                 rs = Safe_calloc(1,strlen(s)+1);
1139                 strcpy(rs,s);   
1140                 return rs;
1141                 
1142         case AOP_DPTR:
1143         case AOP_DPTR2:
1144                 DEBUGpic14_emitcode(";","%d",__LINE__);
1145                 if (aop->type == AOP_DPTR2)
1146                 {
1147                         genSetDPTR(1);
1148                 }
1149                 
1150                 while (offset > aop->coff) {
1151                         pic14_emitcode ("inc","dptr");
1152                         aop->coff++;
1153                 }
1154                 
1155                 while (offset < aop->coff) {            
1156                         pic14_emitcode("lcall","__decdptr");
1157                         aop->coff--;
1158                 }
1159                 
1160                 aop->coff = offset;
1161                 if (aop->code) {
1162                         pic14_emitcode("clr","a");
1163                         pic14_emitcode("movc","a,@a+dptr");
1164                 }
1165                 else {
1166                         pic14_emitcode("movx","a,@dptr");
1167                 }
1168                 
1169                 if (aop->type == AOP_DPTR2)
1170                 {
1171                         genSetDPTR(0);
1172                 }
1173                 
1174                 return (dname ? "acc" : "a");
1175                 
1176                 
1177         case AOP_IMMD:
1178                 if (bit16) 
1179                         sprintf (s,"%s",aop->aopu.aop_immd);
1180                 else
1181                         if (offset) 
1182                                 sprintf(s,"(%s >> %d)",
1183                                 aop->aopu.aop_immd,
1184                                 offset*8);
1185                         else
1186                                 sprintf(s,"%s",
1187                                 aop->aopu.aop_immd);
1188                         DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1189                         rs = Safe_calloc(1,strlen(s)+1);
1190                         strcpy(rs,s);   
1191                         return rs;
1192                         
1193         case AOP_DIR:
1194                 if (offset) {
1195                         sprintf(s,"(%s + %d)",
1196                                 aop->aopu.aop_dir,
1197                                 offset);
1198                         DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1199                 } else
1200                         sprintf(s,"%s",aop->aopu.aop_dir);
1201                 rs = Safe_calloc(1,strlen(s)+1);
1202                 strcpy(rs,s);   
1203                 return rs;
1204                 
1205         case AOP_REG:
1206                 //if (dname) 
1207                 //        return aop->aopu.aop_reg[offset]->dname;
1208                 //else
1209                 return aop->aopu.aop_reg[offset]->name;
1210                 
1211         case AOP_CRY:
1212                 //pic14_emitcode(";","%d",__LINE__);
1213                 return aop->aopu.aop_dir;
1214                 
1215         case AOP_ACC:
1216                 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1217                 return "AOP_accumulator_bug";
1218                 
1219         case AOP_LIT:
1220                 sprintf(s, "0x%02x", pic14aopLiteral (aop->aopu.aop_lit, offset));
1221                 rs = Safe_strdup(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
1447         /* XXX: still needed for BIT operands (AOP_CRY) */
1448         if (offset > (aop->size - 1) &&
1449                 aop->type != AOP_LIT &&
1450                 aop->type != AOP_PCODE)
1451         {
1452                 printf( "%s: (offset[%d] > AOP_SIZE(op)[%d]-1) && AOP_TYPE(op) != AOP_LIT)\n", __FUNCTION__, offset, aop->size);
1453                 return NULL;  //zero;
1454         }
1455         
1456         /* depending on type */
1457         switch (aop->type) {
1458                 
1459         case AOP_R0:
1460         case AOP_R1:
1461         case AOP_DPTR:
1462         case AOP_DPTR2:
1463         case AOP_ACC:
1464                 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1465                 return NULL;
1466                 
1467         case AOP_IMMD:
1468                 DEBUGpic14_emitcode(";","%d",__LINE__);
1469                 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1470                 
1471         case AOP_DIR:
1472                 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1473 #if 0
1474                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1475                 pcop->type = PO_DIR;
1476                 
1477                 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1478                 strcpy(pcop->name,aop->aopu.aop_dir);   
1479                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1480                 if(PCOR(pcop)->r == NULL) {
1481                         //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1482                         PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1483                         DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1484                 } else {
1485                         DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1486                 }
1487                 PCOR(pcop)->instance = offset;
1488                 
1489                 return pcop;
1490 #endif
1491                 
1492         case AOP_REG:
1493                 {
1494                         int rIdx;
1495                         assert (offset < aop->size);
1496                         rIdx = aop->aopu.aop_reg[offset]->rIdx;
1497                         
1498                         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1499                         PCOR(pcop)->rIdx = rIdx;
1500                         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1501                         PCOR(pcop)->r->wasUsed=1;
1502                         PCOR(pcop)->r->isFree=0;
1503                         
1504                         PCOR(pcop)->instance = offset;
1505                         pcop->type = PCOR(pcop)->r->pc_type;
1506                         //rs = aop->aopu.aop_reg[offset]->name;
1507                         DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1508                         return pcop;
1509                 }
1510                 
1511         case AOP_CRY:
1512                 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1513                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1514                 //if(PCOR(pcop)->r == NULL)
1515                 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1516                 return pcop;
1517                 
1518         case AOP_LIT:
1519                 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1520                 
1521         case AOP_STR:
1522                 DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1523                 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1524                 /*
1525                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1526                 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1527                 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1528                 pcop->type = PCOR(pcop)->r->pc_type;
1529                 pcop->name = PCOR(pcop)->r->name;
1530                 
1531                   return pcop;
1532                 */
1533                 
1534         case AOP_PCODE:
1535                 pcop = NULL;
1536                 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1537                         __LINE__, 
1538                         ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1539                 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1540                 switch (aop->aopu.pcop->type)
1541                 {
1542                 case PO_IMMEDIATE:
1543                   pcop = pCodeOpCopy (aop->aopu.pcop);
1544                   /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1545                    * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1546                   PCOI(pcop)->index += offset;
1547                   //PCOI(pcop)->offset = 0;
1548                   break;
1549                 case PO_DIR:
1550                   pcop = pCodeOpCopy (aop->aopu.pcop);
1551                   PCOR(pcop)->instance = offset;
1552                   break;
1553                 default:
1554                   assert ( !"unhandled pCode type" );
1555                   break;
1556                 } // switch
1557                 return pcop;
1558         }
1559         
1560         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1561                 "popGet got unsupported aop->type");
1562         exit(0);
1563 }
1564
1565 /*-----------------------------------------------------------------*/
1566 /* popGetAddr - access the low/high word of a symbol (immediate)   */
1567 /*              (for non-PO_IMMEDIATEs this is the same as popGet) */
1568 /*-----------------------------------------------------------------*/
1569 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1570 {
1571   if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1572   {
1573     pCodeOp *pcop = aop->aopu.pcop;
1574     assert (offset <= GPTRSIZE);
1575
1576     /* special case: index >= 2 should return GPOINTER-style values */
1577     if (offset == 2)
1578     {
1579       pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1580       return pcop;
1581     }
1582     
1583     pcop = pCodeOpCopy (pcop);
1584     /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1585      * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1586     PCOI(pcop)->offset += offset;
1587     PCOI(pcop)->index += index;
1588     //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);
1589     return pcop;
1590   } else {
1591     return popGet (aop, offset + index);
1592   }
1593 }
1594
1595 /*-----------------------------------------------------------------*/
1596 /* aopPut - puts a string for a aop                                                        */
1597 /*-----------------------------------------------------------------*/
1598 void aopPut (asmop *aop, char *s, int offset)
1599 {
1600         char *d = buffer ;
1601         symbol *lbl ;
1602         
1603         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1604         
1605         if (aop->size && offset > ( aop->size - 1)) {
1606                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1607                         "aopPut got offset > aop->size");
1608                 exit(0);
1609         }
1610         
1611         /* will assign value to value */
1612         /* depending on where it is ofcourse */
1613         switch (aop->type) {
1614         case AOP_DIR:
1615                 if (offset) {
1616                         sprintf(d,"(%s + %d)",
1617                                 aop->aopu.aop_dir,offset);
1618                         fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1619                         
1620                 } else
1621                         sprintf(d,"%s",aop->aopu.aop_dir);
1622                 
1623                 if (strcmp(d,s)) {
1624                         DEBUGpic14_emitcode(";","%d",__LINE__);
1625                         if(strcmp(s,"W"))
1626                                 pic14_emitcode("movf","%s,w",s);
1627                         pic14_emitcode("movwf","%s",d);
1628                         
1629                         if(strcmp(s,"W")) {
1630                                 pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1631                                 if(offset >= aop->size) {
1632                                         emitpcode(POC_CLRF,popGet(aop,offset));
1633                                         break;
1634                                 } else {
1635                                         emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1636                                 }
1637                         }
1638                         emitpcode(POC_MOVWF,popGet(aop,offset));
1639                 
1640                 }
1641                 break;
1642                 
1643         case AOP_REG:
1644                 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1645                         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1646                         /*
1647                         if (*s == '@'             ||
1648                         strcmp(s,"r0") == 0 ||
1649                         strcmp(s,"r1") == 0 ||
1650                         strcmp(s,"r2") == 0 ||
1651                         strcmp(s,"r3") == 0 ||
1652                         strcmp(s,"r4") == 0 ||
1653                         strcmp(s,"r5") == 0 ||
1654                         strcmp(s,"r6") == 0 || 
1655                         strcmp(s,"r7") == 0 )
1656                         pic14_emitcode("mov","%s,%s  ; %d",
1657                         aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1658                         else
1659                         */
1660                         
1661                         if(strcmp(s,"W")==0 )
1662                                 pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1663                         
1664                         pic14_emitcode("movwf","%s",
1665                                 aop->aopu.aop_reg[offset]->name);
1666                         
1667                         if(strcmp(s,zero)==0) {
1668                                 emitpcode(POC_CLRF,popGet(aop,offset));
1669                                 
1670                         } else if(strcmp(s,"W")==0) {
1671                                 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1672                                 pcop->type = PO_GPR_REGISTER;
1673                                 
1674                                 PCOR(pcop)->rIdx = -1;
1675                                 PCOR(pcop)->r = NULL;
1676                                 
1677                                 DEBUGpic14_emitcode(";","%d",__LINE__);
1678                                 pcop->name = Safe_strdup(s);
1679                                 emitpcode(POC_MOVFW,pcop);
1680                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1681                         } else if(strcmp(s,one)==0) {
1682                                 emitpcode(POC_CLRF,popGet(aop,offset));
1683                                 emitpcode(POC_INCF,popGet(aop,offset));
1684                         } else {
1685                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1686                         }
1687                 }
1688                 break;
1689                 
1690         case AOP_DPTR:
1691         case AOP_DPTR2:
1692                 
1693                 if (aop->type == AOP_DPTR2)
1694                 {
1695                         genSetDPTR(1);
1696                 }
1697                 
1698                 if (aop->code) {
1699                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1700                                 "aopPut writting to code space");
1701                         exit(0);
1702                 }
1703                 
1704                 while (offset > aop->coff) {
1705                         aop->coff++;
1706                         pic14_emitcode ("inc","dptr");
1707                 }
1708                 
1709                 while (offset < aop->coff) {
1710                         aop->coff-- ;
1711                         pic14_emitcode("lcall","__decdptr");
1712                 }
1713                 
1714                 aop->coff = offset;
1715                 
1716                 /* if not in accumulater */
1717                 MOVA(s);
1718                 
1719                 pic14_emitcode ("movx","@dptr,a");
1720                 
1721                 if (aop->type == AOP_DPTR2)
1722                 {
1723                         genSetDPTR(0);
1724                 }
1725                 break;
1726                 
1727         case AOP_R0:
1728         case AOP_R1:
1729                 while (offset > aop->coff) {
1730                         aop->coff++;
1731                         pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1732                 }
1733                 while (offset < aop->coff) {
1734                         aop->coff-- ;
1735                         pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1736                 }
1737                 aop->coff = offset;
1738                 
1739                 if (aop->paged) {
1740                         MOVA(s);                         
1741                         pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1742                         
1743                 } else
1744                         if (*s == '@') {
1745                                 MOVA(s);
1746                                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1747                         } else
1748                                 if (strcmp(s,"r0") == 0 ||
1749                                         strcmp(s,"r1") == 0 ||
1750                                         strcmp(s,"r2") == 0 ||
1751                                         strcmp(s,"r3") == 0 ||
1752                                         strcmp(s,"r4") == 0 ||
1753                                         strcmp(s,"r5") == 0 ||
1754                                         strcmp(s,"r6") == 0 || 
1755                                         strcmp(s,"r7") == 0 ) {
1756                                         char buffer[10];
1757                                         sprintf(buffer,"a%s",s);
1758                                         pic14_emitcode("mov","@%s,%s",
1759                                                 aop->aopu.aop_ptr->name,buffer);
1760                                 } else
1761                                         pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1762                                 
1763                                 break;
1764                                 
1765         case AOP_STK:
1766                 if (strcmp(s,"a") == 0)
1767                         pic14_emitcode("push","acc");
1768                 else
1769                         pic14_emitcode("push","%s",s);
1770                 
1771                 break;
1772                 
1773         case AOP_CRY:
1774                 /* if bit variable */
1775                 if (!aop->aopu.aop_dir) {
1776                         pic14_emitcode("clr","a");
1777                         pic14_emitcode("rlc","a");
1778                 } else {
1779                         if (s == zero) 
1780                                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1781                         else
1782                                 if (s == one)
1783                                         pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1784                                 else
1785                                         if (!strcmp(s,"c"))
1786                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1787                                         else {
1788                                                 lbl = newiTempLabel(NULL);
1789                                                 
1790                                                 if (strcmp(s,"a")) {
1791                                                         MOVA(s);
1792                                                 }
1793                                                 pic14_emitcode("clr","c");
1794                                                 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1795                                                 pic14_emitcode("cpl","c");
1796                                                 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1797                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1798                                         }
1799                 }
1800                 break;
1801                 
1802         case AOP_STR:
1803                 aop->coff = offset;
1804                 if (strcmp(aop->aopu.aop_str[offset],s))
1805                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1806                 break;
1807                 
1808         case AOP_ACC:
1809                 aop->coff = offset;
1810                 if (!offset && (strcmp(s,"acc") == 0))
1811                         break;
1812                 
1813                 if (strcmp(aop->aopu.aop_str[offset],s))
1814                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1815                 break;
1816                 
1817         default :
1818                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1819                         "aopPut got unsupported aop->type");
1820                 exit(0);
1821         }
1822         
1823 }
1824
1825 /*-----------------------------------------------------------------*/
1826 /* mov2w_op - generate either a MOVLW or MOVFW based operand type  */
1827 /*-----------------------------------------------------------------*/
1828 static void mov2w_op (operand *op, int offset)
1829 {
1830         assert (op);
1831         FENTRY;
1832
1833         /* for PO_IMMEDIATEs: use address or value? */
1834         if (op_isLitLike (op))
1835         {
1836                 /* access address of op */
1837                 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1838                 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1839                 {
1840                         if (offset == GPTRSIZE-1)
1841                                 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1842                         else
1843                                 emitpcode (POC_MOVLW, popGetLit (0));
1844                 }
1845                 else
1846                         emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1847         } else {
1848                 /* access value stored in op */
1849                 mov2w (AOP(op), offset);
1850         }
1851 }
1852
1853
1854 /*-----------------------------------------------------------------*/
1855 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1856 /*-----------------------------------------------------------------*/
1857 void mov2w (asmop *aop, int offset)
1858 {
1859         
1860         if(!aop)
1861                 return;
1862         
1863         DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1864         
1865         if ( aop_isLitLike (aop) )
1866                 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1867         else
1868                 emitpcode(POC_MOVFW,popGet(aop,offset));
1869         
1870 }
1871
1872 static void movwf (asmop *op, int offset)
1873 {
1874         emitpcode (POC_MOVWF, popGet(op, offset));
1875 }
1876
1877 static pCodeOp *get_argument_pcop (int idx)
1878 {
1879         assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1880         return popRegFromIdx (Gstack_base_addr - (idx - 1));
1881 }
1882
1883 static pCodeOp *get_return_val_pcop (int offset)
1884 {
1885         assert (offset > 0 && "the most significant byte is returned via WREG");
1886         return popRegFromIdx (Gstack_base_addr - (offset - 1));
1887 }
1888
1889 static void pass_argument (operand *op, int offset, int idx)
1890 {
1891         if (op)
1892                 mov2w_op (op, offset);
1893         if (idx != 0)
1894                 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1895 }
1896
1897 static void get_returnvalue (operand *op, int offset, int idx)
1898 {
1899         if (idx != 0)
1900                 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1901         movwf(AOP(op), offset);
1902 }
1903
1904 static void call_libraryfunc (char *name)
1905 {
1906   /* library code might reside in different page... */
1907   emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1908   /* call the library function */
1909   emitpcode (POC_CALL, popGetExternal (name));
1910   /* might return from different page... */
1911   emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1912 }
1913 #if 0
1914 /*-----------------------------------------------------------------*/
1915 /* reAdjustPreg - points a register back to where it should        */
1916 /*-----------------------------------------------------------------*/
1917 static void reAdjustPreg (asmop *aop)
1918 {
1919         int size ;
1920         
1921         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1922         aop->coff = 0;
1923         if ((size = aop->size) <= 1)
1924                 return ;
1925         size-- ;
1926         switch (aop->type) {
1927         case AOP_R0 :
1928         case AOP_R1 :
1929                 while (size--)
1930                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1931                 break;                  
1932         case AOP_DPTR :
1933         case AOP_DPTR2:
1934                 if (aop->type == AOP_DPTR2)
1935                 {
1936                         genSetDPTR(1);
1937                 } 
1938                 while (size--)
1939                 {
1940                         pic14_emitcode("lcall","__decdptr");
1941                 }
1942                 
1943                 if (aop->type == AOP_DPTR2)
1944                 {
1945                         genSetDPTR(0);
1946                 }
1947                 break;
1948                 
1949         }
1950         
1951 }
1952 #endif
1953
1954
1955 #if 0
1956 /*-----------------------------------------------------------------*/
1957 /* opIsGptr: returns non-zero if the passed operand is             */
1958 /* a generic pointer type.                                         */
1959 /*-----------------------------------------------------------------*/ 
1960 static int opIsGptr(operand *op)
1961 {
1962         sym_link *type = operandType(op);
1963         
1964         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1965         if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1966         {
1967                 return 1;
1968         }
1969         return 0;          
1970 }
1971 #endif
1972
1973 /*-----------------------------------------------------------------*/
1974 /* pic14_getDataSize - get the operand data size                   */
1975 /*-----------------------------------------------------------------*/
1976 int pic14_getDataSize(operand *op)
1977 {
1978         int size;
1979         
1980         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1981         
1982 #if 0
1983         size = getSize(OP_SYM_ETYPE(op));
1984         return size;
1985         //return AOP_SIZE(op);
1986         
1987         // tsd- in the pic port, the genptr size is 1, so this code here
1988         // fails. ( in the 8051 port, the size was 4).
1989 #else
1990         size = AOP_SIZE(op);
1991         if (IS_GENPTR(OP_SYM_TYPE(op)))
1992         {
1993                 sym_link *type = operandType(op);
1994                 if (IS_GENPTR(type))
1995                 {
1996                         /* generic pointer; arithmetic operations
1997                         * should ignore the high byte (pointer type).
1998                         */
1999                         size--;
2000                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2001                 }
2002         }
2003         return size;
2004 #endif
2005 }
2006
2007 /*-----------------------------------------------------------------*/
2008 /* pic14_outAcc - output Acc                                       */
2009 /*-----------------------------------------------------------------*/
2010 void pic14_outAcc(operand *result)
2011 {
2012         int size,offset;
2013         DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2014         DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
2015         
2016         
2017         size = pic14_getDataSize(result);
2018         if(size){
2019                 emitpcode(POC_MOVWF,popGet(AOP(result),0));
2020                 size--;
2021                 offset = 1;
2022                 /* unsigned or positive */
2023                 while(size--)
2024                         emitpcode(POC_CLRF,popGet(AOP(result),offset++));
2025         }
2026         
2027 }
2028
2029 /*-----------------------------------------------------------------*/
2030 /* pic14_outBitC - output a bit C                                  */
2031 /*-----------------------------------------------------------------*/
2032 void pic14_outBitC(operand *result)
2033 {
2034         
2035         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2036         /* if the result is bit */
2037         if (AOP_TYPE(result) == AOP_CRY) 
2038                 aopPut(AOP(result),"c",0);
2039         else {
2040                 pic14_emitcode("clr","a  ; %d", __LINE__);
2041                 pic14_emitcode("rlc","a");
2042                 pic14_outAcc(result);
2043         }
2044 }
2045
2046 /*-----------------------------------------------------------------*/
2047 /* pic14_toBoolean - emit code for orl a,operator(sizeop)          */
2048 /*-----------------------------------------------------------------*/
2049 void pic14_toBoolean(operand *oper)
2050 {
2051         int size = AOP_SIZE(oper);
2052         int offset = 0;
2053         
2054         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2055
2056         assert (size > 0);
2057
2058         if (size == 1) {
2059                 /* MOVFW does not load the flags... */
2060                 if (AOP_TYPE(oper) == AOP_ACC) {
2061                         emitpcode(POC_IORLW, popGetLit(0));
2062                         offset = 1;
2063                 } else {
2064                         emitpcode(POC_MOVLW, popGetLit(0));
2065                         offset = 0;
2066                 }
2067         } else {
2068                 if ( AOP_TYPE(oper) != AOP_ACC) {
2069                         emitpcode(POC_MOVFW,popGet(AOP(oper),0));
2070                         offset = 1;
2071                 }
2072         }
2073         
2074         while (offset < size) {
2075                 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
2076         }
2077         /* Z is set iff (oper == 0) */
2078 }
2079
2080
2081 /*-----------------------------------------------------------------*/
2082 /* genNot - generate code for ! operation                          */
2083 /*-----------------------------------------------------------------*/
2084 static void genNot (iCode *ic)
2085 {
2086         //symbol *tlbl;
2087         int size;
2088
2089         FENTRY;
2090         
2091         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2092         /* assign asmOps to operand & result */
2093         aopOp (IC_LEFT(ic),ic,FALSE);
2094         aopOp (IC_RESULT(ic),ic,TRUE);
2095         
2096         DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2097         /* if in bit space then a special case */
2098         if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2099                 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2100                         emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2101                         emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2102                 } else {
2103                         emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2104                         emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2105                         emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2106                 }
2107                 goto release;
2108         }
2109         
2110         size = AOP_SIZE(IC_LEFT(ic));
2111         mov2w (AOP(IC_LEFT(ic)),0);
2112         while (--size > 0)
2113         {
2114           if (op_isLitLike (IC_LEFT(ic)))
2115             emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2116           else
2117             emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2118         }
2119         emitpcode(POC_MOVLW, popGetLit (0));
2120         emitSKPNZ;
2121         emitpcode(POC_MOVLW, popGetLit (1));
2122         movwf(AOP(IC_RESULT(ic)), 0);
2123
2124         for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2125         {
2126           emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2127         }
2128         goto release;
2129         
2130 release:        
2131         /* release the aops */
2132         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2133         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2134 }
2135
2136
2137 /*-----------------------------------------------------------------*/
2138 /* genCpl - generate code for complement                                                   */
2139 /*-----------------------------------------------------------------*/
2140 static void genCpl (iCode *ic)
2141 {
2142         operand *left, *result;
2143         int size, offset=0;  
2144         
2145         FENTRY;
2146         
2147         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2148         aopOp((left = IC_LEFT(ic)),ic,FALSE);
2149         aopOp((result=IC_RESULT(ic)),ic,TRUE);
2150         
2151         /* if both are in bit space then 
2152         a special case */
2153         if (AOP_TYPE(result) == AOP_CRY &&
2154                 AOP_TYPE(left) == AOP_CRY ) { 
2155                 
2156                 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir); 
2157                 pic14_emitcode("cpl","c"); 
2158                 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir); 
2159                 goto release; 
2160         } 
2161         
2162         size = AOP_SIZE(result);
2163         if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2164         while (size--) {
2165                 
2166                 if(AOP_TYPE(left) == AOP_ACC) 
2167                         emitpcode(POC_XORLW, popGetLit(0xff));
2168                 else
2169                         emitpcode(POC_COMFW,popGet(AOP(left),offset));
2170                 
2171                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2172                 offset++;
2173         }
2174         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2175         
2176         
2177 release:
2178         /* release the aops */
2179         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2180         freeAsmop(result,NULL,ic,TRUE);
2181 }
2182
2183 /*-----------------------------------------------------------------*/
2184 /* genUminusFloat - unary minus for floating points                        */
2185 /*-----------------------------------------------------------------*/
2186 static void genUminusFloat(operand *op,operand *result)
2187 {
2188         int size ,offset =0 ;
2189         char *l;
2190         
2191         FENTRY;
2192
2193         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2194         /* for this we just need to flip the 
2195         first it then copy the rest in place */
2196         size = AOP_SIZE(op) - 1;
2197         l = aopGet(AOP(op),3,FALSE,FALSE);
2198         
2199         MOVA(l);          
2200         
2201         pic14_emitcode("cpl","acc.7");
2202         aopPut(AOP(result),"a",3);      
2203         
2204         while(size--) {
2205                 aopPut(AOP(result),
2206                         aopGet(AOP(op),offset,FALSE,FALSE),
2207                         offset);
2208                 offset++;
2209         }                
2210 }
2211
2212 /*-----------------------------------------------------------------*/
2213 /* genUminus - unary minus code generation                                                 */
2214 /*-----------------------------------------------------------------*/
2215 static void genUminus (iCode *ic)
2216 {
2217         int size, i;
2218         sym_link *optype, *rtype;
2219         
2220         FENTRY;
2221         
2222         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2223         /* assign asmops */
2224         aopOp(IC_LEFT(ic),ic,FALSE);
2225         aopOp(IC_RESULT(ic),ic,TRUE);
2226         
2227         /* if both in bit space then special
2228         case */
2229         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2230                 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2231                 
2232                 emitpcode(POC_BCF,       popGet(AOP(IC_RESULT(ic)),0));
2233                 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2234                 emitpcode(POC_BSF,       popGet(AOP(IC_RESULT(ic)),0));
2235                 
2236                 goto release; 
2237         } 
2238         
2239         optype = operandType(IC_LEFT(ic));
2240         rtype = operandType(IC_RESULT(ic));
2241         
2242         /* if float then do float stuff */
2243         if (IS_FLOAT(optype)) {
2244                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2245                 goto release;
2246         }
2247         
2248         /* otherwise subtract from zero by taking the 2's complement */
2249         size = AOP_SIZE(IC_LEFT(ic));
2250         
2251         for(i=0; i<size; i++) {
2252                 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2253                         emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
2254                 else {
2255                         emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2256                         emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2257                 }
2258         }
2259         
2260         emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
2261         for(i=1; i<size; i++) {
2262                 emitSKPNZ;
2263                 emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
2264         }
2265         
2266 release:
2267         /* release the aops */
2268         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2269         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);  
2270 }
2271
2272 /*-----------------------------------------------------------------*/
2273 /* saveRegisters - will look for a call and save the registers     */
2274 /*-----------------------------------------------------------------*/
2275 static void saveRegisters(iCode *lic) 
2276 {
2277         int i;
2278         iCode *ic;
2279         bitVect *rsave;
2280         sym_link *dtype;
2281         
2282         FENTRY;
2283
2284         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2285         /* look for call */
2286         for (ic = lic ; ic ; ic = ic->next) 
2287                 if (ic->op == CALL || ic->op == PCALL)
2288                         break;
2289                 
2290                 if (!ic) {
2291                         fprintf(stderr,"found parameter push with no function call\n");
2292                         return ;
2293                 }
2294                 
2295                 /* if the registers have been saved already then
2296                 do nothing */
2297                 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2298                         return ;
2299                 
2300                         /* find the registers in use at this time 
2301                 and push them away to safety */
2302                 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2303                         ic->rUsed);
2304                 
2305                 ic->regsSaved = 1;
2306                 if (options.useXstack) {
2307                         if (bitVectBitValue(rsave,R0_IDX))
2308                                 pic14_emitcode("mov","b,r0");
2309                         pic14_emitcode("mov","r0,%s",spname);
2310                         for (i = 0 ; i < pic14_nRegs ; i++) {
2311                                 if (bitVectBitValue(rsave,i)) {
2312                                         if (i == R0_IDX)
2313                                                 pic14_emitcode("mov","a,b");
2314                                         else
2315                                                 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2316                                         pic14_emitcode("movx","@r0,a");
2317                                         pic14_emitcode("inc","r0");
2318                                 }
2319                         }
2320                         pic14_emitcode("mov","%s,r0",spname);
2321                         if (bitVectBitValue(rsave,R0_IDX))
2322                                 pic14_emitcode("mov","r0,b");     
2323                 }// else
2324                 //for (i = 0 ; i < pic14_nRegs ; i++) {
2325                 //        if (bitVectBitValue(rsave,i))
2326                 //      pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2327                 //}
2328                 
2329                 dtype = operandType(IC_LEFT(ic));
2330                 if (currFunc && dtype && 
2331                         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2332                         IFFUNC_ISISR(currFunc->type) &&
2333                         !ic->bankSaved) 
2334                         
2335                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2336                 
2337 }
2338 /*-----------------------------------------------------------------*/
2339 /* unsaveRegisters - pop the pushed registers                                      */
2340 /*-----------------------------------------------------------------*/
2341 static void unsaveRegisters (iCode *ic)
2342 {
2343         int i;
2344         bitVect *rsave;
2345         
2346         FENTRY;
2347
2348         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2349         /* find the registers in use at this time 
2350         and push them away to safety */
2351         rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2352                 ic->rUsed);
2353         
2354         if (options.useXstack) {
2355                 pic14_emitcode("mov","r0,%s",spname); 
2356                 for (i =  pic14_nRegs ; i >= 0 ; i--) {
2357                         if (bitVectBitValue(rsave,i)) {
2358                                 pic14_emitcode("dec","r0");
2359                                 pic14_emitcode("movx","a,@r0");
2360                                 if (i == R0_IDX)
2361                                         pic14_emitcode("mov","b,a");
2362                                 else
2363                                         pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2364                         }       
2365                         
2366                 }
2367                 pic14_emitcode("mov","%s,r0",spname);
2368                 if (bitVectBitValue(rsave,R0_IDX))
2369                         pic14_emitcode("mov","r0,b");
2370         } //else
2371         //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2372         //      if (bitVectBitValue(rsave,i))
2373         //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2374         //}
2375         
2376 }  
2377
2378
2379 /*-----------------------------------------------------------------*/
2380 /* pushSide -                            */
2381 /*-----------------------------------------------------------------*/
2382 static void pushSide(operand * oper, int size)
2383 {
2384 #if 0
2385         int offset = 0;
2386         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2387         while (size--) {
2388                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2389                 if (AOP_TYPE(oper) != AOP_REG &&
2390                         AOP_TYPE(oper) != AOP_DIR &&
2391                         strcmp(l,"a") ) {
2392                         pic14_emitcode("mov","a,%s",l);
2393                         pic14_emitcode("push","acc");
2394                 } else
2395                         pic14_emitcode("push","%s",l);
2396         }
2397 #endif
2398 }
2399
2400 /*-----------------------------------------------------------------*/
2401 /* assignResultValue -                           */
2402 /*-----------------------------------------------------------------*/
2403 static void assignResultValue(operand * oper)
2404 {
2405         int size = AOP_SIZE(oper);
2406         int offset = 0;
2407         
2408         FENTRY;
2409
2410         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2411         
2412         DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2413         
2414         /* assign MSB first (passed via WREG) */
2415         while (size--) {
2416                 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2417                 GpsuedoStkPtr++;
2418         }
2419 }
2420
2421
2422 /*-----------------------------------------------------------------*/
2423 /* genIpush - genrate code for pushing this gets a little complex  */
2424 /*-----------------------------------------------------------------*/
2425 static void genIpush (iCode *ic)
2426 {
2427         FENTRY;
2428         
2429         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2430 #if 0
2431         int size, offset = 0 ;
2432         char *l;
2433         
2434         
2435         /* if this is not a parm push : ie. it is spill push 
2436         and spill push is always done on the local stack */
2437         if (!ic->parmPush) {
2438                 
2439                 /* and the item is spilt then do nothing */
2440                 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2441                         return ;
2442                 
2443                 aopOp(IC_LEFT(ic),ic,FALSE);
2444                 size = AOP_SIZE(IC_LEFT(ic));
2445                 /* push it on the stack */
2446                 while(size--) {
2447                         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2448                         if (*l == '#') {
2449                                 MOVA(l);
2450                                 l = "acc";
2451                         }
2452                         pic14_emitcode("push","%s",l);
2453                 }
2454                 return ;                
2455         }
2456         
2457         /* this is a paramter push: in this case we call
2458         the routine to find the call and save those
2459         registers that need to be saved */   
2460         saveRegisters(ic);
2461         
2462         /* then do the push */
2463         aopOp(IC_LEFT(ic),ic,FALSE);
2464         
2465         
2466         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2467         size = AOP_SIZE(IC_LEFT(ic));
2468         
2469         while (size--) {
2470                 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2471                 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2472                         AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2473                         strcmp(l,"a") ) {
2474                         pic14_emitcode("mov","a,%s",l);
2475                         pic14_emitcode("push","acc");
2476                 } else
2477                         pic14_emitcode("push","%s",l);
2478         }         
2479         
2480         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2481 #endif
2482 }
2483
2484 /*-----------------------------------------------------------------*/
2485 /* genIpop - recover the registers: can happen only for spilling   */
2486 /*-----------------------------------------------------------------*/
2487 static void genIpop (iCode *ic)
2488 {
2489         FENTRY;
2490
2491         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2492         assert (!"genIpop -- unimplemented");
2493 #if 0
2494         int size,offset ;
2495         
2496         
2497         /* if the temp was not pushed then */
2498         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2499                 return ;
2500         
2501         aopOp(IC_LEFT(ic),ic,FALSE);
2502         size = AOP_SIZE(IC_LEFT(ic));
2503         offset = (size-1);
2504         while (size--) 
2505                 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2506                 FALSE,TRUE));
2507         
2508         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2509 #endif
2510 }
2511
2512 /*-----------------------------------------------------------------*/
2513 /* unsaverbank - restores the resgister bank from stack                    */
2514 /*-----------------------------------------------------------------*/
2515 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2516 {
2517         FENTRY;
2518
2519         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2520 #if 0
2521         int i;
2522         asmop *aop ;
2523         regs *r = NULL;
2524         
2525         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2526         if (popPsw) {
2527                 if (options.useXstack) {
2528                         aop = newAsmop(0);
2529                         r = getFreePtr(ic,&aop,FALSE);
2530                         
2531                         
2532                         pic14_emitcode("mov","%s,_spx",r->name);
2533                         pic14_emitcode("movx","a,@%s",r->name);
2534                         pic14_emitcode("mov","psw,a");
2535                         pic14_emitcode("dec","%s",r->name);
2536                         
2537                 }else
2538                         pic14_emitcode ("pop","psw");
2539         }
2540         
2541         for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2542                 if (options.useXstack) {           
2543                         pic14_emitcode("movx","a,@%s",r->name);
2544                         //pic14_emitcode("mov","(%s+%d),a",
2545                         //         regspic14[i].base,8*bank+regspic14[i].offset);
2546                         pic14_emitcode("dec","%s",r->name);
2547                         
2548                 } else 
2549                         pic14_emitcode("pop",""); //"(%s+%d)",
2550                 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2551         }
2552         
2553         if (options.useXstack) {
2554                 
2555                 pic14_emitcode("mov","_spx,%s",r->name);
2556                 freeAsmop(NULL,aop,ic,TRUE);
2557                 
2558         }
2559 #endif 
2560 }
2561
2562 /*-----------------------------------------------------------------*/
2563 /* saverbank - saves an entire register bank on the stack                  */
2564 /*-----------------------------------------------------------------*/
2565 static void saverbank (int bank, iCode *ic, bool pushPsw)
2566 {
2567         FENTRY;
2568
2569         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2570 #if 0
2571         int i;
2572         asmop *aop ;
2573         regs *r = NULL;
2574         
2575         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2576         if (options.useXstack) {
2577                 
2578                 aop = newAsmop(0);
2579                 r = getFreePtr(ic,&aop,FALSE);  
2580                 pic14_emitcode("mov","%s,_spx",r->name);
2581                 
2582         }
2583         
2584         for (i = 0 ; i < pic14_nRegs ;i++) {
2585                 if (options.useXstack) {
2586                         pic14_emitcode("inc","%s",r->name);
2587                         //pic14_emitcode("mov","a,(%s+%d)",
2588                         //               regspic14[i].base,8*bank+regspic14[i].offset);
2589                         pic14_emitcode("movx","@%s,a",r->name);                 
2590                 } else 
2591                         pic14_emitcode("push","");// "(%s+%d)",
2592                 //regspic14[i].base,8*bank+regspic14[i].offset);
2593         }
2594         
2595         if (pushPsw) {
2596                 if (options.useXstack) {
2597                         pic14_emitcode("mov","a,psw");
2598                         pic14_emitcode("movx","@%s,a",r->name); 
2599                         pic14_emitcode("inc","%s",r->name);
2600                         pic14_emitcode("mov","_spx,%s",r->name);                 
2601                         freeAsmop (NULL,aop,ic,TRUE);
2602                         
2603                 } else
2604                         pic14_emitcode("push","psw");
2605                 
2606                 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2607         }
2608         ic->bankSaved = 1;
2609 #endif
2610 }
2611
2612 /*-----------------------------------------------------------------*/
2613 /* genCall - generates a call statement                                                    */
2614 /*-----------------------------------------------------------------*/
2615 static void genCall (iCode *ic)
2616 {
2617         sym_link *dtype;         
2618         symbol *sym;
2619         char *name;
2620         int isExtern;
2621         
2622         FENTRY;
2623
2624         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2625         
2626         /* if caller saves & we have not saved then */
2627         if (!ic->regsSaved)
2628                 saveRegisters(ic);
2629         
2630                 /* if we are calling a function that is not using
2631                 the same register bank then we need to save the
2632         destination registers on the stack */
2633         dtype = operandType(IC_LEFT(ic));
2634         if (currFunc && dtype && 
2635                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2636                 IFFUNC_ISISR(currFunc->type) &&
2637                 !ic->bankSaved) 
2638                 
2639                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2640         
2641         /* if send set is not empty the assign */
2642         if (_G.sendSet) {
2643                 iCode *sic;
2644                 /* For the Pic port, there is no data stack.
2645                 * So parameters passed to functions are stored
2646                 * in registers. (The pCode optimizer will get
2647                 * rid of most of these :).
2648                 */
2649                 int psuedoStkPtr=-1;
2650                 int firstTimeThruLoop = 1;
2651                 
2652                 _G.sendSet = reverseSet(_G.sendSet);
2653                 
2654                 /* First figure how many parameters are getting passed */
2655                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2656                 sic = setNextItem(_G.sendSet)) {
2657                         
2658                         aopOp(IC_LEFT(sic),sic,FALSE);
2659                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2660                         freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2661                 }
2662                 
2663                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2664                 sic = setNextItem(_G.sendSet)) {
2665                         int size, offset = 0;
2666                         
2667                         aopOp(IC_LEFT(sic),sic,FALSE);
2668                         size = AOP_SIZE(IC_LEFT(sic));
2669                         
2670                         while (size--) {
2671                                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2672                                         AopType(AOP_TYPE(IC_LEFT(sic))));
2673                                 
2674                                 if(!firstTimeThruLoop) {
2675                                         /* If this is not the first time we've been through the loop
2676                                         * then we need to save the parameter in a temporary
2677                                         * register. The last byte of the last parameter is
2678                                         * passed in W. */
2679                                         emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2680                                         
2681                                 }
2682                                 firstTimeThruLoop=0;
2683                                 
2684                                 mov2w_op (IC_LEFT(sic),  offset);
2685                                 offset++;
2686                         }
2687                         freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2688                 }
2689                 _G.sendSet = NULL;
2690         }
2691         /* make the call */
2692         sym = OP_SYMBOL(IC_LEFT(ic));
2693         name = sym->rname[0] ? sym->rname : sym->name;
2694         isExtern = IS_EXTERN(sym->etype) || pic14_inISR;
2695         if (isExtern) {
2696                 /* Extern functions and ISRs maybe on a different page;
2697                  * must call pagesel */
2698                 emitpcode(POC_PAGESEL,popGetWithString(name,1));
2699         }
2700         emitpcode(POC_CALL,popGetWithString(name,isExtern));
2701         if (isExtern) {
2702                 /* May have returned from a different page;
2703                  * must use pagesel to restore PCLATH before next
2704                  * goto or call instruction */
2705                 emitpcode(POC_PAGESEL,popGetWithString("$",0));
2706         }
2707         GpsuedoStkPtr=0;
2708         /* if we need assign a result value */
2709         if ((IS_ITEMP(IC_RESULT(ic)) && 
2710                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2711                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2712                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2713                 
2714                 _G.accInUse++;
2715                 aopOp(IC_RESULT(ic),ic,FALSE);
2716                 _G.accInUse--;
2717                 
2718                 assignResultValue(IC_RESULT(ic));
2719                 
2720                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2721                         AopType(AOP_TYPE(IC_RESULT(ic))));
2722                 
2723                 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2724         }
2725         
2726         /* if register bank was saved then pop them */
2727         if (ic->bankSaved)
2728                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2729         
2730         /* if we hade saved some registers then unsave them */
2731         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2732                 unsaveRegisters (ic);
2733         
2734         
2735 }
2736
2737 /*-----------------------------------------------------------------*/
2738 /* genPcall - generates a call by pointer statement                        */
2739 /*-----------------------------------------------------------------*/
2740 static void genPcall (iCode *ic)
2741 {
2742         sym_link *dtype;
2743         symbol *albl = newiTempLabel(NULL);
2744         symbol *blbl = newiTempLabel(NULL);
2745         PIC_OPCODE poc;
2746         pCodeOp *pcop;
2747         operand *left;
2748         
2749         FENTRY;
2750
2751         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2752         /* if caller saves & we have not saved then */
2753         if (!ic->regsSaved)
2754                 saveRegisters(ic);
2755         
2756                 /* if we are calling a function that is not using
2757                 the same register bank then we need to save the
2758         destination registers on the stack */
2759         dtype = operandType(IC_LEFT(ic));
2760         if (currFunc && dtype && 
2761                 IFFUNC_ISISR(currFunc->type) &&
2762                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2763                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2764         
2765         left = IC_LEFT(ic);
2766         aopOp(left,ic,FALSE);
2767         DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2768         
2769         poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2770         
2771         pushSide(IC_LEFT(ic), FPTRSIZE);
2772         
2773         /* if send set is not empty, assign parameters */
2774         if (_G.sendSet) {
2775                 
2776                 DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2777                 /* no way to pass args - W always gets used to make the call */
2778         }
2779         /* first idea - factor out a common helper function and call it.
2780         But don't know how to get it generated only once in its own block
2781         
2782         if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2783                 char *rname;
2784                 char *buffer;
2785                 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2786                 DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2787                 buffer = Safe_calloc(1,strlen(rname)+16);
2788                 sprintf(buffer, "%s_goto_helper", rname);
2789                 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2790                 free(buffer);
2791         }
2792         */
2793         emitpcode(POC_CALL,popGetLabel(albl->key));
2794         pcop = popGetLabel(blbl->key);
2795         emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2796         emitpcode(POC_GOTO,pcop);
2797         emitpLabel(albl->key);
2798         
2799         emitpcode(poc,popGetAddr(AOP(left),1,0));
2800         emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2801         emitpcode(poc,popGetAddr(AOP(left),0,0));
2802         emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2803         
2804         emitpLabel(blbl->key);
2805         
2806         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2807         
2808         /* if we need to assign a result value */
2809         if ((IS_ITEMP(IC_RESULT(ic)) &&
2810                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2811                 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2812                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2813                 
2814                 _G.accInUse++;
2815                 aopOp(IC_RESULT(ic),ic,FALSE);
2816                 _G.accInUse--;
2817
2818                 GpsuedoStkPtr = 0;
2819                 
2820                 assignResultValue(IC_RESULT(ic));
2821                 
2822                 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2823         }
2824         
2825         /* if register bank was saved then unsave them */
2826         if (currFunc && dtype && 
2827                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2828                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2829         
2830                 /* if we hade saved some registers then
2831         unsave them */
2832         if (ic->regsSaved)
2833                 unsaveRegisters (ic);
2834         
2835 }
2836
2837 /*-----------------------------------------------------------------*/
2838 /* resultRemat - result  is rematerializable                                       */
2839 /*-----------------------------------------------------------------*/
2840 static int resultRemat (iCode *ic)
2841 {
2842         //      DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2843         FENTRY;
2844
2845         if (SKIP_IC(ic) || ic->op == IFX)
2846                 return 0;
2847         
2848         if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2849                 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2850                 if (sym->remat && !POINTER_SET(ic)) 
2851                         return 1;
2852         }
2853         
2854         return 0;
2855 }
2856
2857 #if defined(__BORLANDC__) || defined(_MSC_VER)
2858 #define STRCASECMP stricmp
2859 #else
2860 #define STRCASECMP strcasecmp
2861 #endif
2862
2863 #if 0
2864 /*-----------------------------------------------------------------*/
2865 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2866 /*-----------------------------------------------------------------*/
2867 static bool inExcludeList(char *s)
2868 {
2869         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2870         int i =0;
2871         
2872         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2873         if (options.excludeRegs[i] &&
2874                 STRCASECMP(options.excludeRegs[i],"none") == 0)
2875                 return FALSE ;
2876         
2877         for ( i = 0 ; options.excludeRegs[i]; i++) {
2878                 if (options.excludeRegs[i] &&
2879                         STRCASECMP(s,options.excludeRegs[i]) == 0)
2880                         return TRUE;
2881         }
2882         return FALSE ;
2883 }
2884 #endif
2885
2886 /*-----------------------------------------------------------------*/
2887 /* genFunction - generated code for function entry                                 */
2888 /*-----------------------------------------------------------------*/
2889 static void genFunction (iCode *ic)
2890 {
2891         symbol *sym;
2892         sym_link *ftype;
2893         
2894         FENTRY;
2895
2896         DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2897         
2898         labelOffset += (max_key+4);
2899         max_key=0;
2900         GpsuedoStkPtr=0;
2901         _G.nRegsSaved = 0;
2902         /* create the function header */
2903         pic14_emitcode(";","-----------------------------------------");
2904         pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2905         pic14_emitcode(";","-----------------------------------------");
2906         
2907         /* prevent this symbol from being emitted as 'extern' */
2908         pic14_stringInSet(sym->rname, &pic14_localFunctions, 1);
2909
2910         pic14_emitcode("","%s:",sym->rname);
2911         addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2912         
2913         ftype = operandType(IC_LEFT(ic));
2914         
2915         /* if critical function then turn interrupts off */
2916         if (IFFUNC_ISCRITICAL(ftype))
2917                 pic14_emitcode("clr","ea");
2918         
2919                 /* here we need to generate the equates for the
2920         register bank if required */
2921 #if 0
2922         if (FUNC_REGBANK(ftype) != rbank) {
2923                 int i ;
2924                 
2925                 rbank = FUNC_REGBANK(ftype);
2926                 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2927                         if (strcmp(regspic14[i].base,"0") == 0)
2928                                 pic14_emitcode("","%s = 0x%02x",
2929                                 regspic14[i].dname,
2930                                 8*rbank+regspic14[i].offset);
2931                         else
2932                                 pic14_emitcode ("","%s = %s + 0x%02x",
2933                                 regspic14[i].dname,
2934                                 regspic14[i].base,
2935                                 8*rbank+regspic14[i].offset);
2936                 }
2937         }
2938 #endif
2939         
2940         /* if this is an interrupt service routine */
2941         pic14_inISR = 0;
2942         if (IFFUNC_ISISR(sym->type)) {
2943                 pic14_inISR = 1;
2944         /*  already done in pic14createInterruptVect() - delete me
2945         addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2946         emitpcodeNULLop(POC_NOP);
2947         emitpcodeNULLop(POC_NOP);
2948         emitpcodeNULLop(POC_NOP);
2949                 */
2950                 emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2951                 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2952                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2953                 emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2954                 emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2955                 emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2956                 emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2957                 
2958                 pBlockConvert2ISR(pb);
2959                 pic14_hasInterrupt = 1;
2960 #if 0  
2961                 if (!inExcludeList("acc"))              
2962                         pic14_emitcode ("push","acc");  
2963                 if (!inExcludeList("b"))
2964                         pic14_emitcode ("push","b");
2965                 if (!inExcludeList("dpl"))
2966                         pic14_emitcode ("push","dpl");
2967                 if (!inExcludeList("dph"))
2968                         pic14_emitcode ("push","dph");
2969                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2970                 {
2971                         pic14_emitcode ("push", "dpx");
2972                         /* Make sure we're using standard DPTR */
2973                         pic14_emitcode ("push", "dps");
2974                         pic14_emitcode ("mov", "dps, #0x00");
2975                         if (options.stack10bit)
2976                         { 
2977                                 /* This ISR could conceivably use DPTR2. Better save it. */
2978                                 pic14_emitcode ("push", "dpl1");
2979                                 pic14_emitcode ("push", "dph1");
2980                                 pic14_emitcode ("push", "dpx1");
2981                         }
2982                 }
2983                 /* if this isr has no bank i.e. is going to
2984                 run with bank 0 , then we need to save more
2985                 registers :-) */
2986                 if (!FUNC_REGBANK(sym->type)) {
2987                         
2988                 /* if this function does not call any other
2989                 function then we can be economical and
2990                         save only those registers that are used */
2991                         if (! IFFUNC_HASFCALL(sym->type)) {
2992                                 int i;
2993                                 
2994                                 /* if any registers used */
2995                                 if (sym->regsUsed) {
2996                                         /* save the registers used */
2997                                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2998                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2999                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3000                                                         pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);               
3001                                         }
3002                                 }
3003                                 
3004                         } else {
3005                         /* this function has    a function call cannot
3006                         determines register usage so we will have the
3007                                 entire bank */
3008                                 saverbank(0,ic,FALSE);
3009                         }       
3010                 }
3011 #endif
3012         } else {
3013         /* if callee-save to be used for this function
3014                 then save the registers being used in this function */
3015                 if (IFFUNC_CALLEESAVES(sym->type)) {
3016                         int i;
3017                         
3018                         /* if any registers used */
3019                         if (sym->regsUsed) {
3020                                 /* save the registers used */
3021                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3022                                         if (bitVectBitValue(sym->regsUsed,i) ||
3023                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
3024                                                 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
3025                                                 _G.nRegsSaved++;
3026                                         }
3027                                 }
3028                         }
3029                 }
3030         }
3031         
3032         /* set the register bank to the desired value */
3033         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
3034                 pic14_emitcode("push","psw");
3035                 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);       
3036         }
3037         
3038         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3039                 
3040                 if (options.useXstack) {
3041                         pic14_emitcode("mov","r0,%s",spname);
3042                         pic14_emitcode("mov","a,_bp");
3043                         pic14_emitcode("movx","@r0,a");
3044                         pic14_emitcode("inc","%s",spname);
3045                 }
3046                 else
3047                 {
3048                         /* set up the stack */
3049                         pic14_emitcode ("push","_bp");   /* save the callers stack      */
3050                 }
3051                 pic14_emitcode ("mov","_bp,%s",spname);
3052         }
3053         
3054         /* adjust the stack for the function */
3055         if (sym->stack) {
3056                 
3057                 int i = sym->stack;
3058                 if (i > 256 ) 
3059                         werror(W_STACK_OVERFLOW,sym->name);
3060                 
3061                 if (i > 3 && sym->recvSize < 4) {                
3062                         
3063                         pic14_emitcode ("mov","a,sp");
3064                         pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3065                         pic14_emitcode ("mov","sp,a");
3066                         
3067                 }
3068                 else
3069                         while(i--)
3070                                 pic14_emitcode("inc","sp");
3071         }
3072         
3073         if (sym->xstack) {
3074                 
3075                 pic14_emitcode ("mov","a,_spx");
3076                 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3077                 pic14_emitcode ("mov","_spx,a");
3078         }
3079         
3080 }
3081
3082 /*-----------------------------------------------------------------*/
3083 /* genEndFunction - generates epilogue for functions                       */
3084 /*-----------------------------------------------------------------*/
3085 static void genEndFunction (iCode *ic)
3086 {
3087         symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3088         
3089         FENTRY;
3090
3091         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3092         
3093         if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3094         {
3095                 pic14_emitcode ("mov","%s,_bp",spname);
3096         }
3097         
3098         /* if use external stack but some variables were
3099         added to the local stack then decrement the
3100         local stack */
3101         if (options.useXstack && sym->stack) {    
3102                 pic14_emitcode("mov","a,sp");
3103                 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3104                 pic14_emitcode("mov","sp,a");
3105         }
3106         
3107         
3108         if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3109                 if (options.useXstack) {
3110                         pic14_emitcode("mov","r0,%s",spname);
3111                         pic14_emitcode("movx","a,@r0");
3112                         pic14_emitcode("mov","_bp,a");
3113                         pic14_emitcode("dec","%s",spname);
3114                 }
3115                 else
3116                 {
3117                         pic14_emitcode ("pop","_bp");
3118                 }
3119         }
3120         
3121         /* restore the register bank    */        
3122         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3123                 pic14_emitcode ("pop","psw");
3124         
3125         if (IFFUNC_ISISR(sym->type)) {
3126                 
3127                 /* now we need to restore the registers */
3128                 /* if this isr has no bank i.e. is going to
3129                 run with bank 0 , then we need to save more
3130 registers :-) */
3131                 if (!FUNC_REGBANK(sym->type)) {
3132                         
3133                 /* if this function does not call any other
3134                 function then we can be economical and
3135                         save only those registers that are used */
3136                         if (! IFFUNC_HASFCALL(sym->type)) {
3137                                 int i;
3138                                 
3139                                 /* if any registers used */
3140                                 if (sym->regsUsed) {
3141                                         /* save the registers used */
3142                                         for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3143                                                 if (bitVectBitValue(sym->regsUsed,i) ||
3144                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3145                                                         pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3146                                         }
3147                                 }
3148                                 
3149                         } else {
3150                         /* this function has    a function call cannot
3151                         determines register usage so we will have the
3152                                 entire bank */
3153                                 unsaverbank(0,ic,FALSE);
3154                         }       
3155                 }
3156 #if 0
3157                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3158                 {
3159                         if (options.stack10bit)
3160                         {
3161                                 pic14_emitcode ("pop", "dpx1");
3162                                 pic14_emitcode ("pop", "dph1");
3163                                 pic14_emitcode ("pop", "dpl1");
3164                         } 
3165                         pic14_emitcode ("pop", "dps");
3166                         pic14_emitcode ("pop", "dpx");
3167                 }
3168                 if (!inExcludeList("dph"))
3169                         pic14_emitcode ("pop","dph");
3170                 if (!inExcludeList("dpl"))
3171                         pic14_emitcode ("pop","dpl");
3172                 if (!inExcludeList("b"))
3173                         pic14_emitcode ("pop","b");
3174                 if (!inExcludeList("acc"))
3175                         pic14_emitcode ("pop","acc");
3176                 
3177                 if (IFFUNC_ISCRITICAL(sym->type))
3178                         pic14_emitcode("setb","ea");
3179 #endif
3180                 
3181                 /* if debug then send end of function */
3182                 /*      if (options.debug && currFunc) { */
3183                 if (currFunc) {
3184                         debugFile->writeEndFunction (currFunc, ic, 1);
3185                 }
3186                 
3187                 pic14_emitcode ("reti","");
3188                 emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
3189                 emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
3190                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
3191                 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3192                 emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
3193                 emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
3194                 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3195                 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3196                 emitpcodeNULLop(POC_RETFIE);
3197         }
3198         else {
3199                 if (IFFUNC_ISCRITICAL(sym->type))
3200                         pic14_emitcode("setb","ea");
3201                 
3202                 if (IFFUNC_CALLEESAVES(sym->type)) {
3203                         int i;
3204                         
3205                         /* if any registers used */
3206                         if (sym->regsUsed) {
3207                                 /* save the registers used */
3208                                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3209                                         if (bitVectBitValue(sym->regsUsed,i) ||
3210                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3211                                                 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3212                                 }
3213                         }
3214                         
3215                 }
3216                 
3217                 /* if debug then send end of function */
3218                 if (currFunc) {
3219                         debugFile->writeEndFunction (currFunc, ic, 1);
3220                 }
3221                 
3222                 pic14_emitcode ("return","");
3223                 emitpcodeNULLop(POC_RETURN);
3224                 
3225                 /* Mark the end of a function */
3226                 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3227         }
3228         
3229 }
3230
3231 /*-----------------------------------------------------------------*/
3232 /* genRet - generate code for return statement                                     */
3233 /*-----------------------------------------------------------------*/
3234 static void genRet (iCode *ic)
3235 {
3236         int size,offset = 0;
3237         
3238         FENTRY;
3239
3240         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3241         /* if we have no return value then
3242         just generate the "ret" */
3243         if (!IC_LEFT(ic)) 
3244                 goto jumpret;           
3245         
3246                 /* we have something to return then
3247         move the return value into place */
3248         aopOp(IC_LEFT(ic),ic,FALSE);
3249         size = AOP_SIZE(IC_LEFT(ic));
3250
3251         for (offset = 0; offset < size; offset++)
3252         {
3253                 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3254         }
3255         
3256         freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3257         
3258 jumpret:
3259         /* generate a jump to the return label
3260         if the next is not the return statement */
3261         if (!(ic->next && ic->next->op == LABEL &&
3262                 IC_LABEL(ic->next) == returnLabel)) {
3263                 
3264                 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3265         }
3266         
3267 }
3268
3269 /*-----------------------------------------------------------------*/
3270 /* genLabel - generates a label                                                                    */
3271 /*-----------------------------------------------------------------*/
3272 static void genLabel (iCode *ic)
3273 {
3274         FENTRY;
3275
3276         /* special case never generate */
3277         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3278         if (IC_LABEL(ic) == entryLabel)
3279                 return ;
3280         
3281         emitpLabel(IC_LABEL(ic)->key);
3282         pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3283 }
3284
3285 /*-----------------------------------------------------------------*/
3286 /* genGoto - generates a goto                                                                      */
3287 /*-----------------------------------------------------------------*/
3288 //tsd
3289 static void genGoto (iCode *ic)
3290 {
3291         FENTRY;
3292
3293         emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3294         pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3295 }
3296
3297
3298 /*-----------------------------------------------------------------*/
3299 /* genMultbits :- multiplication of bits                                                   */
3300 /*-----------------------------------------------------------------*/
3301 static void genMultbits (operand *left, 
3302                                                  operand *right, 
3303                                                  operand *result)
3304 {
3305         FENTRY;
3306         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3307         
3308         if(!pic14_sameRegs(AOP(result),AOP(right)))
3309                 emitpcode(POC_BSF,      popGet(AOP(result),0));
3310         
3311         emitpcode(POC_BTFSC,popGet(AOP(right),0));
3312         emitpcode(POC_BTFSS,popGet(AOP(left),0));
3313         emitpcode(POC_BCF,  popGet(AOP(result),0));
3314         
3315 }
3316
3317
3318 /*-----------------------------------------------------------------*/
3319 /* genMultOneByte : 8 bit multiplication & division                        */
3320 /*-----------------------------------------------------------------*/
3321 static void genMultOneByte (operand *left,
3322                                                         operand *right,
3323                                                         operand *result)
3324 {
3325         char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3326         
3327         // symbol *lbl ;
3328         int size,offset,i;
3329         
3330         
3331         FENTRY;
3332         
3333         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3334         DEBUGpic14_AopType(__LINE__,left,right,result);
3335         DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3336         
3337         /* (if two literals, the value is computed before) */
3338         /* if one literal, literal on the right */
3339         if (AOP_TYPE(left) == AOP_LIT){
3340                 operand *t = right;
3341                 right = left;
3342                 left = t;
3343         }
3344
3345         assert (AOP_SIZE(left) == AOP_SIZE(right));
3346         
3347         size = min(AOP_SIZE(result),AOP_SIZE(left));
3348         offset = Gstack_base_addr - (2*size - 1);
3349
3350         /* pass right operand as argument */
3351         for (i=0; i < size; i++)
3352         {
3353                 mov2w (AOP(right), i);
3354                 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3355         } // for
3356         
3357         /* pass left operand as argument */
3358         for (i=0; i < size; i++)
3359         {
3360                 mov2w (AOP(left), i);
3361                 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3362         } // for
3363         assert (offset == Gstack_base_addr);
3364         
3365         /* call library routine */
3366         assert (size > 0 && size <= 4);
3367         call_libraryfunc (func[size]);
3368         
3369         /* assign result */
3370         movwf (AOP(result), size-1);
3371         for (i=0; i < size - 1; i++)
3372         {
3373                 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3374                 movwf (AOP(result), size - 2 - i);
3375         } // for
3376
3377         /* now (zero-/sign) extend the result to its size */
3378         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3379 }
3380
3381 /*-----------------------------------------------------------------*/
3382 /* genMult - generates code for multiplication                                     */
3383 /*-----------------------------------------------------------------*/
3384 static void genMult (iCode *ic)
3385 {
3386         operand *left = IC_LEFT(ic);
3387         operand *right = IC_RIGHT(ic);
3388         operand *result= IC_RESULT(ic); 
3389         
3390         FENTRY;
3391
3392         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3393         /* assign the amsops */
3394         aopOp (left,ic,FALSE);
3395         aopOp (right,ic,FALSE);
3396         aopOp (result,ic,TRUE);
3397         
3398         DEBUGpic14_AopType(__LINE__,left,right,result);
3399         
3400         /* special cases first */
3401         /* both are bits */
3402         if (AOP_TYPE(left) == AOP_CRY &&
3403                 AOP_TYPE(right)== AOP_CRY) {
3404                 genMultbits(left,right,result);
3405                 goto release ;
3406         }
3407         
3408         /* if both are of size == 1 */
3409         if (AOP_SIZE(left) == 1 &&
3410                 AOP_SIZE(right) == 1 ) {
3411                 genMultOneByte(left,right,result);
3412                 goto release ;
3413         }
3414         
3415         /* should have been converted to function call */
3416         assert(0) ;
3417         
3418 release :
3419         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3420         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3421         freeAsmop(result,NULL,ic,TRUE); 
3422 }
3423
3424 /*-----------------------------------------------------------------*/
3425 /* genDivbits :- division of bits                                                                  */
3426 /*-----------------------------------------------------------------*/
3427 static void genDivbits (operand *left, 
3428                                                 operand *right, 
3429                                                 operand *result)
3430 {
3431         
3432         char *l;
3433         
3434         FENTRY;
3435
3436         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3437         /* the result must be bit */      
3438         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3439         l = aopGet(AOP(left),0,FALSE,FALSE);
3440         
3441         MOVA(l);          
3442         
3443         pic14_emitcode("div","ab");
3444         pic14_emitcode("rrc","a");
3445         aopPut(AOP(result),"c",0);
3446 }
3447
3448 /*-----------------------------------------------------------------*/
3449 /* genDivOneByte : 8 bit division                                                                  */
3450 /*-----------------------------------------------------------------*/
3451 static void genDivOneByte (operand *left,
3452                                                    operand *right,
3453                                                    operand *result)
3454 {
3455         int size;
3456         
3457         FENTRY;
3458         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3459         
3460         assert (AOP_SIZE(result) == 1);
3461         assert (AOP_SIZE(right) == 1);
3462         assert (AOP_SIZE(left) == 1);
3463
3464         size = min(AOP_SIZE(result),AOP_SIZE(left));
3465
3466         if (AOP_TYPE(right) == AOP_LIT)
3467         {
3468                 /* XXX: might add specialized code */
3469         }
3470
3471         if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3472         {
3473                 /* unsigned division */
3474         #if 1
3475                 mov2w(AOP(right),0);
3476                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3477                 mov2w(AOP(left),0);
3478                 call_libraryfunc("__divuchar");
3479                 movwf(AOP(result),0);
3480         #else
3481                 pCodeOp *temp;
3482                 symbol *lbl;
3483
3484                 temp = popGetTempReg();
3485                 lbl = newiTempLabel(NULL);
3486                 
3487                 /* XXX: improve this naive approach:
3488                    [result] = [a] / [b]
3489                         ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3490
3491                    In PIC assembler:
3492                    movf  left,W
3493                    movwf temp           // temp <-- left
3494                    movf  right,W        // W <-- right
3495                    clrf  result
3496                    label1:
3497                    incf  result
3498                    subwf temp,F         // temp <-- temp - W
3499                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if temp < W
3500                    goto  label1
3501                    decf result          // we just subtract once too often
3502                  */
3503
3504                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3505                 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3506                 
3507                 mov2w(AOP(left),0);
3508                 emitpcode(POC_MOVWF, temp);
3509                 mov2w(AOP(right),0);
3510                 emitpcode(POC_CLRF, popGet(AOP(result),0));
3511
3512                 emitpLabel(lbl->key);
3513                 emitpcode(POC_INCF, popGet(AOP(result),0));
3514                 emitpcode(POC_SUBWF, temp);
3515                 emitSKPNC;
3516                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3517                 emitpcode(POC_DECF, popGet(AOP(result),0));
3518         #endif
3519         }
3520         else
3521         {
3522                 /* signed division */
3523                 mov2w(AOP(right),0);
3524                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3525                 mov2w(AOP(left),0);
3526                 call_libraryfunc("__divschar");
3527                 movwf(AOP(result),0);
3528         }
3529
3530         /* now performed the signed/unsigned division -- extend result */
3531         addSign(result, 1, !SPEC_USIGN(operandType(result)));
3532 }
3533
3534 /*-----------------------------------------------------------------*/
3535 /* genDiv - generates code for division                            */
3536 /*-----------------------------------------------------------------*/
3537 static void genDiv (iCode *ic)
3538 {
3539         operand *left = IC_LEFT(ic);
3540         operand *right = IC_RIGHT(ic);
3541         operand *result= IC_RESULT(ic); 
3542         
3543         FENTRY;
3544         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3545         /* assign the amsops */
3546         aopOp (left,ic,FALSE);
3547         aopOp (right,ic,FALSE);
3548         aopOp (result,ic,TRUE);
3549         
3550         /* special cases first */
3551         /* both are bits */
3552         if (AOP_TYPE(left) == AOP_CRY &&
3553                 AOP_TYPE(right)== AOP_CRY) {
3554                 genDivbits(left,right,result);
3555                 goto release ;
3556         }
3557         
3558         /* if both are of size == 1 */
3559         if (AOP_SIZE(left) == 1 &&
3560                 AOP_SIZE(right) == 1 ) {
3561                 genDivOneByte(left,right,result);
3562                 goto release ;
3563         }
3564         
3565         /* should have been converted to function call */
3566         assert(0);
3567 release :
3568         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3569         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3570         freeAsmop(result,NULL,ic,TRUE); 
3571 }
3572
3573 /*-----------------------------------------------------------------*/
3574 /* genModbits :- modulus of bits                                                                   */
3575 /*-----------------------------------------------------------------*/
3576 static void genModbits (operand *left, 
3577                                                 operand *right, 
3578                                                 operand *result)
3579 {
3580         
3581         char *l;
3582         
3583         FENTRY;
3584         /* the result must be bit */      
3585         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3586         l = aopGet(AOP(left),0,FALSE,FALSE);
3587         
3588         MOVA(l);
3589         
3590         pic14_emitcode("div","ab");
3591         pic14_emitcode("mov","a,b");
3592         pic14_emitcode("rrc","a");
3593         aopPut(AOP(result),"c",0);
3594 }
3595
3596 /*-----------------------------------------------------------------*/
3597 /* genModOneByte : 8 bit modulus                                                                   */
3598 /*-----------------------------------------------------------------*/
3599 static void genModOneByte (operand *left,
3600                                                    operand *right,
3601                                                    operand *result)
3602 {
3603         int size;
3604         
3605         FENTRY;
3606         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3607         
3608         assert (AOP_SIZE(result) == 1);
3609         assert (AOP_SIZE(right) == 1);
3610         assert (AOP_SIZE(left) == 1);
3611
3612         size = min(AOP_SIZE(result),AOP_SIZE(left));
3613
3614         if (AOP_TYPE(right) == AOP_LIT)
3615         {
3616                 /* XXX: might add specialized code */
3617         }
3618
3619         if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3620         {
3621                 /* unsigned division */
3622         #if 1
3623                 mov2w(AOP(right),0);
3624                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3625                 mov2w(AOP(left),0);
3626                 call_libraryfunc("__moduchar");
3627                 movwf(AOP(result),0);
3628         #else
3629                 pCodeOp *temp;
3630                 symbol *lbl;
3631
3632                 lbl = newiTempLabel(NULL);
3633                 
3634                 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3635
3636                 /* XXX: improve this naive approach:
3637                    [result] = [a] % [b]
3638                         ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3639
3640                    In PIC assembler:
3641                    movf  left,W
3642                    movwf result         // result <-- left
3643                    movf  right,W        // W <-- right
3644                    label1:
3645                    subwf result,F       // result <-- result - W
3646                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if result < W
3647                    goto  label1
3648                    addwf result, F      // we just subtract once too often
3649                  */
3650
3651                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3652                 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3653                 
3654                 if (!pic14_sameRegs(AOP(left), AOP(result)))
3655                 {
3656                         mov2w(AOP(left),0);
3657                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
3658                 }
3659                 mov2w(AOP(right),0);
3660
3661                 emitpLabel(lbl->key);
3662                 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3663                 emitSKPNC;
3664                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3665                 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3666         #endif
3667         }
3668         else
3669         {
3670                 /* signed division */
3671                 mov2w(AOP(right),0);
3672                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3673                 mov2w(AOP(left),0);
3674                 call_libraryfunc("__modschar");
3675                 movwf(AOP(result),0);
3676         }
3677
3678         /* now we performed the signed/unsigned modulus -- extend result */
3679         addSign(result, 1, !SPEC_USIGN(operandType(result)));
3680 }
3681
3682 /*-----------------------------------------------------------------*/
3683 /* genMod - generates code for division                                                    */
3684 /*-----------------------------------------------------------------*/
3685 static void genMod (iCode *ic)
3686 {
3687         operand *left = IC_LEFT(ic);
3688         operand *right = IC_RIGHT(ic);
3689         operand *result= IC_RESULT(ic);  
3690         
3691         FENTRY;
3692         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3693         /* assign the amsops */
3694         aopOp (left,ic,FALSE);
3695         aopOp (right,ic,FALSE);
3696         aopOp (result,ic,TRUE);
3697         
3698         /* special cases first */
3699         /* both are bits */
3700         if (AOP_TYPE(left) == AOP_CRY &&
3701                 AOP_TYPE(right)== AOP_CRY) {
3702                 genModbits(left,right,result);
3703                 goto release ;
3704         }
3705         
3706         /* if both are of size == 1 */
3707         if (AOP_SIZE(left) == 1 &&
3708                 AOP_SIZE(right) == 1 ) {
3709                 genModOneByte(left,right,result);
3710                 goto release ;
3711         }
3712         
3713         /* should have been converted to function call */
3714         assert(0);
3715         
3716 release :
3717         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3718         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3719         freeAsmop(result,NULL,ic,TRUE); 
3720 }
3721
3722 /*-----------------------------------------------------------------*/
3723 /* genIfxJump :- will create a jump depending on the ifx                   */
3724 /*-----------------------------------------------------------------*/
3725 /*
3726 note: May need to add parameter to indicate when a variable is in bit space.
3727 */
3728 static void genIfxJump (iCode *ic, char *jval)
3729 {
3730         
3731         FENTRY;
3732         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3733         /* if true label then we jump if condition
3734         supplied is true */
3735         if ( IC_TRUE(ic) ) {
3736                 
3737                 if(strcmp(jval,"a") == 0)
3738                         emitSKPZ;
3739                 else if (strcmp(jval,"c") == 0)
3740                         emitSKPC;
3741                 else {
3742                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3743                         emitpcode(POC_BTFSC,    newpCodeOpBit(jval,-1,1));
3744                 }
3745                 
3746                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3747                 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3748                 
3749         }
3750         else {
3751                 /* false label is present */
3752                 if(strcmp(jval,"a") == 0)
3753                         emitSKPNZ;
3754                 else if (strcmp(jval,"c") == 0)
3755                         emitSKPNC;
3756                 else {
3757                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3758                         emitpcode(POC_BTFSS,    newpCodeOpBit(jval,-1,1));
3759                 }
3760                 
3761                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3762                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3763                 
3764         }
3765         
3766         
3767         /* mark the icode as generated */
3768         ic->generated = 1;
3769 }
3770
3771 #if 0
3772 /*-----------------------------------------------------------------*/
3773 /* genSkip                                                                                                                 */
3774 /*-----------------------------------------------------------------*/
3775 static void genSkip(iCode *ifx,int status_bit)
3776 {
3777         FENTRY;
3778         if(!ifx)
3779                 return;
3780         
3781         if ( IC_TRUE(ifx) ) {
3782                 switch(status_bit) {
3783                 case 'z':
3784                         emitSKPNZ;
3785                         break;
3786                         
3787                 case 'c':
3788                         emitSKPNC;
3789                         break;
3790                         
3791                 case 'd':
3792                         emitSKPDC;
3793                         break;
3794                         
3795                 }
3796                 
3797                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3798                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3799                 
3800         } else {
3801                 
3802                 switch(status_bit) {
3803                         
3804                 case 'z':
3805                         emitSKPZ;
3806                         break;
3807                         
3808                 case 'c':
3809                         emitSKPC;
3810                         break;
3811                         
3812                 case 'd':
3813                         emitSKPDC;
3814                         break;
3815                 }
3816                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3817                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3818                 
3819         }
3820         
3821 }
3822 #endif
3823
3824 /*-----------------------------------------------------------------*/
3825 /* genSkipc                                                                                                        */
3826 /*-----------------------------------------------------------------*/
3827 static void genSkipc(resolvedIfx *rifx)
3828 {
3829         FENTRY;
3830         if(!rifx)
3831                 return;
3832         
3833         if(rifx->condition)
3834                 emitSKPNC;
3835         else
3836                 emitSKPC;
3837         
3838         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3839         emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3840         rifx->generated = 1;
3841 }
3842
3843 #if 0
3844 /*-----------------------------------------------------------------*/
3845 /* genSkipz2                                                                                                       */
3846 /*-----------------------------------------------------------------*/
3847 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3848 {
3849         FENTRY;
3850         if(!rifx)
3851                 return;
3852         
3853         if( (rifx->condition ^ invert_condition) & 1)
3854                 emitSKPZ;
3855         else
3856                 emitSKPNZ;
3857         
3858         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3859         rifx->generated = 1;
3860 }
3861 #endif
3862
3863 #if 0
3864 /*-----------------------------------------------------------------*/
3865 /* genSkipz                                                        */
3866 /*-----------------------------------------------------------------*/
3867 static void genSkipz(iCode *ifx, int condition)
3868 {
3869         FENTRY;
3870         assert (ifx != NULL);
3871         
3872         if(condition)
3873                 emitSKPNZ;
3874         else
3875                 emitSKPZ;
3876         
3877         if ( IC_TRUE(ifx) )
3878                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3879         else
3880                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3881         
3882         if ( IC_TRUE(ifx) )
3883                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3884         else
3885                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3886         
3887 }
3888 #endif
3889
3890 #if 0
3891 /*-----------------------------------------------------------------*/
3892 /* genSkipCond                                                     */
3893 /*-----------------------------------------------------------------*/
3894 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3895 {
3896         FENTRY;
3897         if(!rifx)
3898                 return;
3899         
3900         if(rifx->condition)
3901                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3902         else
3903                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3904         
3905         
3906         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3907         rifx->generated = 1;
3908 }
3909 #endif
3910
3911 #if 0
3912 /*-----------------------------------------------------------------*/
3913 /* genChkZeroes :- greater or less than comparison                 */
3914 /*     For each byte in a literal that is zero, inclusive or the   */
3915 /*     the corresponding byte in the operand with W                */
3916 /*     returns true if any of the bytes are zero                   */
3917 /*-----------------------------------------------------------------*/
3918 static int genChkZeroes(operand *op, int lit,  int size)
3919 {
3920         
3921         int i;
3922         int flag =1;
3923         
3924         while(size--) {
3925                 i = (lit >> (size*8)) & 0xff;
3926                 
3927                 if(i==0) {
3928                         if(flag) 
3929                                 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3930                         else
3931                                 emitpcode(POC_IORFW, popGet(AOP(op),size));
3932                         flag = 0;
3933                 }
3934         }
3935         
3936         return (flag==0);
3937 }
3938 #endif
3939
3940
3941 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3942 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
3943 #define DEBUGpc           emitpComment
3944
3945 /*-----------------------------------------------------------------*/
3946 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
3947 /*                  aop (if it's NOT a literal) or from lit (if    */
3948 /*                  aop is a literal)                              */
3949 /*-----------------------------------------------------------------*/
3950 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3951   if (aop->type == AOP_LIT) {
3952     emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3953   } else {
3954     emitpcode (POC_MOVFW, popGet (aop, offset));
3955   }
3956 }
3957
3958 /* genCmp performs a left < right comparison, stores
3959  * the outcome in result (if != NULL) and generates
3960  * control flow code for the ifx (if != NULL).
3961  *
3962  * This version leaves in sequences like
3963  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3964  * which should be optmized by the peephole
3965  * optimizer - RN 2005-01-01 */
3966 static void genCmp (operand *left,operand *right,
3967                     operand *result, iCode *ifx, int sign)
3968 {
3969   resolvedIfx rIfx;
3970   int size;
3971   int offs;
3972   symbol *templbl;
3973   operand *dummy;
3974   unsigned long lit;
3975   unsigned long mask;
3976   int performedLt;
3977   int invert_result = 0;
3978
3979   FENTRY;
3980   
3981   assert (AOP_SIZE(left) == AOP_SIZE(right));
3982   assert (left && right);
3983
3984   size = AOP_SIZE(right) - 1;
3985   mask = (0x100UL << (size*8)) - 1;
3986   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3987   performedLt = 1;
3988   templbl = NULL;
3989   lit = 0;
3990   
3991   resolveIfx (&rIfx, ifx);
3992
3993   /**********************************************************************
3994    * handle bits - bit compares are promoted to int compares seemingly! *
3995    **********************************************************************/
3996 #if 0
3997   // THIS IS COMPLETELY UNTESTED!
3998   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3999     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4000     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4001     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4002
4003     emitSETC;
4004     // 1 < {0,1} is false --> clear C by skipping the next instruction
4005     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4006     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4007     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4008     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4009     emitCLRC; // only skipped for left=0 && right=1
4010
4011     goto correct_result_in_carry;
4012   } // if
4013 #endif
4014
4015   /*************************************************
4016    * make sure that left is register (or the like) *
4017    *************************************************/
4018   if (!isAOP_REGlike(left)) {
4019     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4020     assert (isAOP_LIT(left));
4021     assert (isAOP_REGlike(right));
4022     // swap left and right
4023     // left < right <==> right > left <==> (right >= left + 1)
4024     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4025
4026     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4027       // MAXVALUE < right? always false
4028       if (performedLt) emitCLRC; else emitSETC;
4029       goto correct_result_in_carry;
4030     } // if
4031
4032     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4033     // that's why we handled it above.
4034     lit++;
4035
4036     dummy = left;
4037     left = right;
4038     right = dummy;
4039
4040     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4041   } else if (isAOP_LIT(right)) {
4042     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4043   } // if
4044
4045   assert (isAOP_REGlike(left)); // left must be register or the like
4046   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4047
4048   /*************************************************
4049    * special cases go here                         *
4050    *************************************************/
4051
4052   if (isAOP_LIT(right)) {
4053     if (!sign) {
4054       // unsigned comparison to a literal
4055       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4056       if (lit == 0) {
4057         // unsigned left < 0? always false
4058         if (performedLt) emitCLRC; else emitSETC;
4059         goto correct_result_in_carry;
4060       }
4061     } else {
4062       // signed comparison to a literal
4063       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4064       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4065         // signed left < 0x80000000? always false
4066         if (performedLt) emitCLRC; else emitSETC;
4067         goto correct_result_in_carry;
4068       } else if (lit == 0) {
4069         // compare left < 0; set CARRY if SIGNBIT(left) is set
4070         if (performedLt) emitSETC; else emitCLRC;
4071         emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
4072         if (performedLt) emitCLRC; else emitSETC;
4073         goto correct_result_in_carry;
4074       }
4075     } // if (!sign)
4076   } // right is literal
4077
4078   /*************************************************
4079    * perform a general case comparison             *
4080    * make sure we get CARRY==1 <==> left >= right  *
4081    *************************************************/
4082   // compare most significant bytes
4083   //DEBUGpc ("comparing bytes at offset %d", size);
4084   if (!sign) {
4085     // unsigned comparison
4086     pic14_mov2w_regOrLit (AOP(right), lit, size);
4087     emitpcode (POC_SUBFW, popGet (AOP(left), size));
4088   } else {
4089     // signed comparison
4090     // (add 2^n to both operands then perform an unsigned comparison)
4091     if (isAOP_LIT(right)) {
4092       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4093       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4094
4095       if (litbyte == 0x80) {
4096         // left >= 0x80 -- always true, but more bytes to come
4097         mov2w (AOP(left), size);
4098         emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
4099         emitSETC;
4100       } else {
4101         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4102         mov2w (AOP(left), size);
4103         emitpcode (POC_ADDLW, popGetLit (0x80));
4104         emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4105       } // if
4106     } else {
4107       pCodeOp *pctemp = popGetTempReg();
4108       mov2w (AOP(left), size);
4109       emitpcode (POC_ADDLW, popGetLit (0x80));
4110       emitpcode (POC_MOVWF, pctemp);
4111       mov2w (AOP(right), size);
4112       emitpcode (POC_ADDLW, popGetLit (0x80));
4113       emitpcode (POC_SUBFW, pctemp);
4114       popReleaseTempReg(pctemp);
4115     }
4116   } // if (!sign)
4117
4118   // compare remaining bytes (treat as unsigned case from above)
4119   templbl = newiTempLabel ( NULL );
4120   offs = size;
4121   while (offs--) {
4122     //DEBUGpc ("comparing bytes at offset %d", offs);
4123     emitSKPZ;
4124     emitpcode (POC_GOTO, popGetLabel (templbl->key));
4125     pic14_mov2w_regOrLit (AOP(right), lit, offs);
4126     emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4127   } // while (offs)
4128   emitpLabel (templbl->key);
4129   goto result_in_carry;
4130
4131 result_in_carry:
4132   
4133   /****************************************************
4134    * now CARRY contains the result of the comparison: *
4135    * SUBWF sets CARRY iff                             *
4136    * F-W >= 0 <==> F >= W <==> !(F < W)               *
4137    * (F=left, W=right)                                *
4138    ****************************************************/
4139
4140   if (performedLt) {
4141     invert_result = 1;
4142     // value will be used in the following genSkipc()
4143     rIfx.condition ^= 1;
4144   } // if
4145
4146 correct_result_in_carry:
4147
4148   // assign result to variable (if neccessary)
4149   if (result && AOP_TYPE(result) != AOP_CRY) {
4150     //DEBUGpc ("assign result");
4151     size = AOP_SIZE(result);
4152     while (size--) {
4153       emitpcode (POC_CLRF, popGet (AOP(result), size));
4154     } // while
4155     if (invert_result) {
4156       emitSKPC;
4157       emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4158     } else {
4159       emitpcode (POC_RLF, popGet (AOP(result), 0));
4160     }
4161   } // if (result)
4162
4163   // perform conditional jump
4164   if (ifx) {
4165     //DEBUGpc ("generate control flow");
4166     genSkipc (&rIfx);
4167     ifx->generated = 1;
4168   } // if
4169 }
4170
4171
4172 #if 0
4173 /* OLD VERSION -- BUGGY, DO NOT USE */
4174
4175 /*-----------------------------------------------------------------*/
4176 /* genCmp :- greater or less than comparison                       */
4177 /*-----------------------------------------------------------------*/
4178 static void genCmp (operand *left,operand *right,
4179                                         operand *result, iCode *ifx, int sign)
4180 {
4181         int size; //, offset = 0 ;
4182         unsigned long lit = 0L,i = 0;
4183         resolvedIfx rFalseIfx;
4184         //  resolvedIfx rTrueIfx;
4185         symbol *truelbl;
4186
4187         FENTRY;
4188         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4189         /*
4190         if(ifx) {
4191         DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4192         DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4193         }
4194         */
4195         
4196         resolveIfx(&rFalseIfx,ifx);
4197         truelbl  = newiTempLabel(NULL);
4198         size = max(AOP_SIZE(left),AOP_SIZE(right));
4199         
4200         DEBUGpic14_AopType(__LINE__,left,right,result);
4201         
4202 #define _swapp
4203         
4204         /* if literal is on the right then swap with left */
4205         if ((AOP_TYPE(right) == AOP_LIT)) {
4206                 operand *tmp = right ;
4207                 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4208                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4209 #ifdef _swapp
4210                 
4211                 lit = (lit - 1) & mask;
4212                 right = left;
4213                 left = tmp;
4214                 rFalseIfx.condition ^= 1;
4215 #endif
4216                 
4217         } else if ((AOP_TYPE(left) == AOP_LIT)) {
4218                 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4219         }
4220         
4221         
4222         //if(IC_TRUE(ifx) == NULL)
4223         /* if left & right are bit variables */
4224         if (AOP_TYPE(left) == AOP_CRY &&
4225                 AOP_TYPE(right) == AOP_CRY ) {
4226                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4227                 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4228         } else {
4229         /* subtract right from left if at the
4230         end the carry flag is set then we know that
4231                 left is greater than right */
4232                 
4233                 symbol *lbl  = newiTempLabel(NULL);
4234                 
4235 #ifndef _swapp
4236                 if(AOP_TYPE(right) == AOP_LIT) {
4237                         
4238                         //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4239                         
4240                         DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4241                         
4242                         /* special cases */
4243                         
4244                         if(lit == 0) {
4245                                 
4246                                 if(sign != 0) 
4247                                         genSkipCond(&rFalseIfx,left,size-1,7);
4248                                 else 
4249                                         /* no need to compare to 0...*/
4250                                         /* NOTE: this is a de-generate compare that most certainly 
4251                                         *       creates some dead code. */
4252                                         emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4253                                 
4254                                 if(ifx) ifx->generated = 1;
4255                                 return;
4256                                 
4257                         }
4258                         size--;
4259                         
4260                         if(size == 0) {
4261                                 //i = (lit >> (size*8)) & 0xff;
4262                                 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4263                                 
4264                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4265                                 
4266                                 i = ((0-lit) & 0xff);
4267                                 if(sign) {
4268                                         if( i == 0x81) { 
4269                                         /* lit is 0x7f, all signed chars are less than
4270                                                 * this except for 0x7f itself */
4271                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4272                                                 genSkipz2(&rFalseIfx,0);
4273                                         } else {
4274                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4275                                                 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4276                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4277                                         }
4278                                         
4279                                 } else {
4280                                         if(lit == 1) {
4281                                                 genSkipz2(&rFalseIfx,1);
4282                                         } else {
4283                                                 emitpcode(POC_ADDLW, popGetLit(i));
4284                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4285                                         }
4286                                 }
4287                                 
4288                                 if(ifx) ifx->generated = 1;
4289                                 return;
4290                         }
4291                         
4292                         /* chars are out of the way. now do ints and longs */
4293                         
4294                         
4295                         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4296                         
4297                         /* special cases */
4298                         
4299                         if(sign) {
4300                                 
4301                                 if(lit == 0) {
4302                                         genSkipCond(&rFalseIfx,left,size,7);
4303                                         if(ifx) ifx->generated = 1;
4304                                         return;
4305                                 }
4306                                 
4307                                 if(lit <0x100) {
4308                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4309                                         
4310                                         //rFalseIfx.condition ^= 1;
4311                                         //genSkipCond(&rFalseIfx,left,size,7);
4312                                         //rFalseIfx.condition ^= 1;
4313                                         
4314                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4315                                         if(rFalseIfx.condition)
4316                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4317                                         else
4318                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4319                                         
4320                                         emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4321                                         emitpcode(POC_ADDFW, popGet(AOP(left),0));
4322                                         emitpcode(POC_MOVFW, popGet(AOP(left),1));
4323                                         
4324                                         while(size > 1)
4325                                                 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4326                                         
4327                                         if(rFalseIfx.condition) {
4328                                                 emitSKPZ;
4329                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4330                                                 
4331                                         } else {
4332                                                 emitSKPNZ;
4333                                         }
4334                                         
4335                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4336                                         emitpLabel(truelbl->key);
4337                                         if(ifx) ifx->generated = 1;
4338                                         return;
4339                                         
4340                                 }
4341                                 
4342                                 if(size == 1) {
4343                                         
4344                                         if( (lit & 0xff) == 0) {
4345                                                 /* lower byte is zero */
4346                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4347                                                 i = ((lit >> 8) & 0xff) ^0x80;
4348                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4349                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4350                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4351                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4352                                                 
4353                                                 
4354                                                 if(ifx) ifx->generated = 1;
4355                                                 return;
4356                                                 
4357                                         }
4358                                 } else {
4359                                         /* Special cases for signed longs */
4360                                         if( (lit & 0xffffff) == 0) {
4361                                                 /* lower byte is zero */
4362                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4363                                                 i = ((lit >> 8*3) & 0xff) ^0x80;
4364                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4365                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4366                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4367                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4368                                                 
4369                                                 
4370                                                 if(ifx) ifx->generated = 1;
4371                                                 return;
4372                                                 
4373                                         }
4374                                         
4375                                 }
4376                                 
4377                                 
4378                                 if(lit & (0x80 << (size*8))) {
4379                                         /* lit is negative */
4380                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4381                                         
4382                                         //genSkipCond(&rFalseIfx,left,size,7);
4383                                         
4384                                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4385                                         
4386                                         if(rFalseIfx.condition)
4387                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4388                                         else
4389                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4390                                         
4391                                         
4392                                 } else {
4393                                         /* lit is positive */
4394                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4395                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4396                                         if(rFalseIfx.condition)
4397                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4398                                         else
4399                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4400                                         
4401                                 }
4402                                 
4403                                 /* There are no more special cases, so perform a general compare */
4404                                 
4405                                 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4406                                 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4407                                 
4408                                 while(size--) {
4409                                         
4410                                         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4411                                         emitSKPNZ;
4412                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4413                                 }
4414                                 //rFalseIfx.condition ^= 1;
4415                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4416                                 
4417                                 emitpLabel(truelbl->key);
4418                                 
4419                                 if(ifx) ifx->generated = 1;
4420                                 return;
4421                                 
4422                                 
4423                         }
4424
4425
4426                         /* sign is out of the way. So now do an unsigned compare */
4427                         DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4428
4429
4430                         /* General case - compare to an unsigned literal on the right.*/
4431
4432                         i = (lit >> (size*8)) & 0xff;
4433                         emitpcode(POC_MOVLW, popGetLit(i));
4434                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4435                         while(size--) {
4436                                 i = (lit >> (size*8)) & 0xff;
4437                                 
4438                                 if(i) {
4439                                         emitpcode(POC_MOVLW, popGetLit(i));
4440                                         emitSKPNZ;
4441                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4442                                 } else {
4443                                 /* this byte of the lit is zero, 
4444                                         *if it's not the last then OR in the variable */
4445                                         if(size)
4446                                                 emitpcode(POC_IORFW, popGet(AOP(left),size));
4447                                 }
4448                         }
4449
4450
4451                 emitpLabel(lbl->key);
4452                 //if(emitFinalCheck)
4453                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4454                 if(sign)
4455                         emitpLabel(truelbl->key);
4456
4457                 if(ifx) ifx->generated = 1;
4458                 return;
4459
4460
4461                 }
4462 #endif  // _swapp
4463
4464                 if(AOP_TYPE(left) == AOP_LIT) {
4465                         //symbol *lbl = newiTempLabel(NULL);
4466                         
4467                         //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4468                         
4469                         
4470                         DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4471                         
4472                         /* Special cases */
4473                         if((lit == 0) && (sign == 0)){
4474                                 
4475                                 size--;
4476                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4477                                 while(size) 
4478                                         emitpcode(POC_IORFW, popGet(AOP(right),--size));
4479                                 
4480                                 genSkipz2(&rFalseIfx,0);
4481                                 if(ifx) ifx->generated = 1;
4482                                 return;
4483                         }
4484                         
4485                         if(size==1) {
4486                                 /* Special cases */
4487                                 lit &= 0xff;
4488                                 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4489                                         /* degenerate compare can never be true */
4490                                         if(rFalseIfx.condition == 0)
4491                                                 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4492                                         
4493                                         if(ifx) ifx->generated = 1;
4494                                         return;
4495                                 }
4496                                 
4497                                 if(sign) {
4498                                         /* signed comparisons to a literal byte */
4499                                         
4500                                         int lp1 = (lit+1) & 0xff;
4501                                         
4502                                         DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4503                                         switch (lp1) {
4504                                         case 0:
4505                                                 rFalseIfx.condition ^= 1;
4506                                                 genSkipCond(&rFalseIfx,right,0,7);
4507                                                 break;
4508                                         case 0x7f:
4509                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4510                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4511                                                 genSkipz2(&rFalseIfx,1);
4512                                                 break;
4513                                         default:
4514                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4515                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4516                                                 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4517                                                 rFalseIfx.condition ^= 1;
4518                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4519                                                 break;
4520                                         }
4521                                         if(ifx) ifx->generated = 1;
4522                                 } else {
4523                                         /* unsigned comparisons to a literal byte */
4524                                         
4525                                         switch(lit & 0xff ) {
4526                                         case 0:
4527                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4528                                                 genSkipz2(&rFalseIfx,0);
4529                                                 if(ifx) ifx->generated = 1;
4530                                                 break;
4531                                         case 0x7f:
4532                                                 genSkipCond(&rFalseIfx,right,0,7);
4533                                                 if(ifx) ifx->generated = 1;
4534                                                 break;
4535                                                 
4536                                         default:
4537                                                 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4538                                                 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4539                                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4540                                                 rFalseIfx.condition ^= 1;
4541                                                 if (AOP_TYPE(result) == AOP_CRY) {
4542                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4543                                                         if(ifx) ifx->generated = 1;
4544                                                 } else {
4545                                                         DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4546                                                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4547                                                         emitpcode(POC_RLF, popGet(AOP(result),0));
4548                                                         emitpcode(POC_MOVLW, popGetLit(0x01));
4549                                                         emitpcode(POC_XORWF, popGet(AOP(result),0));
4550                                                 }       
4551                                                 break;
4552                                         }
4553                                 }
4554                                 
4555                                 //goto check_carry;
4556                                 return;
4557                                 
4558                         } else {
4559                                 
4560                                 /* Size is greater than 1 */
4561                                 
4562                                 if(sign) {
4563                                         int lp1 = lit+1;
4564                                         
4565                                         size--;
4566                                         
4567                                         if(lp1 == 0) {
4568                                                 /* this means lit = 0xffffffff, or -1 */
4569                                                 
4570                                                 
4571                                                 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4572                                                 rFalseIfx.condition ^= 1;
4573                                                 genSkipCond(&rFalseIfx,right,size,7);
4574                                                 if(ifx) ifx->generated = 1;
4575                                                 return;
4576                                         }
4577                                         
4578                                         if(lit == 0) {
4579                                                 int s = size;
4580                                                 
4581                                                 if(rFalseIfx.condition) {
4582                                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4583                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4584                                                 }
4585                                                 
4586                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4587                                                 while(size--)
4588                                                         emitpcode(POC_IORFW, popGet(AOP(right),size));
4589                                                 
4590                                                 
4591                                                 emitSKPZ;
4592                                                 if(rFalseIfx.condition) {
4593                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4594                                                         emitpLabel(truelbl->key);
4595                                                 }else {
4596                                                         rFalseIfx.condition ^= 1;
4597                                                         genSkipCond(&rFalseIfx,right,s,7);
4598                                                 }
4599                                                 
4600                                                 if(ifx) ifx->generated = 1;
4601                                                 return;
4602                                         }
4603                                         
4604                                         if((size == 1) &&  (0 == (lp1&0xff))) {
4605                                                 /* lower byte of signed word is zero */
4606                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4607                                                 i = ((lp1 >> 8) & 0xff) ^0x80;
4608                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4609                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4610                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4611                                                 rFalseIfx.condition ^= 1;
4612                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4613                                                 
4614                                                 
4615                                                 if(ifx) ifx->generated = 1;
4616                                                 return;
4617                                         }
4618                                         
4619                                         if(lit & (0x80 << (size*8))) {
4620                                                 /* Lit is less than zero */
4621                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4622                                                 //rFalseIfx.condition ^= 1;
4623                                                 //genSkipCond(&rFalseIfx,left,size,7);
4624                                                 //rFalseIfx.condition ^= 1;
4625                                                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4626                                                 //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4627                                                 
4628                                                 if(rFalseIfx.condition)
4629                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4630                                                 else
4631                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4632                                                 
4633                                                 
4634                                         } else {
4635                                                 /* Lit is greater than or equal to zero */
4636                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4637                                                 //rFalseIfx.condition ^= 1;
4638                                                 //genSkipCond(&rFalseIfx,right,size,7);
4639                                                 //rFalseIfx.condition ^= 1;
4640                                                 
4641                                                 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4642                                                 //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4643                                                 
4644                                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4645                                                 if(rFalseIfx.condition)
4646                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4647                                                 else
4648                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4649                                                 
4650                                         }
4651                                         
4652                                         
4653                                         emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4654                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4655                                         
4656                                         while(size--) {
4657                                                 
4658                                                 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4659                                                 emitSKPNZ;
4660                                                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4661                                         }
4662                                         rFalseIfx.condition ^= 1;
4663                                         //rFalseIfx.condition = 1;
4664                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4665                                         
4666                                         emitpLabel(truelbl->key);
4667                                         
4668                                         if(ifx) ifx->generated = 1;
4669                                         return;
4670                                         // end of if (sign)
4671                                 } else {
4672                                         
4673                                         /* compare word or long to an unsigned literal on the right.*/
4674                                         
4675                                         
4676                                         size--;
4677                                         if(lit < 0xff) {
4678                                                 DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4679                                                 switch (lit) {
4680                                                 case 0:
4681                                                         break; /* handled above */
4682                                                 /*
4683                                                 case 0xff:
4684                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4685                                                         while(size--)
4686                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4687                                                         genSkipz2(&rFalseIfx,0);
4688                                                         break;
4689                                                 */
4690                                                 default:
4691                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4692                                                         while(--size)
4693                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4694                                                         
4695                                                         emitSKPZ;
4696                                                         if(rFalseIfx.condition)
4697                                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4698                                                         else
4699                                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4700                                                         
4701                                                         
4702                                                         emitpcode(POC_MOVLW, popGetLit(lit+1));
4703                                                         emitpcode(POC_SUBFW, popGet(AOP(right),0));
4704                                                         
4705                                                         rFalseIfx.condition ^= 1;
4706                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4707                                                 }
4708                                                 
4709                                                 emitpLabel(truelbl->key);
4710                                                 
4711                                                 if(ifx) ifx->generated = 1;
4712                                                 return;
4713                                         }
4714                                         
4715                                         
4716                                         lit++;
4717                                         DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4718                                         i = (lit >> (size*8)) & 0xff;
4719                                         
4720                                         emitpcode(POC_MOVLW, popGetLit(i));
4721                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4722                                         
4723                                         while(size--) {
4724                                                 i = (lit >> (size*8)) & 0xff;
4725                                                 
4726                                                 if(i) {
4727                                                         emitpcode(POC_MOVLW, popGetLit(i));
4728                                                         emitSKPNZ;
4729                                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4730                                                 } else {
4731                                                 /* this byte of the lit is zero, 
4732                                                         *if it's not the last then OR in the variable */
4733                                                         if(size)
4734                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4735                                                 }
4736                                         }
4737                                         
4738                                         
4739                                         emitpLabel(lbl->key);
4740                                         
4741                                         rFalseIfx.condition ^= 1;
4742                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4743                                 }
4744                                 
4745                                 if(sign)
4746                                         emitpLabel(truelbl->key);
4747                                 if(ifx) ifx->generated = 1;
4748                                 return;
4749                         }
4750                 }
4751                 /* Compare two variables */
4752                 
4753                 DEBUGpic14_emitcode(";sign","%d",sign);
4754                 
4755                 size--;
4756                 if(sign) {
4757                         /* Sigh. thus sucks... */
4758                         if(size) {
4759                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4760                                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4761                                 emitpcode(POC_MOVLW, popGetLit(0x80));
4762                                 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4763                                 emitpcode(POC_XORFW, popGet(AOP(right),size));
4764                                 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4765                         } else {
4766                                 /* Signed char comparison */
4767                                 /* Special thanks to Nikolai Golovchenko for this snippet */
4768                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4769                                 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4770                                 emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4771                                 emitpcode(POC_XORFW, popGet(AOP(left),0));
4772                                 emitpcode(POC_XORFW, popGet(AOP(right),0));
4773                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4774                                 
4775                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4776                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4777                                 
4778                                 if(ifx) ifx->generated = 1;
4779                                 return;
4780                         }
4781                         
4782                 } else {
4783                         
4784                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4785                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4786                 }
4787                 
4788                 
4789                 /* The rest of the bytes of a multi-byte compare */
4790                 while (size) {
4791                         
4792                         emitSKPZ;
4793                         emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4794                         size--;
4795                         
4796                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4797                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4798                         
4799                         
4800                 }
4801                 
4802                 emitpLabel(lbl->key);
4803                 
4804                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4805                 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4806                         (AOP_TYPE(result) == AOP_REG)) {
4807                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4808                         emitpcode(POC_RLF, popGet(AOP(result),0));
4809                 } else {
4810                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4811                 }       
4812                 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4813                 if(ifx) ifx->generated = 1;
4814                 
4815                 return;
4816                 
4817         }
4818         
4819         // check_carry:
4820         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4821                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4822                 pic14_outBitC(result);
4823         } else {
4824                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4825                 /* if the result is used in the next
4826                 ifx conditional branch then generate
4827                 code a little differently */
4828                 if (ifx )
4829                         genIfxJump (ifx,"c");
4830                 else
4831                         pic14_outBitC(result);
4832                 /* leave the result in acc */
4833         }
4834         
4835 }
4836 #endif
4837
4838 /*-----------------------------------------------------------------*/
4839 /* genCmpGt :- greater than comparison                             */
4840 /*-----------------------------------------------------------------*/
4841 static void genCmpGt (iCode *ic, iCode *ifx)
4842 {
4843         operand *left, *right, *result;
4844         sym_link *letype , *retype;
4845         int sign ;
4846         
4847         FENTRY;
4848         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4849         left = IC_LEFT(ic);
4850         right= IC_RIGHT(ic);
4851         result = IC_RESULT(ic);
4852         
4853         letype = getSpec(operandType(left));
4854         retype =getSpec(operandType(right));
4855         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4856         /* assign the amsops */
4857         aopOp (left,ic,FALSE);
4858         aopOp (right,ic,FALSE);
4859         aopOp (result,ic,TRUE);
4860         
4861         genCmp(right, left, result, ifx, sign);
4862         
4863         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4864         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4865         freeAsmop(result,NULL,ic,TRUE); 
4866 }
4867
4868 /*-----------------------------------------------------------------*/
4869 /* genCmpLt - less than comparisons                                */
4870 /*-----------------------------------------------------------------*/
4871 static void genCmpLt (iCode *ic, iCode *ifx)
4872 {
4873         operand *left, *right, *result;
4874         sym_link *letype , *retype;
4875         int sign ;
4876         
4877         FENTRY;
4878         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4879         left = IC_LEFT(ic);
4880         right= IC_RIGHT(ic);
4881         result = IC_RESULT(ic);
4882         
4883         letype = getSpec(operandType(left));
4884         retype =getSpec(operandType(right));
4885         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4886         
4887         /* assign the amsops */
4888         aopOp (left,ic,FALSE);
4889         aopOp (right,ic,FALSE);
4890         aopOp (result,ic,TRUE);
4891         
4892         genCmp(left, right, result, ifx, sign);
4893         
4894         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4895         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4896         freeAsmop(result,NULL,ic,TRUE); 
4897 }
4898
4899 #if 0
4900 /*-----------------------------------------------------------------*/
4901 /* genc16bit2lit - compare a 16 bit value to a literal             */
4902 /*-----------------------------------------------------------------*/
4903 static void genc16bit2lit(operand *op, int lit, int offset)
4904 {
4905         int i;
4906         
4907         FENTRY;
4908         DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4909         if( (lit&0xff) == 0) 
4910                 i=1;
4911         else
4912                 i=0;
4913         
4914         switch( BYTEofLONG(lit,i)) { 
4915         case 0:
4916                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4917                 break;
4918         case 1:
4919                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4920                 break;
4921         case 0xff:
4922                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4923                 break;
4924         default:
4925                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4926                 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4927         }
4928         
4929         i ^= 1;
4930         
4931         switch( BYTEofLONG(lit,i)) { 
4932         case 0:
4933                 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4934                 break;
4935         case 1:
4936                 emitSKPNZ;
4937                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4938                 break;
4939         case 0xff:
4940                 emitSKPNZ;
4941                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4942                 break;
4943         default:
4944                 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4945                 emitSKPNZ;
4946                 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4947                 
4948         }
4949         
4950 }
4951 #endif
4952
4953 #if 0
4954 /*-----------------------------------------------------------------*/
4955 /* gencjneshort - compare and jump if not equal                    */
4956 /*-----------------------------------------------------------------*/
4957 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4958 {
4959         int size = min(AOP_SIZE(left),AOP_SIZE(right));
4960         int offset = 0;
4961         //resolvedIfx rIfx;
4962         symbol *lbl;
4963         
4964         //unsigned long lit = 0L;
4965         FENTRY;
4966         if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4967           emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4968           return;
4969         }
4970         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4971         DEBUGpic14_AopType(__LINE__,left,right,result);
4972         
4973         assert (!pic14_sameRegs (AOP(left), AOP(result)));
4974         assert (!pic14_sameRegs (AOP(right), AOP(result)));
4975         if (AOP_SIZE(result)) {
4976           for (offset = 0; offset < AOP_SIZE(result); offset++)
4977             emitpcode (POC_CLRF, popGet (AOP(result), offset));
4978         }
4979         
4980         assert (AOP_SIZE(left) == AOP_SIZE(right));
4981         //resolveIfx(&rIfx,ifx);
4982         lbl = newiTempLabel (NULL);
4983         while (size--)
4984         {
4985           mov2w (AOP(right),size);
4986           emitpcode (POC_XORFW, popGet (AOP(left), size));
4987           if (size)
4988           {
4989             emitSKPZ;
4990             emitpcode (POC_GOTO, popGetLabel (lbl->key));
4991           }
4992         } // while
4993         emitpLabel (lbl->key);
4994         if (AOP_SIZE(result)) {
4995           emitSKPNZ;
4996           emitpcode (POC_INCF, popGet (AOP(result), 0));
4997         } else {
4998           assert (ifx);
4999           genSkipz (ifx, NULL != IC_TRUE(ifx));
5000           ifx->generated = 1;
5001         }
5002         return;
5003 #if 0   
5004         if(result)
5005         {
5006                 DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
5007                 assert (!pic14_sameRegs (AOP(result), AOP(left)));
5008                 assert (!pic14_sameRegs (AOP(result), AOP(right)));
5009                 for (offset=0; offset < AOP_SIZE(result); offset++)
5010                 {
5011                         emitpcode (POC_CLRF, popGet (AOP(result), offset));
5012                 } // for offset
5013         }
5014         
5015         
5016         /* if the left side is a literal or 
5017         if the right is in a pointer register and left 
5018         is not */
5019         if ((AOP_TYPE(left) == AOP_LIT) || 
5020                 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5021                 operand *t = right;
5022                 right = left;
5023                 left = t;
5024         }
5025         if(AOP_TYPE(right) == AOP_LIT)
5026                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5027         
5028         /* if the right side is a literal then anything goes */
5029         if (AOP_TYPE(right) == AOP_LIT &&
5030                 AOP_TYPE(left) != AOP_DIR ) {
5031                 switch(size) {
5032                 case 2:
5033                         genc16bit2lit(left, lit, 0);
5034                         emitSKPNZ;
5035                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
5036                         break;
5037                 default:
5038                         offset = 0;
5039                         while (size--) {
5040                                 if(lit & 0xff) {
5041                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5042                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5043                                 } else {
5044                                         emitpcode(POC_MOVF,popGet(AOP(left),offset));
5045                                 }
5046                                 
5047                                 emitSKPNZ;
5048                                 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5049                                 offset++;
5050                                 lit >>= 8;
5051                         }
5052                         break;
5053                 }
5054         }
5055         
5056         /* if the right side is in a register or in direct space or
5057         if the left is a pointer register & right is not */    
5058         else if (AOP_TYPE(right) == AOP_REG ||
5059                 AOP_TYPE(right) == AOP_DIR || 
5060                 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5061                 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5062                 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5063                 int lbl_key = lbl->key;
5064                 
5065                 if(!result) {
5066                         DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5067                         fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5068                                 __FUNCTION__,__LINE__);
5069                         return;
5070                 }
5071                 
5072                 /*     switch(size) { */
5073                 /*     case 2: */
5074                 /*       genc16bit2lit(left, lit, 0); */
5075                 /*       emitSKPNZ; */
5076                 /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
5077                 /*       break; */
5078                 /*     default: */
5079                 offset = 0;
5080                 while (size--) {
5081                         int emit_skip=1;
5082                         if((AOP_TYPE(left) == AOP_DIR) && 
5083                                 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5084                                 
5085                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5086                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5087                                 
5088                         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5089                                 
5090                                 switch (lit & 0xff) {
5091                                 case 0:
5092                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5093                                         break;
5094                                 case 1:
5095                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5096                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5097                                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
5098                                         emit_skip=0;
5099                                         break;
5100                                 case 0xff:
5101                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5102                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5103                                         //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5104                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5105                                         emit_skip=0;
5106                                         break;
5107                                 default:
5108                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5109                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5110                                 }
5111                                 lit >>= 8;
5112                                 
5113                         } else {
5114                                 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5115                         }
5116                         if(emit_skip) {
5117                                 if(AOP_TYPE(result) == AOP_CRY) {
5118                                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5119                                         if(rIfx.condition)
5120                                                 emitSKPNZ;
5121                                         else
5122                                                 emitSKPZ;
5123                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5124                                 } else {
5125                                         /* fix me. probably need to check result size too */
5126                                         //emitpcode(POC_CLRF,popGet(AOP(result),0));
5127                                         if(rIfx.condition)
5128                                                 emitSKPZ;
5129                                         else
5130                                                 emitSKPNZ;
5131                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5132                                 }
5133                                 if(ifx)
5134                                         ifx->generated=1;
5135                         }
5136                         emit_skip++;
5137                         offset++;
5138                 }
5139                 /*       break; */
5140                 /*     } */
5141         } else if(AOP_TYPE(right) == AOP_REG &&
5142                 AOP_TYPE(left) != AOP_DIR){
5143
5144                 offset = 0;
5145                 while(size--) {
5146                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5147                         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5148                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5149                         if(rIfx.condition)
5150                                 emitSKPNZ;
5151                         else
5152                                 emitSKPZ;
5153                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5154                         offset++;
5155                 }
5156                 
5157         }else{
5158                 /* right is a pointer reg need both a & b */
5159                 offset = 0;
5160                 while(size--) {
5161                         char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5162                         if(strcmp(l,"b"))
5163                                 pic14_emitcode("mov","b,%s",l);
5164                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5165                         pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5166                         offset++;
5167                 }
5168         }
5169         
5170         emitpcode(POC_INCF,popGet(AOP(result),0));
5171         if(!rIfx.condition)
5172                 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5173         
5174         emitpLabel(lbl->key);
5175         
5176         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5177         
5178         if(ifx)
5179                 ifx->generated = 1;
5180 #endif
5181 }
5182 #endif
5183
5184 #if 0
5185 /*-----------------------------------------------------------------*/
5186 /* gencjne - compare and jump if not equal                         */
5187 /*-----------------------------------------------------------------*/
5188 static void gencjne(operand *left, operand *right, iCode *ifx)
5189 {
5190         symbol *tlbl  = newiTempLabel(NULL);
5191         
5192         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5193         gencjneshort(left, right, lbl);
5194         
5195         pic14_emitcode("mov","a,%s",one);
5196         pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5197         pic14_emitcode("","%05d_DS_:",lbl->key+100);
5198         pic14_emitcode("clr","a");
5199         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5200         
5201         emitpLabel(lbl->key);
5202         emitpLabel(tlbl->key);
5203         
5204 }
5205 #endif
5206
5207 /*-----------------------------------------------------------------*/
5208 /* genCmpEq - generates code for equal to                          */
5209 /*-----------------------------------------------------------------*/
5210 static void genCmpEq (iCode *ic, iCode *ifx)
5211 {
5212   operand *left, *right, *result;
5213   int size;
5214   symbol *false_label;
5215
5216   FENTRY;
5217   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5218
5219   if(ifx)
5220     DEBUGpic14_emitcode ("; ifx is non-null","");
5221   else
5222     DEBUGpic14_emitcode ("; ifx is null","");
5223
5224   aopOp((left=IC_LEFT(ic)),ic,FALSE);
5225   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5226   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5227
5228   DEBUGpic14_AopType(__LINE__,left,right,result);
5229
5230   /* if literal, move literal to right */ 
5231   if (op_isLitLike (IC_LEFT(ic))) {
5232     operand *tmp = right ;
5233     right = left;
5234     left = tmp;
5235   }
5236
5237   false_label = NULL;
5238   if (ifx && !IC_TRUE(ifx))
5239   {
5240     assert (IC_FALSE(ifx));
5241     false_label = IC_FALSE(ifx);
5242   }
5243
5244   size = min(AOP_SIZE(left),AOP_SIZE(right));
5245   assert(!pic14_sameRegs(AOP(result),AOP(left)));
5246   assert(!pic14_sameRegs(AOP(result),AOP(right)));
5247
5248   /* assume left != right */
5249   {
5250     int i;
5251     for (i=0; i < AOP_SIZE(result); i++)
5252     {
5253       emitpcode(POC_CLRF, popGet(AOP(result),i));
5254     }
5255   }
5256
5257   if (AOP_TYPE(right) == AOP_LIT)
5258   {
5259     unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5260     int i;
5261     size = AOP_SIZE(left);
5262     assert(!op_isLitLike(left));
5263
5264     switch (lit)
5265     {
5266       case 0:
5267         mov2w(AOP(left), 0);
5268         for (i=1; i < size; i++)
5269           emitpcode(POC_IORFW,popGet(AOP(left),i));
5270         /* now Z is set iff `left == right' */
5271         emitSKPZ;
5272         if (!false_label) false_label = newiTempLabel(NULL);
5273         emitpcode(POC_GOTO, popGetLabel(false_label->key));
5274         break;
5275
5276       default:
5277         for (i=0; i < size; i++)
5278         {
5279           mov2w(AOP(left),i);
5280           emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5281           /* now Z is cleared if `left != right' */
5282           emitSKPZ;
5283           if (!false_label) false_label = newiTempLabel(NULL);
5284           emitpcode(POC_GOTO, popGetLabel(false_label->key));
5285         } // for i
5286         break;
5287     } // switch (lit)
5288   }
5289   else
5290   {
5291     /* right is no literal */
5292     int i;
5293
5294     for (i=0; i < size; i++)
5295     {
5296       mov2w(AOP(right),i);
5297       emitpcode(POC_XORFW,popGet(AOP(left),i));
5298       /* now Z is cleared if `left != right' */
5299       emitSKPZ;
5300       if (!false_label) false_label = newiTempLabel(NULL);
5301       emitpcode(POC_GOTO, popGetLabel(false_label->key));
5302     } // for i
5303   }
5304
5305   /* if we reach here, left == right */
5306
5307   if (AOP_SIZE(result) > 0)
5308   {
5309     emitpcode(POC_INCF, popGet(AOP(result),0));
5310   }
5311
5312   if (ifx && IC_TRUE(ifx))
5313   {
5314     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5315   }
5316
5317   if (false_label && (!ifx || IC_TRUE(ifx)))
5318     emitpLabel(false_label->key);
5319
5320   if (ifx) ifx->generated = 1;
5321
5322   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5323   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5324   freeAsmop(result,NULL,ic,TRUE);
5325 }
5326
5327 /*-----------------------------------------------------------------*/
5328 /* ifxForOp - returns the icode containing the ifx for operand     */
5329 /*-----------------------------------------------------------------*/
5330 static iCode *ifxForOp ( operand *op, iCode *ic )
5331 {
5332         FENTRY;
5333         /* if true symbol then needs to be assigned */
5334         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5335         if (IS_TRUE_SYMOP(op))
5336                 return NULL ;
5337         
5338         /* if this has register type condition and
5339         the next instruction is ifx with the same operand
5340         and live to of the operand is upto the ifx only then */
5341         if (ic->next &&
5342                 ic->next->op == IFX &&
5343                 IC_COND(ic->next)->key == op->key &&
5344                 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5345                 return ic->next;
5346         
5347         if (ic->next &&
5348                 ic->next->op == IFX &&
5349                 IC_COND(ic->next)->key == op->key) {
5350                 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5351                 return ic->next;
5352         }
5353         
5354         DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5355         if (ic->next &&
5356                 ic->next->op == IFX)
5357                 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5358         
5359         if (ic->next &&
5360                 ic->next->op == IFX &&
5361                 IC_COND(ic->next)->key == op->key) {
5362                 DEBUGpic14_emitcode ("; "," key is okay");
5363                 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5364                         OP_SYMBOL(op)->liveTo,
5365                         ic->next->seq);
5366         }
5367         
5368         
5369         return NULL;
5370 }
5371 /*-----------------------------------------------------------------*/
5372 /* genAndOp - for && operation                                     */
5373 /*-----------------------------------------------------------------*/
5374 static void genAndOp (iCode *ic)
5375 {
5376         operand *left,*right, *result;
5377         /*     symbol *tlbl; */
5378         
5379         FENTRY;
5380         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5381         /* note here that && operations that are in an
5382         if statement are taken away by backPatchLabels
5383         only those used in arthmetic operations remain */
5384         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5385         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5386         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5387         
5388         DEBUGpic14_AopType(__LINE__,left,right,result);
5389         
5390         emitpcode(POC_MOVFW,popGet(AOP(left),0));
5391         emitpcode(POC_ANDFW,popGet(AOP(right),0));
5392         emitpcode(POC_MOVWF,popGet(AOP(result),0));
5393         
5394         /* if both are bit variables */
5395         /*     if (AOP_TYPE(left) == AOP_CRY && */
5396         /*         AOP_TYPE(right) == AOP_CRY ) { */
5397         /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5398         /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5399         /*         pic14_outBitC(result); */
5400         /*     } else { */
5401         /*         tlbl = newiTempLabel(NULL); */
5402         /*         pic14_toBoolean(left);     */
5403         /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5404         /*         pic14_toBoolean(right); */
5405         /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5406         /*         pic14_outBitAcc(result); */
5407         /*     } */
5408         
5409         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5410         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5411         freeAsmop(result,NULL,ic,TRUE);
5412 }
5413
5414
5415 /*-----------------------------------------------------------------*/
5416 /* genOrOp - for || operation                                      */
5417 /*-----------------------------------------------------------------*/
5418 /*
5419 tsd pic port -
5420 modified this code, but it doesn't appear to ever get called
5421 */
5422
5423 static void genOrOp (iCode *ic)
5424 {
5425         operand *left,*right, *result;
5426         symbol *tlbl;
5427         int i;
5428         
5429         /* note here that || operations that are in an
5430         if statement are taken away by backPatchLabels
5431         only those used in arthmetic operations remain */
5432         FENTRY;
5433         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5434         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5435         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5436         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5437         
5438         DEBUGpic14_AopType(__LINE__,left,right,result);
5439
5440         for (i=0; i < AOP_SIZE(result); i++)
5441         {
5442                 emitpcode(POC_CLRF, popGet(AOP(result), i));
5443         } // for i
5444
5445         tlbl = newiTempLabel(NULL);
5446         pic14_toBoolean(left);
5447         emitSKPZ;
5448         emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5449         pic14_toBoolean(right);
5450         emitpLabel(tlbl->key);
5451         /* here Z is clear IFF `left || right' */
5452         emitSKPZ;
5453         emitpcode(POC_INCF, popGet(AOP(result), 0));
5454         
5455         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5456         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5457         freeAsmop(result,NULL,ic,TRUE);            
5458 }
5459
5460 /*-----------------------------------------------------------------*/
5461 /* isLiteralBit - test if lit == 2^n                               */
5462 /*-----------------------------------------------------------------*/
5463 static int isLiteralBit(unsigned long lit)
5464 {
5465         unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5466                 0x100L,0x200L,0x400L,0x800L,
5467                 0x1000L,0x2000L,0x4000L,0x8000L,
5468                 0x10000L,0x20000L,0x40000L,0x80000L,
5469                 0x100000L,0x200000L,0x400000L,0x800000L,
5470                 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5471                 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5472         int idx;
5473         
5474         FENTRY;
5475         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5476         for(idx = 0; idx < 32; idx++)
5477                 if(lit == pw[idx])
5478                         return idx+1;
5479                 return 0;
5480 }
5481
5482 /*-----------------------------------------------------------------*/
5483 /* continueIfTrue -                                                */
5484 /*-----------------------------------------------------------------*/
5485 static void continueIfTrue (iCode *ic)
5486 {
5487         FENTRY;
5488         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5489         if(IC_TRUE(ic))
5490         {
5491                 // Why +100?!?
5492                 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5493                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5494         }
5495         ic->generated = 1;
5496 }
5497
5498 /*-----------------------------------------------------------------*/
5499 /* jmpIfTrue -                                                     */
5500 /*-----------------------------------------------------------------*/
5501 static void jumpIfTrue (iCode *ic)
5502 {
5503         FENTRY;
5504         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5505         if(!IC_TRUE(ic))
5506         {
5507                 // Why +100?!?
5508                 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5509                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5510         }
5511         ic->generated = 1;
5512 }
5513
5514 /*-----------------------------------------------------------------*/
5515 /* jmpTrueOrFalse -                                                */
5516 /*-----------------------------------------------------------------*/
5517 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5518 {
5519         FENTRY;
5520         // ugly but optimized by peephole
5521         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5522         if(IC_TRUE(ic)){
5523                 symbol *nlbl = newiTempLabel(NULL);
5524                 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5525                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5526                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5527                 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5528         }
5529         else{
5530                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5531                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5532         }
5533         ic->generated = 1;
5534 }
5535
5536 /*-----------------------------------------------------------------*/
5537 /* genAnd  - code for and                                          */
5538 /*-----------------------------------------------------------------*/
5539 static void genAnd (iCode *ic, iCode *ifx)
5540 {
5541         operand *left, *right, *result;
5542         int size, offset=0;  
5543         unsigned long lit = 0L;
5544         int bytelit = 0;
5545         resolvedIfx rIfx;
5546         
5547         FENTRY;
5548         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5549         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5550         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5551         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5552         
5553         resolveIfx(&rIfx,ifx);
5554         
5555         /* if left is a literal & right is not then exchange them */
5556         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5557                 AOP_NEEDSACC(left)) {
5558                 operand *tmp = right ;
5559                 right = left;
5560                 left = tmp;
5561         }
5562         
5563         /* if result = right then exchange them */
5564         if(pic14_sameRegs(AOP(result),AOP(right))){
5565                 operand *tmp = right ;
5566                 right = left;
5567                 left = tmp;
5568         }
5569         
5570         /* if right is bit then exchange them */
5571         if (AOP_TYPE(right) == AOP_CRY &&
5572                 AOP_TYPE(left) != AOP_CRY){
5573                 operand *tmp = right ;
5574                 right = left;
5575                 left = tmp;
5576         }
5577         if(AOP_TYPE(right) == AOP_LIT)
5578                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5579         
5580         size = AOP_SIZE(result);
5581         
5582         DEBUGpic14_AopType(__LINE__,left,right,result);
5583         
5584         // if(bit & yy)
5585         // result = bit & yy;
5586         if (AOP_TYPE(left) == AOP_CRY){
5587                 // c = bit & literal;
5588                 if(AOP_TYPE(right) == AOP_LIT){
5589                         if(lit & 1) {
5590                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5591                                         // no change
5592                                         goto release;
5593                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5594                         } else {
5595                                 // bit(result) = 0;
5596                                 if(size && (AOP_TYPE(result) == AOP_CRY)){
5597                                         pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5598                                         goto release;
5599                                 }
5600                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5601                                         jumpIfTrue(ifx);
5602                                         goto release;
5603                                 }
5604                                 pic14_emitcode("clr","c");
5605                         }
5606                 } else {
5607                         if (AOP_TYPE(right) == AOP_CRY){
5608                                 // c = bit & bit;
5609                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5610                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5611                         } else {
5612                                 // c = bit & val;
5613                                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5614                                 // c = lsb
5615                                 pic14_emitcode("rrc","a");
5616                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5617                         }
5618                 }
5619                 // bit = c
5620                 // val = c
5621                 if(size)
5622                         pic14_outBitC(result);
5623                 // if(bit & ...)
5624                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5625                         genIfxJump(ifx, "c");           
5626                 goto release ;
5627         }
5628         
5629         // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5630         // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5631         if((AOP_TYPE(right) == AOP_LIT) &&
5632                 (AOP_TYPE(result) == AOP_CRY) &&
5633                 (AOP_TYPE(left) != AOP_CRY)){
5634                 int posbit = isLiteralBit(lit);
5635                 /* left &  2^n */
5636                 if(posbit){
5637                         posbit--;
5638                         //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5639                         // bit = left & 2^n
5640                         if(size)
5641                                 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5642                         // if(left &  2^n)
5643                         else{
5644                                 if(ifx){
5645                                         int offset = 0;
5646                                         while (posbit > 7) {
5647                                                 posbit -= 8;
5648                                                 offset++;
5649                                         }
5650                                         emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5651                                                 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit-1,0));
5652                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5653                                         
5654                                         ifx->generated = 1;
5655                                 }
5656                                 goto release;
5657                         }
5658                 } else {
5659                         symbol *tlbl = newiTempLabel(NULL);
5660                         int sizel = AOP_SIZE(left);
5661                         if(size)
5662                                 pic14_emitcode("setb","c");
5663                         while(sizel--){
5664                                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5665                                         mov2w( AOP(left), offset);
5666                                         // byte ==  2^n ?
5667                                         if((posbit = isLiteralBit(bytelit)) != 0) {
5668                                                 emitpcode(rIfx.condition ? POC_BTFSC : POC_BTFSS, // XXX: or the other way round?
5669                                                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit - 1, 0));
5670                                                 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5671                                         }
5672                                         else{
5673                                                 emitpcode(POC_ANDLW, newpCodeOpLit(bytelit & 0x0ff));
5674                                                 if (rIfx.condition) emitSKPZ;
5675                                                 else emitSKPNZ;
5676                                                 
5677                                                 if(bytelit != 0x0FFL)
5678                                                 {
5679                                                         pic14_emitcode("anl","a,%s",
5680                                                         aopGet(AOP(right),offset,FALSE,TRUE));
5681                                                 }
5682                                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5683                                         }
5684
5685                                         emitpcode(POC_GOTO, popGetLabel(rIfx.lbl->key));
5686                                         ifx->generated = 1;
5687                                                 
5688                                 }
5689                                 offset++;
5690                         }
5691                         // bit = left & literal
5692                         if(size){
5693                                 pic14_emitcode("clr","c");
5694                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5695                         }
5696                         // if(left & literal)
5697                         else{
5698                                 if(ifx)
5699                                         jmpTrueOrFalse(ifx, tlbl);
5700                                 goto release ;
5701                         }
5702                 }
5703                 pic14_outBitC(result);
5704                 goto release ;
5705         }
5706         
5707         /* if left is same as result */
5708         if(pic14_sameRegs(AOP(result),AOP(left))){
5709                 int know_W = -1;
5710                 for(;size--; offset++,lit>>=8) {
5711                         if(AOP_TYPE(right) == AOP_LIT){
5712                                 switch(lit & 0xff) {
5713                                 case 0x00:
5714                                         /*  and'ing with 0 has clears the result */
5715                                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
5716                                         break;
5717                                 case 0xff:
5718                                         /* and'ing with 0xff is a nop when the result and left are the same */
5719                                         break;
5720                                         
5721                                 default:
5722                                         {
5723                                                 int p = my_powof2( (~lit) & 0xff );
5724                                                 if(p>=0) {
5725                                                         /* only one bit is set in the literal, so use a bcf instruction */
5726                                                         emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5727                                                         
5728                                                 } else {
5729                                                         if(know_W != (int)(lit&0xff))
5730                                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5731                                                         know_W = lit &0xff;
5732                                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5733                                                 }
5734                                         }    
5735                                 }
5736                         } else {
5737                                 if (AOP_TYPE(left) == AOP_ACC) {
5738                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5739                                 } else {        
5740                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5741                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5742                                         
5743                                 }
5744                         }
5745                 }
5746                 
5747         } else {
5748                 // left & result in different registers
5749                 if(AOP_TYPE(result) == AOP_CRY){
5750                         // result = bit
5751                         // if(size), result in bit
5752                         // if(!size && ifx), conditional oper: if(left & right)
5753                         symbol *tlbl = newiTempLabel(NULL);
5754                         int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5755                         if(size)
5756                                 pic14_emitcode("setb","c");
5757                         while(sizer--){
5758                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5759                                 pic14_emitcode("anl","a,%s",
5760                                         aopGet(AOP(left),offset,FALSE,FALSE));
5761                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5762                                 offset++;
5763                         }
5764                         if(size){
5765                                 CLRC;
5766                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5767                                 pic14_outBitC(result);
5768                         } else if(ifx)
5769                                 jmpTrueOrFalse(ifx, tlbl);
5770                 } else {
5771                         for(;(size--);offset++) {
5772                                 // normal case
5773                                 // result = left & right
5774                                 if(AOP_TYPE(right) == AOP_LIT){
5775                                         int t = (lit >> (offset*8)) & 0x0FFL;
5776                                         switch(t) { 
5777                                         case 0x00:
5778                                                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5779                                                 break;
5780                                         case 0xff:
5781                                                 if(AOP_TYPE(left) != AOP_ACC) {
5782                                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5783                                                 }
5784                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5785                                                 break;
5786                                         default:
5787                                                 if(AOP_TYPE(left) == AOP_ACC) {
5788                                                         emitpcode(POC_ANDLW, popGetLit(t));
5789                                                 } else {
5790                                                         emitpcode(POC_MOVLW, popGetLit(t));
5791                                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5792                                                 }
5793                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5794                                         }
5795                                         continue;
5796                                 }
5797                                 
5798                                 if (AOP_TYPE(left) == AOP_ACC) {
5799                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5800                                 } else {
5801                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5802                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5803                                 }
5804                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5805                         }
5806                 }
5807         }
5808         
5809 release :
5810         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5811         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5812         freeAsmop(result,NULL,ic,TRUE);     
5813 }
5814
5815 /*-----------------------------------------------------------------*/
5816 /* genOr  - code for or                                            */
5817 /*-----------------------------------------------------------------*/
5818 static void genOr (iCode *ic, iCode *ifx)
5819 {
5820         operand *left, *right, *result;
5821         int size, offset=0;
5822         unsigned long lit = 0L;
5823         
5824         FENTRY;
5825         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5826         
5827         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5828         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5829         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5830         
5831         DEBUGpic14_AopType(__LINE__,left,right,result);
5832         
5833         /* if left is a literal & right is not then exchange them */
5834         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5835                 AOP_NEEDSACC(left)) {
5836                 operand *tmp = right ;
5837                 right = left;
5838                 left = tmp;
5839         }
5840         
5841         /* if result = right then exchange them */
5842         if(pic14_sameRegs(AOP(result),AOP(right))){
5843                 operand *tmp = right ;
5844                 right = left;
5845                 left = tmp;
5846         }
5847         
5848         /* if right is bit then exchange them */
5849         if (AOP_TYPE(right) == AOP_CRY &&
5850                 AOP_TYPE(left) != AOP_CRY){
5851                 operand *tmp = right ;
5852                 right = left;
5853                 left = tmp;
5854         }
5855         
5856         DEBUGpic14_AopType(__LINE__,left,right,result);
5857         
5858         if(AOP_TYPE(right) == AOP_LIT)
5859                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5860         
5861         size = AOP_SIZE(result);
5862         
5863         // if(bit | yy)
5864         // xx = bit | yy;
5865         if (AOP_TYPE(left) == AOP_CRY){
5866                 if(AOP_TYPE(right) == AOP_LIT){
5867                         // c = bit & literal;
5868                         if(lit){
5869                                 // lit != 0 => result = 1
5870                                 if(AOP_TYPE(result) == AOP_CRY){
5871                                         if(size)
5872                                                 emitpcode(POC_BSF, popGet(AOP(result),0));
5873                                         //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5874                                         //   AOP(result)->aopu.aop_dir,
5875                                         //   AOP(result)->aopu.aop_dir);
5876                                         else if(ifx)
5877                                                 continueIfTrue(ifx);
5878                                         goto release;
5879                                 }
5880                         } else {
5881                                 // lit == 0 => result = left
5882                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5883                                         goto release;
5884                                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5885                         }
5886                 } else {
5887                         if (AOP_TYPE(right) == AOP_CRY){
5888                                 if(pic14_sameRegs(AOP(result),AOP(left))){
5889                                         // c = bit | bit;
5890                                         emitpcode(POC_BCF,   popGet(AOP(result),0));
5891                                         emitpcode(POC_BTFSC, popGet(AOP(right),0));
5892                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5893                                         
5894                                         pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5895                                                 AOP(result)->aopu.aop_dir,
5896                                                 AOP(result)->aopu.aop_dir);
5897                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5898                                                 AOP(right)->aopu.aop_dir,
5899                                                 AOP(right)->aopu.aop_dir);
5900                                         pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5901                                                 AOP(result)->aopu.aop_dir,
5902                                                 AOP(result)->aopu.aop_dir);
5903                                 } else {
5904                                         if( AOP_TYPE(result) == AOP_ACC) {
5905                                                 emitpcode(POC_MOVLW, popGetLit(0));
5906                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5907                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5908                                                 emitpcode(POC_MOVLW, popGetLit(1));
5909                                                 
5910                                         } else {
5911                                                 
5912                                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5913                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5914                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5915                                                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5916                                                 
5917                                                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5918                                                         AOP(result)->aopu.aop_dir,
5919                                                         AOP(result)->aopu.aop_dir);
5920                                                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5921                                                         AOP(right)->aopu.aop_dir,
5922                                                         AOP(right)->aopu.aop_dir);
5923                                                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5924                                                         AOP(left)->aopu.aop_dir,
5925                                                         AOP(left)->aopu.aop_dir);
5926                                                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5927                                                         AOP(result)->aopu.aop_dir,
5928                                                         AOP(result)->aopu.aop_dir);
5929                                         }
5930                                 }
5931                         } else {
5932                                 // c = bit | val;
5933                                 symbol *tlbl = newiTempLabel(NULL);
5934                                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5935                                 
5936                                 
5937                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5938                                 if( AOP_TYPE(right) == AOP_ACC) {
5939                                         emitpcode(POC_IORLW, popGetLit(0));
5940                                         emitSKPNZ;
5941                                         emitpcode(POC_BTFSC, popGet(AOP(left),0));
5942                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5943                                 }
5944                                 
5945                                 
5946                                 
5947                                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5948                                         pic14_emitcode(";XXX setb","c");
5949                                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5950                                         AOP(left)->aopu.aop_dir,tlbl->key+100);
5951                                 pic14_toBoolean(right);
5952                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5953                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5954                                         jmpTrueOrFalse(ifx, tlbl);
5955                                         goto release;
5956                                 } else {
5957                                         CLRC;
5958                                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5959                                 }
5960                         }
5961                 }
5962                 // bit = c
5963                 // val = c
5964                 if(size)
5965                         pic14_outBitC(result);
5966                 // if(bit | ...)
5967                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5968                         genIfxJump(ifx, "c");           
5969                 goto release ;
5970         }
5971
5972         // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5973         // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5974         if((AOP_TYPE(right) == AOP_LIT) &&
5975           (AOP_TYPE(result) == AOP_CRY) &&
5976           (AOP_TYPE(left) != AOP_CRY)){
5977                 if(lit){
5978                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5979                         // result = 1
5980                         if(size)
5981                                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5982                         else 
5983                                 continueIfTrue(ifx);
5984                         goto release;
5985                 } else {
5986                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5987                         // lit = 0, result = boolean(left)
5988                         if(size)
5989                                 pic14_emitcode(";XXX setb","c");
5990                         pic14_toBoolean(right);
5991                         if(size){
5992                                 symbol *tlbl = newiTempLabel(NULL);
5993                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5994                                 CLRC;
5995                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5996                         } else {
5997                                 genIfxJump (ifx,"a");
5998                                 goto release;
5999                         }
6000                 }
6001                 pic14_outBitC(result);
6002                 goto release ;
6003         }
6004
6005         /* if left is same as result */
6006         if(pic14_sameRegs(AOP(result),AOP(left))){
6007                 int know_W = -1;
6008                 for(;size--; offset++,lit>>=8) {
6009                         if(AOP_TYPE(right) == AOP_LIT){
6010                                 if((lit & 0xff) == 0)
6011                                         /*  or'ing with 0 has no effect */
6012                                         continue;
6013                                 else {
6014                                         int p = my_powof2(lit & 0xff);
6015                                         if(p>=0) {
6016                                                 /* only one bit is set in the literal, so use a bsf instruction */
6017                                                 emitpcode(POC_BSF,
6018                                                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6019                                         } else {
6020                                                 if(know_W != (int)(lit & 0xff))
6021                                                         emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
6022                                                 know_W = lit & 0xff;
6023                                                 emitpcode(POC_IORWF, popGet(AOP(left),offset));
6024                                         }
6025                                         
6026                                 }
6027                         } else {
6028                                 if (AOP_TYPE(left) == AOP_ACC) {
6029                                         emitpcode(POC_IORFW,  popGet(AOP(right),offset));
6030                                         pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6031                                 } else {        
6032                                         emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
6033                                         emitpcode(POC_IORWF,  popGet(AOP(left),offset));
6034                                         
6035                                         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6036                                         pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
6037                                         
6038                                 }
6039                         }
6040                 }
6041         } else {
6042                 // left & result in different registers
6043                 if(AOP_TYPE(result) == AOP_CRY){
6044                         // result = bit
6045                         // if(size), result in bit
6046                         // if(!size && ifx), conditional oper: if(left | right)
6047                         symbol *tlbl = newiTempLabel(NULL);
6048                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6049                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6050                         
6051                         
6052                         if(size)
6053                                 pic14_emitcode(";XXX setb","c");
6054                         while(sizer--){
6055                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6056                                 pic14_emitcode(";XXX orl","a,%s",
6057                                         aopGet(AOP(left),offset,FALSE,FALSE));
6058                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6059                                 offset++;
6060                         }
6061                         if(size){
6062                                 CLRC;
6063                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6064                                 pic14_outBitC(result);
6065                         } else if(ifx)
6066                                 jmpTrueOrFalse(ifx, tlbl);
6067                 } else for(;(size--);offset++){
6068                         // normal case
6069                         // result = left | right
6070                         if(AOP_TYPE(right) == AOP_LIT){
6071                                 int t = (lit >> (offset*8)) & 0x0FFL;
6072                                 switch(t) { 
6073                                 case 0x00:
6074                                         if (AOP_TYPE(left) != AOP_ACC) {
6075                                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
6076                                         }
6077                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6078                                         
6079                                         break;
6080                                 default:
6081                                         if (AOP_TYPE(left) == AOP_ACC) {
6082                                                 emitpcode(POC_IORLW,  popGetLit(t));
6083                                         } else {
6084                                                 emitpcode(POC_MOVLW,  popGetLit(t));
6085                                                 emitpcode(POC_IORFW,  popGet(AOP(left),offset));
6086                                         }
6087                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));        
6088                                 }
6089                                 continue;
6090                         }
6091                         
6092                         // faster than result <- left, anl result,right
6093                         // and better if result is SFR
6094                         if (AOP_TYPE(left) == AOP_ACC) {
6095                                 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6096                         } else {
6097                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6098                                 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6099                         }
6100                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6101                 }
6102         }
6103
6104 release :
6105         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6106         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6107         freeAsmop(result,NULL,ic,TRUE);     
6108 }
6109
6110 /*-----------------------------------------------------------------*/
6111 /* genXor - code for xclusive or                                   */
6112 /*-----------------------------------------------------------------*/
6113 static void genXor (iCode *ic, iCode *ifx)
6114 {
6115         operand *left, *right, *result;
6116         int size, offset=0;
6117         unsigned long lit = 0L;
6118         
6119         FENTRY;
6120         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6121         
6122         aopOp((left = IC_LEFT(ic)),ic,FALSE);
6123         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6124         aopOp((result=IC_RESULT(ic)),ic,TRUE);
6125         
6126         /* if left is a literal & right is not ||
6127         if left needs acc & right does not */
6128         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6129                 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6130                 operand *tmp = right ;
6131                 right = left;
6132                 left = tmp;
6133         }
6134         
6135         /* if result = right then exchange them */
6136         if(pic14_sameRegs(AOP(result),AOP(right))){
6137                 operand *tmp = right ;
6138                 right = left;
6139                 left = tmp;
6140         }
6141         
6142         /* if right is bit then exchange them */
6143         if (AOP_TYPE(right) == AOP_CRY &&
6144                 AOP_TYPE(left) != AOP_CRY){
6145                 operand *tmp = right ;
6146                 right = left;
6147                 left = tmp;
6148         }
6149         if(AOP_TYPE(right) == AOP_LIT)
6150                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6151         
6152         size = AOP_SIZE(result);
6153         
6154         // if(bit ^ yy)
6155         // xx = bit ^ yy;
6156         if (AOP_TYPE(left) == AOP_CRY){
6157                 if(AOP_TYPE(right) == AOP_LIT){
6158                         // c = bit & literal;
6159                         if(lit>>1){
6160                                 // lit>>1  != 0 => result = 1
6161                                 if(AOP_TYPE(result) == AOP_CRY){
6162                                         if(size)
6163                                         {emitpcode(POC_BSF,  popGet(AOP(result),offset));
6164                                         pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6165                                         else if(ifx)
6166                                                 continueIfTrue(ifx);
6167                                         goto release;
6168                                 }
6169                                 pic14_emitcode("setb","c");
6170                         } else{
6171                                 // lit == (0 or 1)
6172                                 if(lit == 0){
6173                                         // lit == 0, result = left
6174                                         if(size && pic14_sameRegs(AOP(result),AOP(left)))
6175                                                 goto release;
6176                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6177                                 } else{
6178                                         // lit == 1, result = not(left)
6179                                         if(size && pic14_sameRegs(AOP(result),AOP(left))){
6180                                                 emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
6181                                                 emitpcode(POC_XORWF,  popGet(AOP(result),offset));
6182                                                 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6183                                                 goto release;
6184                                         } else {
6185                                                 assert ( !"incomplete genXor" );
6186                                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6187                                                 pic14_emitcode("cpl","c");
6188                                         }
6189                                 }
6190                         }
6191                         
6192                 } else {
6193                         // right != literal
6194                         symbol *tlbl = newiTempLabel(NULL);
6195                         if (AOP_TYPE(right) == AOP_CRY){
6196                                 // c = bit ^ bit;
6197                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6198                         }
6199                         else{
6200                                 int sizer = AOP_SIZE(right);
6201                                 // c = bit ^ val
6202                                 // if val>>1 != 0, result = 1
6203                                 pic14_emitcode("setb","c");
6204                                 while(sizer){
6205                                         MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6206                                         if(sizer == 1)
6207                                                 // test the msb of the lsb
6208                                                 pic14_emitcode("anl","a,#0xfe");
6209                                         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6210                                         sizer--;
6211                                 }
6212                                 // val = (0,1)
6213                                 pic14_emitcode("rrc","a");
6214                         }
6215                         pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6216                         pic14_emitcode("cpl","c");
6217                         pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6218                 }
6219                 // bit = c
6220                 // val = c
6221                 if(size)
6222                         pic14_outBitC(result);
6223                 // if(bit | ...)
6224                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6225                         genIfxJump(ifx, "c");           
6226                 goto release ;
6227         }
6228         
6229         if(pic14_sameRegs(AOP(result),AOP(left))){
6230                 /* if left is same as result */
6231                 for(;size--; offset++) {
6232                         if(AOP_TYPE(right) == AOP_LIT){
6233                                 int t  = (lit >> (offset*8)) & 0x0FFL;
6234                                 if(t == 0x00L)
6235                                         continue;
6236                                 else
6237                                         if (IS_AOP_PREG(left)) {
6238                                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6239                                                 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6240                                                 aopPut(AOP(result),"a",offset);
6241                                         } else {
6242                                                 emitpcode(POC_MOVLW, popGetLit(t));
6243                                                 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6244                                                 pic14_emitcode("xrl","%s,%s",
6245                                                         aopGet(AOP(left),offset,FALSE,TRUE),
6246                                                         aopGet(AOP(right),offset,FALSE,FALSE));
6247                                         }
6248                         } else {
6249                                 if (AOP_TYPE(left) == AOP_ACC)
6250                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6251                                 else {
6252                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6253                                         emitpcode(POC_XORWF,popGet(AOP(left),offset));
6254                                         /*
6255                                         if (IS_AOP_PREG(left)) {
6256                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6257                                         aopPut(AOP(result),"a",offset);
6258                                         } else
6259                                         pic14_emitcode("xrl","%s,a",
6260                                         aopGet(AOP(left),offset,FALSE,TRUE));
6261                                         */
6262                                 }
6263                         }
6264                 }
6265         } else {
6266                 // left & result in different registers
6267                 if(AOP_TYPE(result) == AOP_CRY){
6268                         // result = bit
6269                         // if(size), result in bit
6270                         // if(!size && ifx), conditional oper: if(left ^ right)
6271                         symbol *tlbl = newiTempLabel(NULL);
6272                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6273                         if(size)
6274                                 pic14_emitcode("setb","c");
6275                         while(sizer--){
6276                                 if((AOP_TYPE(right) == AOP_LIT) &&
6277                                         (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6278                                         MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6279                                 } else {
6280                                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6281                                         pic14_emitcode("xrl","a,%s",
6282                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6283                                 }
6284                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6285                                 offset++;
6286                         }
6287                         if(size){
6288                                 CLRC;
6289                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6290                                 pic14_outBitC(result);
6291                         } else if(ifx)
6292                                 jmpTrueOrFalse(ifx, tlbl);
6293                 } else for(;(size--);offset++){
6294                         // normal case
6295                         // result = left & right
6296                         if(AOP_TYPE(right) == AOP_LIT){
6297                                 int t = (lit >> (offset*8)) & 0x0FFL;
6298                                 switch(t) { 
6299                                 case 0x00:
6300                                         if (AOP_TYPE(left) != AOP_ACC) {
6301                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6302                                         }
6303                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6304                                         pic14_emitcode("movf","%s,w",
6305                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6306                                         pic14_emitcode("movwf","%s",
6307                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6308                                         break;
6309                                 case 0xff:
6310                                         if (AOP_TYPE(left) == AOP_ACC) {
6311                                                 emitpcode(POC_XORLW, popGetLit(t));
6312                                         } else {
6313                                                 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6314                                         }
6315                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6316                                         break;
6317                                 default:
6318                                         if (AOP_TYPE(left) == AOP_ACC) {
6319                                                 emitpcode(POC_XORLW, popGetLit(t));
6320                                         } else {
6321                                                 emitpcode(POC_MOVLW, popGetLit(t));
6322                                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6323                                         }
6324                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6325                                         pic14_emitcode("movlw","0x%x",t);
6326                                         pic14_emitcode("xorwf","%s,w",
6327                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6328                                         pic14_emitcode("movwf","%s",
6329                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6330                                         
6331                                 }
6332                                 continue;
6333                         }
6334                         
6335                         // faster than result <- left, anl result,right
6336                         // and better if result is SFR
6337                         if (AOP_TYPE(left) == AOP_ACC) {
6338                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6339                         } else {
6340                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6341                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6342                         }
6343                         if ( AOP_TYPE(result) != AOP_ACC){
6344                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6345                         }
6346                 }
6347         }
6348         
6349 release :
6350         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6351         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6352         freeAsmop(result,NULL,ic,TRUE);     
6353 }
6354
6355 /*-----------------------------------------------------------------*/
6356 /* genInline - write the inline code out                           */
6357 /*-----------------------------------------------------------------*/
6358 static void genInline (iCode *ic)
6359 {
6360   char *buffer, *bp, *bp1;
6361
6362   FENTRY;
6363   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6364
6365   _G.inLine += (!options.asmpeep);
6366
6367   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6368   strcpy(buffer,IC_INLINE(ic));
6369
6370   /* emit each line as a code */
6371   while (*bp) {
6372     if (*bp == '\n') {
6373       *bp++ = '\0';
6374       
6375       if(*bp1)
6376         addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6377       bp1 = bp;
6378     } else {
6379       if (*bp == ':') {
6380         bp++;
6381         *bp = '\0';
6382         bp++;
6383
6384         /* print label, use this special format with NULL directive
6385          * to denote that the argument should not be indented with tab */
6386         addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6387
6388         bp1 = bp;
6389       } else
6390         bp++;
6391     }
6392   }
6393   if ((bp1 != bp) && *bp1)
6394     addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6395
6396   Safe_free(buffer);
6397
6398   _G.inLine -= (!options.asmpeep);
6399 }
6400
6401 /*-----------------------------------------------------------------*/
6402 /* genRRC - rotate right with carry                                */
6403 /*-----------------------------------------------------------------*/
6404 static void genRRC (iCode *ic)
6405 {
6406         operand *left , *result ;
6407         int size, offset = 0, same;
6408         
6409         FENTRY;
6410         /* rotate right with carry */
6411         left = IC_LEFT(ic);
6412         result=IC_RESULT(ic);
6413         aopOp (left,ic,FALSE);
6414         aopOp (result,ic,FALSE);
6415         
6416         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6417         
6418         same = pic14_sameRegs(AOP(result),AOP(left));
6419         
6420         size = AOP_SIZE(result);    
6421         
6422         /* get the lsb and put it into the carry */
6423         emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6424         
6425         offset = 0 ;
6426         
6427         while(size--) {
6428                 
6429                 if(same) {
6430                         emitpcode(POC_RRF, popGet(AOP(left),offset));
6431                 } else {
6432                         emitpcode(POC_RRFW, popGet(AOP(left),offset));
6433                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6434                 }
6435                 
6436                 offset++;
6437         }
6438         
6439         freeAsmop(left,NULL,ic,TRUE);
6440         freeAsmop(result,NULL,ic,TRUE);
6441 }
6442
6443 /*-----------------------------------------------------------------*/
6444 /* genRLC - generate code for rotate left with carry               */
6445 /*-----------------------------------------------------------------*/
6446 static void genRLC (iCode *ic)
6447 {    
6448         operand *left , *result ;
6449         int size, offset = 0;
6450         int same;
6451         
6452         FENTRY;
6453         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6454         /* rotate right with carry */
6455         left = IC_LEFT(ic);
6456         result=IC_RESULT(ic);
6457         aopOp (left,ic,FALSE);
6458         aopOp (result,ic,FALSE);
6459         
6460         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6461         
6462         same = pic14_sameRegs(AOP(result),AOP(left));
6463         
6464         /* move it to the result */
6465         size = AOP_SIZE(result);    
6466         
6467         /* get the msb and put it into the carry */
6468         emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6469         
6470         offset = 0 ;
6471         
6472         while(size--) {
6473                 
6474                 if(same) {
6475                         emitpcode(POC_RLF, popGet(AOP(left),offset));
6476                 } else {
6477                         emitpcode(POC_RLFW, popGet(AOP(left),offset));
6478                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6479                 }
6480                 
6481                 offset++;
6482         }
6483         
6484         
6485         freeAsmop(left,NULL,ic,TRUE);
6486         freeAsmop(result,NULL,ic,TRUE);
6487 }
6488
6489 /*-----------------------------------------------------------------*/
6490 /* genGetHbit - generates code get highest order bit               */
6491 /*-----------------------------------------------------------------*/
6492 static void genGetHbit (iCode *ic)
6493 {
6494         operand *left, *result;
6495         left = IC_LEFT(ic);
6496         result=IC_RESULT(ic);
6497         aopOp (left,ic,FALSE);
6498         aopOp (result,ic,FALSE);
6499         
6500         FENTRY;
6501         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6502         /* get the highest order byte into a */
6503         MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6504         if(AOP_TYPE(result) == AOP_CRY){
6505                 pic14_emitcode("rlc","a");
6506                 pic14_outBitC(result);
6507         }
6508         else{
6509                 pic14_emitcode("rl","a");
6510                 pic14_emitcode("anl","a,#0x01");
6511                 pic14_outAcc(result);
6512         }
6513         
6514         
6515         freeAsmop(left,NULL,ic,TRUE);
6516         freeAsmop(result,NULL,ic,TRUE);
6517 }
6518
6519 /*-----------------------------------------------------------------*/
6520 /* AccLsh - shift left accumulator by known count                  */
6521 /* MARK: pic14 always rotates through CARRY!                       */
6522 /*-----------------------------------------------------------------*/
6523 static void AccLsh (pCodeOp *pcop,int shCount)
6524 {
6525         FENTRY;
6526         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6527         shCount &= 0x0007;              // shCount : 0..7
6528         switch(shCount){
6529         case 0 :
6530                 return;
6531                 break;
6532         case 1 :
6533                 emitCLRC;
6534                 emitpcode(POC_RLF,pcop);
6535                 return;
6536                 break;
6537         case 2 :
6538                 emitpcode(POC_RLF,pcop);
6539                 emitpcode(POC_RLF,pcop);
6540                 break;
6541         case 3 :
6542                 emitpcode(POC_RLF,pcop);
6543                 emitpcode(POC_RLF,pcop);
6544                 emitpcode(POC_RLF,pcop);
6545                 break;
6546         case 4 :
6547                 emitpcode(POC_SWAPF,pcop);
6548                 break;
6549         case 5 :
6550                 emitpcode(POC_SWAPF,pcop);
6551                 emitpcode(POC_RLF,pcop);
6552                 break;
6553         case 6 :
6554                 emitpcode(POC_SWAPF,pcop);
6555                 emitpcode(POC_RLF,pcop);
6556                 emitpcode(POC_RLF,pcop);
6557                 break;
6558         case 7 :
6559                 emitpcode(POC_RRFW,pcop);
6560                 emitpcode(POC_RRF,pcop);
6561                 break;
6562         }
6563         /* clear invalid bits */
6564         emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6565         emitpcode(POC_ANDWF, pcop);
6566 }
6567
6568 /*-----------------------------------------------------------------*/
6569 /* AccRsh - shift right accumulator by known count                 */
6570 /* MARK: pic14 always rotates through CARRY!                       */
6571 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6572 /*            1: mask out invalid bits (zero-extend)               */
6573 /*            2: sign-extend result (pretty slow)                  */
6574 /*-----------------------------------------------------------------*/
6575 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6576 {
6577         FENTRY;
6578         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6579         shCount &= 0x0007;              // shCount : 0..7
6580         switch(shCount){
6581         case 0 :
6582                 return;
6583                 break;
6584         case 1 :
6585                 /* load sign if needed */
6586                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6587                 else if (mask_mode == 1) emitCLRC;
6588                 emitpcode(POC_RRF,pcop);
6589                 return;
6590                 break;
6591         case 2 :
6592                 /* load sign if needed */
6593                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6594                 emitpcode(POC_RRF,pcop);
6595                 /* load sign if needed */
6596                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6597                 emitpcode(POC_RRF,pcop);
6598                 if (mask_mode == 2) return;
6599                 break;
6600         case 3 :
6601                 /* load sign if needed */
6602                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6603                 emitpcode(POC_RRF,pcop);
6604                 /* load sign if needed */
6605                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6606                 emitpcode(POC_RRF,pcop);
6607                 /* load sign if needed */
6608                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6609                 emitpcode(POC_RRF,pcop);
6610                 if (mask_mode == 2) return;
6611                 break;
6612         case 4 :
6613                 emitpcode(POC_SWAPF,pcop);
6614                 break;
6615         case 5 :
6616                 emitpcode(POC_SWAPF,pcop);
6617                 emitpcode(POC_RRF,pcop);
6618                 break;
6619         case 6 :
6620                 emitpcode(POC_SWAPF,pcop);
6621                 emitpcode(POC_RRF,pcop);
6622                 emitpcode(POC_RRF,pcop);
6623                 break;
6624         case 7 :
6625                 if (mask_mode == 2)
6626                 {
6627                         /* load sign */
6628                         emitpcode(POC_RLFW,pcop);
6629                         emitpcode(POC_CLRF,pcop);
6630                         emitSKPNC;
6631                         emitpcode(POC_COMF,pcop);
6632                         return;
6633                 } else {
6634                         emitpcode(POC_RLFW,pcop);
6635                         emitpcode(POC_RLF,pcop);
6636                 }
6637                 break;
6638         }
6639
6640         if (mask_mode == 0)
6641         {
6642                 /* leave invalid bits undefined */
6643                 return;
6644         }
6645         
6646         /* clear invalid bits -- zero-extend */
6647         emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6648         emitpcode(POC_ANDWF, pcop);
6649
6650         if (mask_mode == 2) {
6651           /* sign-extend */
6652           emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6653           emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6654           emitpcode(POC_IORWF, pcop);
6655         }
6656 }
6657
6658 #if 0
6659 /*-----------------------------------------------------------------*/
6660 /* AccSRsh - signed right shift accumulator by known count                 */
6661 /*-----------------------------------------------------------------*/
6662 static void AccSRsh (int shCount)
6663 {
6664         symbol *tlbl ;
6665         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6666         if(shCount != 0){
6667                 if(shCount == 1){
6668                         pic14_emitcode("mov","c,acc.7");
6669                         pic14_emitcode("rrc","a");
6670                 } else if(shCount == 2){
6671                         pic14_emitcode("mov","c,acc.7");
6672                         pic14_emitcode("rrc","a");
6673                         pic14_emitcode("mov","c,acc.7");
6674                         pic14_emitcode("rrc","a");
6675                 } else {
6676                         tlbl = newiTempLabel(NULL);
6677                         /* rotate right accumulator */
6678                         AccRol(8 - shCount);
6679                         /* and kill the higher order bits */
6680                         pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6681                         pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6682                         pic14_emitcode("orl","a,#0x%02x",
6683                                 (unsigned char)~SRMask[shCount]);
6684                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6685                 }
6686         }
6687 }
6688
6689 /*-----------------------------------------------------------------*/
6690 /* shiftR1Left2Result - shift right one byte from left to result   */
6691 /*-----------------------------------------------------------------*/
6692 static void shiftR1Left2ResultSigned (operand *left, int offl,
6693                                                                           operand *result, int offr,
6694                                                                           int shCount)
6695 {
6696         int same;
6697         
6698         FENTRY;
6699         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6700         
6701         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6702         
6703         switch(shCount) {
6704         case 1:
6705                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6706                 if(same) 
6707                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6708                 else {
6709                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6710                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6711                 }
6712                 
6713                 break;
6714         case 2:
6715                 
6716                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6717                 if(same) 
6718                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6719                 else {
6720                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6721                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6722                 }
6723                 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6724                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6725                 
6726                 break;
6727                 
6728         case 3:
6729                 if(same)
6730                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6731                 else {
6732                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6733                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6734                 }
6735                 
6736                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6737                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6738                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6739                 
6740                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6741                 emitpcode(POC_IORLW, popGetLit(0xe0));
6742                 
6743                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6744                 break;
6745                 
6746         case 4:
6747                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6748                 emitpcode(POC_ANDLW,  popGetLit(0x0f));
6749                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6750                 emitpcode(POC_IORLW,  popGetLit(0xf0));
6751                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6752                 break;
6753         case 5:
6754                 if(same) {
6755                         emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6756                 } else {
6757                         emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6758                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6759                 }
6760                 emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6761                 emitpcode(POC_ANDLW,  popGetLit(0x07));
6762                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6763                 emitpcode(POC_IORLW,  popGetLit(0xf8));
6764                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6765                 break;
6766                 
6767         case 6:
6768                 if(same) {
6769                         emitpcode(POC_MOVLW, popGetLit(0x00));
6770                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6771                         emitpcode(POC_MOVLW, popGetLit(0xfe));
6772                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6773                         emitpcode(POC_IORLW, popGetLit(0x01));
6774                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6775                 } else {
6776                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6777                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6778                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6779                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6780                         emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6781                 }
6782                 break;
6783                 
6784         case 7:
6785                 if(same) {
6786                         emitpcode(POC_MOVLW, popGetLit(0x00));
6787                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6788                         emitpcode(POC_MOVLW, popGetLit(0xff));
6789                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6790                 } else {
6791                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6792                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6793                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6794                 }
6795                 
6796         default:
6797                 break;
6798         }
6799 }
6800
6801 /*-----------------------------------------------------------------*/
6802 /* shiftR1Left2Result - shift right one byte from left to result   */
6803 /*-----------------------------------------------------------------*/
6804 static void shiftR1Left2Result (operand *left, int offl,
6805                                                                 operand *result, int offr,
6806                                                                 int shCount, int sign)
6807 {
6808         int same;
6809         
6810         FENTRY;
6811         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6812         
6813         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6814         
6815         /* Copy the msb into the carry if signed. */
6816         if(sign) {
6817                 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6818                 return;
6819         }
6820         
6821         
6822         
6823         switch(shCount) {
6824         case 1:
6825                 emitCLRC;
6826                 if(same) 
6827                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6828                 else {
6829                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6830                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6831                 }
6832                 break;
6833         case 2:
6834                 emitCLRC;
6835                 if(same) {
6836                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6837                 } else {
6838                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6839                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6840                 }
6841                 emitCLRC;
6842                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6843                 
6844                 break;
6845         case 3:
6846                 if(same)
6847                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6848                 else {
6849                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6850                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6851                 }
6852                 
6853                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6854                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6855                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6856                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6857                 break;
6858                 
6859         case 4:
6860                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6861                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6862                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6863                 break;
6864                 
6865         case 5:
6866                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6867                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6868                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6869                 emitCLRC;
6870                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6871                 
6872                 break;
6873         case 6:
6874                 
6875                 emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6876                 emitpcode(POC_ANDLW, popGetLit(0x80));
6877                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6878                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6879                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6880                 break;
6881                 
6882         case 7:
6883                 
6884                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6885                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6886                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6887                 
6888                 break;
6889                 
6890         default:
6891                 break;
6892         }
6893 }
6894
6895 /*-----------------------------------------------------------------*/
6896 /* shiftL1Left2Result - shift left one byte from left to result    */
6897 /*-----------------------------------------------------------------*/
6898 static void shiftL1Left2Result (operand *left, int offl,
6899                                                                 operand *result, int offr, int shCount)
6900 {
6901         int same;
6902         
6903         //    char *l;
6904         FENTRY;
6905         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6906         
6907         same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6908         DEBUGpic14_emitcode ("; ***","same =  %d",same);
6909         //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6910         //    MOVA(l);
6911         /* shift left accumulator */
6912         //AccLsh(shCount); // don't comment out just yet...
6913         //    aopPut(AOP(result),"a",offr);
6914         
6915         switch(shCount) {
6916         case 1:
6917                 /* Shift left 1 bit position */
6918                 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6919                 if(same) {
6920                         emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6921                 } else {
6922                         emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6923                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6924                 }
6925                 break;
6926         case 2:
6927                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6928                 emitpcode(POC_ANDLW,popGetLit(0x7e));
6929                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6930                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6931                 break;
6932         case 3:
6933                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6934                 emitpcode(POC_ANDLW,popGetLit(0x3e));
6935                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6936                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6937                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6938                 break;
6939         case 4:
6940                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6941                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6942                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6943                 break;
6944         case 5:
6945                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6946                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6947                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6948                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6949                 break;
6950         case 6:
6951                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6952                 emitpcode(POC_ANDLW, popGetLit(0x30));
6953                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6954                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6955                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6956                 break;
6957         case 7:
6958                 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6959                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6960                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6961                 break;
6962                 
6963         default:
6964                 DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6965         }
6966         
6967 }
6968 #endif
6969
6970 /*-----------------------------------------------------------------*/
6971 /* movLeft2Result - move byte from left to result                  */
6972 /*-----------------------------------------------------------------*/
6973 static void movLeft2Result (operand *left, int offl,
6974                                                         operand *result, int offr)
6975 {
6976         char *l;
6977         FENTRY;
6978         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6979         if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6980                 l = aopGet(AOP(left),offl,FALSE,FALSE);
6981                 
6982                 if (*l == '@' && (IS_AOP_PREG(result))) {
6983                         pic14_emitcode("mov","a,%s",l);
6984                         aopPut(AOP(result),"a",offr);
6985                 } else {
6986                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6987                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6988                 }
6989         }
6990 }
6991
6992 /*-----------------------------------------------------------------*/
6993 /* shiftLeft_Left2ResultLit - shift left by known count            */
6994 /*-----------------------------------------------------------------*/
6995
6996 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6997 {
6998         int size, same, offr, i;
6999
7000         size = AOP_SIZE(left);
7001         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7002         
7003         same = pic14_sameRegs (AOP(left), AOP(result));
7004         
7005         offr = shCount / 8;
7006         shCount = shCount & 0x07;
7007
7008         size -= offr;
7009
7010         switch (shCount)
7011         {
7012         case 0: /* takes 0 or 2N cycles (for offr==0) */
7013                 if (!same || offr) {
7014                         for (i=size-1; i >= 0; i--)
7015                                 movLeft2Result (left, i, result, offr + i);
7016                 } // if
7017                 break;
7018                 
7019         case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
7020                 if (same && offr) {
7021                         shiftLeft_Left2ResultLit (left, result, 8 * offr);
7022                         shiftLeft_Left2ResultLit (result, result, shCount);
7023                         return; /* prevent clearing result again */
7024                 } else {
7025                         emitCLRC;
7026                         for (i=0; i < size; i++) {
7027                                 if (same && !offr) {
7028                                         emitpcode (POC_RLF, popGet (AOP(left), i));
7029                                 } else {
7030                                         emitpcode (POC_RLFW, popGet (AOP(left), i));
7031                                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7032                                 } // if
7033                         } // for
7034                 } // if (offr)
7035                 break;
7036                 
7037         case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
7038                 /* works in-place/with offr as well */
7039                 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
7040                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7041                 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
7042
7043                 for (i = size - 2; i >= 0; i--)
7044                 {
7045                         emitpcode (POC_SWAPFW, popGet (AOP(left), i));
7046                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7047                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7048                         emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
7049                         emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
7050                 } // for i
7051                 break;
7052                 
7053         case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7054                 /* works in-place/with offr as well */
7055                 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7056                 for (i = size-2; i >= 0; i--) {
7057                         emitpcode (POC_RRFW, popGet (AOP(left), i));
7058                         emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7059                 } // for i
7060                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7061                 emitpcode (POC_RRF, popGet (AOP(result), offr));
7062                 break;
7063         
7064         default:
7065                 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7066                 shiftLeft_Left2ResultLit (result, result, 1);
7067                 return; /* prevent clearing result again */
7068                 break;
7069         } // switch
7070
7071         while (0 < offr--)
7072         {
7073                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7074         } // while
7075 }
7076
7077 /*-----------------------------------------------------------------*/
7078 /* shiftRight_Left2ResultLit - shift right by known count          */
7079 /*-----------------------------------------------------------------*/
7080
7081 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7082 {
7083         int size, same, offr, i;
7084
7085         size = AOP_SIZE(left);
7086         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7087         
7088         same = pic14_sameRegs (AOP(left), AOP(result));
7089         
7090         offr = shCount / 8;
7091         shCount = shCount & 0x07;
7092
7093         size -= offr;
7094
7095         if (size)
7096         {
7097                 switch (shCount)
7098                 {
7099                 case 0: /* takes 0 or 2N cycles (for offr==0) */
7100                         if (!same || offr) {
7101                                 for (i=0; i < size; i++)
7102                                         movLeft2Result (left, i + offr, result, i);
7103                         } // if
7104                         break;
7105                         
7106                 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7107                         emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7108                         if (same && offr) {
7109                                 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7110                                 shiftRight_Left2ResultLit (result, result, shCount, sign);
7111                                 return; /* prevent sign-extending result again */
7112                         } else {
7113                                 emitCLRC;
7114                                 if (sign) {
7115                                         emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7116                                         emitSETC;
7117                                 }
7118                                 for (i = size-1; i >= 0; i--) {
7119                                         if (same && !offr) {
7120                                                 emitpcode (POC_RRF, popGet (AOP(left), i));
7121                                         } else {
7122                                                 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7123                                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7124                                         }
7125                                 } // for i
7126                         } // if (offr)
7127                         break;
7128                         
7129                 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7130                         /* works in-place/with offr as well */
7131                         emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7132                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7133                         emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7134
7135                         for (i = 1; i < size; i++)
7136                         {
7137                                 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7138                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7139                                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7140                                 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7141                                 emitpcode (POC_XORWF, popGet (AOP(result), i));
7142                         } // for i
7143
7144                         if (sign)
7145                         {
7146                                 emitpcode (POC_MOVLW, popGetLit (0xF0));
7147                                 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7148                                 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7149                         } // if
7150                         break;
7151                         
7152                 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7153                         /* works in-place/with offr as well */
7154                         emitpcode (POC_RLFW, popGet (AOP(left), offr));
7155                         for (i = 0; i < size-1; i++) {
7156                                 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7157                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7158                         } // for i
7159                         emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7160                         if (!sign) {
7161                                 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7162                         } else {
7163                                 emitSKPNC;
7164                                 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7165                         }
7166                         break;
7167                 
7168                 default:
7169                         shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7170                         shiftRight_Left2ResultLit (result, result, 1, sign);
7171                         return; /* prevent sign extending result again */
7172                         break;
7173                 } // switch
7174         } // if
7175
7176         addSign (result, size, sign);
7177 }
7178
7179 #if 0
7180 /*-----------------------------------------------------------------*/
7181 /* shiftL2Left2Result - shift left two bytes from left to result   */
7182 /*-----------------------------------------------------------------*/
7183 static void shiftL2Left2Result (operand *left, int offl,
7184                                                                 operand *result, int offr, int shCount)
7185 {
7186         FENTRY;
7187         
7188         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7189         
7190         if(pic14_sameRegs(AOP(result), AOP(left))) {
7191                 switch(shCount) {
7192                 case 0:
7193                         break;
7194                 case 1:
7195                 case 2:
7196                 case 3:
7197                         
7198                         emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7199                         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7200                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7201                         
7202                         while(--shCount) {
7203                                 emitCLRC;
7204                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7205                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7206                         }
7207                         
7208                         break;
7209                 case 4:
7210                 case 5:
7211                         emitpcode(POC_MOVLW, popGetLit(0x0f));
7212                         emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7213                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7214                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7215                         emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7216                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7217                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7218                         if(shCount >=5) {
7219                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7220                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7221                         }
7222                         break;
7223                 case 6:
7224                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7225                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7226                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7227                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7228                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7229                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7230                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7231                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7232                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7233                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7234                         break;
7235                 case 7:
7236                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7237                         emitpcode(POC_RRFW, popGet(AOP(result),offr));
7238                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7239                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7240                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7241                 }
7242                 
7243         } else {
7244                 switch(shCount) {
7245                 case 0:
7246                         break;
7247                 case 1:
7248                 case 2:
7249                 case 3:
7250                 /* note, use a mov/add for the shift since the mov has a
7251                         chance of getting optimized out */
7252                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7253                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7254                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7255                         emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
7256                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7257                         
7258                         while(--shCount) {
7259                                 emitCLRC;
7260                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7261                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7262                         }
7263                         break;
7264                         
7265                 case 4:
7266                 case 5:
7267                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7268                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7269                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7270                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7271                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7272                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7273                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7274                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7275                         
7276                         
7277                         if(shCount == 5) {
7278                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7279                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7280                         }
7281                         break;
7282                 case 6:
7283                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7284                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7285                         emitpcode(POC_RRFW, popGet(AOP(result),offl));
7286                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
7287                         
7288                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7289                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7290                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7291                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7292                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7293                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7294                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7295                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7296                         break;
7297                 case 7:
7298                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7299                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7300                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7301                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7302                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7303                 }
7304         }
7305         
7306 }
7307
7308 /*-----------------------------------------------------------------*/
7309 /* shiftR2Left2Result - shift right two bytes from left to result  */
7310 /*-----------------------------------------------------------------*/
7311 static void shiftR2Left2Result (operand *left, int offl,
7312                                                                 operand *result, int offr,
7313                                                                 int shCount, int sign)
7314 {
7315         int same=0;
7316         
7317         FENTRY;
7318         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7319         same = pic14_sameRegs(AOP(result), AOP(left));
7320         
7321         if(same && ((offl + MSB16) == offr)){
7322                 same=1;
7323                 /* don't crash result[offr] */
7324                 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7325                 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7326         }
7327         /* else {
7328         movLeft2Result(left,offl, result, offr);
7329         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7330         }
7331         */
7332         /* a:x >> shCount (x = lsb(result))*/
7333         /*
7334         if(sign)
7335         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7336         else {
7337         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7338         */
7339         switch(shCount) {
7340         case 0:
7341                 break;
7342         case 1:
7343         case 2:
7344         case 3:
7345                 if(sign)
7346                         emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7347                 else
7348                         emitCLRC;
7349                 
7350                 if(same) {
7351                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7352                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7353                 } else {
7354                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7355                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7356                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7357                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7358                 }
7359                 
7360                 while(--shCount) {
7361                         if(sign)
7362                                 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7363                         else
7364                                 emitCLRC;
7365                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7366                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7367                 }
7368                 break;
7369         case 4:
7370         case 5:
7371                 if(same) {
7372                         
7373                         emitpcode(POC_MOVLW, popGetLit(0xf0));
7374                         emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7375                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7376                         
7377                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7378                         emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7379                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7380                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7381                 } else {
7382                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7383                         emitpcode(POC_ANDLW, popGetLit(0x0f));
7384                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7385                         
7386                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7387                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7388                         emitpcode(POC_ANDLW, popGetLit(0xf0));
7389                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7390                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7391                 }
7392                 
7393                 if(shCount >=5) {
7394                         emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7395                         emitpcode(POC_RRF, popGet(AOP(result),offr));
7396                 }
7397                 
7398                 if(sign) {
7399                         emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7400                         emitpcode(POC_BTFSC, 
7401                                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7402                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7403                 }
7404                 
7405                 break;
7406                 
7407         case 6:
7408                 if(same) {
7409                         
7410                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7411                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7412                         
7413                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7414                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7415                         emitpcode(POC_RLFW, popGet(AOP(result),offr));
7416                         emitpcode(POC_ANDLW,popGetLit(0x03));
7417                         if(sign) {
7418                                 emitpcode(POC_BTFSC, 
7419                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7420                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7421                         }
7422                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7423                         emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7424                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7425                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7426                 } else {
7427                         emitpcode(POC_RLFW, popGet(AOP(left),offl));
7428                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7429                         emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7430                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7431                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7432                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7433                         emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7434                         emitpcode(POC_ANDLW,popGetLit(0x03));
7435                         if(sign) {
7436                                 emitpcode(POC_BTFSC, 
7437                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7438                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7439                         }
7440                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7441                         //emitpcode(POC_RLF,  popGet(AOP(result),offr));
7442                         
7443                         
7444                 }
7445                 
7446                 break;
7447         case 7:
7448                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7449                 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7450                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7451                 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7452                 if(sign) {
7453                         emitSKPNC;
7454                         emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7455                 } else 
7456                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7457   }
7458 }
7459
7460 /*-----------------------------------------------------------------*/
7461 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7462 /*-----------------------------------------------------------------*/
7463 static void shiftLLeftOrResult (operand *left, int offl,
7464                                                                 operand *result, int offr, int shCount)
7465 {
7466         FENTRY;
7467         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7468         
7469         /* shift left accumulator */
7470         AccLsh(left,offl,shCount);
7471         /* or with result */
7472         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7473         assert ( !"broken (modifies left, fails for left==result))" );
7474 }
7475
7476 /*-----------------------------------------------------------------*/
7477 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7478 /*-----------------------------------------------------------------*/
7479 static void shiftRLeftOrResult (operand *left, int offl,
7480                                                                 operand *result, int offr, int shCount)
7481 {
7482         FENTRY;
7483         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7484         
7485         /* shift right accumulator */
7486         AccRsh(left,offl,shCount);
7487         /* or with result */
7488         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7489         assert ( !"broken (modifies left, fails for left==result))" );
7490 }
7491
7492 /*-----------------------------------------------------------------*/
7493 /* genlshOne - left shift a one byte quantity by known count       */
7494 /*-----------------------------------------------------------------*/
7495 static void genlshOne (operand *result, operand *left, int shCount)
7496 {       
7497         FENTRY;
7498         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7499         shiftL1Left2Result(left, LSB, result, LSB, shCount);
7500 }
7501
7502 /*-----------------------------------------------------------------*/
7503 /* genlshTwo - left shift two bytes by known amount != 0           */
7504 /*-----------------------------------------------------------------*/
7505 static void genlshTwo (operand *result,operand *left, int shCount)
7506 {
7507         int size;
7508         
7509         FENTRY;
7510         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7511         size = pic14_getDataSize(result);
7512         
7513         /* if shCount >= 8 */
7514         if (shCount >= 8) {
7515                 shCount -= 8 ;
7516                 
7517                 if (size > 1){
7518                         if (shCount)
7519                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7520                         else 
7521                                 movLeft2Result(left, LSB, result, MSB16);
7522                 }
7523                 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7524         }
7525         
7526         /*  1 <= shCount <= 7 */
7527         else {  
7528                 if(size == 1)
7529                         shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7530                 else 
7531                         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7532         }
7533 }
7534
7535 /*-----------------------------------------------------------------*/
7536 /* shiftLLong - shift left one long from left to result            */
7537 /* offl = LSB or MSB16                                             */
7538 /*-----------------------------------------------------------------*/
7539 static void shiftLLong (operand *left, operand *result, int offr )
7540 {
7541         char *l;
7542         int size = AOP_SIZE(result);
7543         
7544         FENTRY;
7545         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7546         if(size >= LSB+offr){
7547                 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7548                 MOVA(l);
7549                 pic14_emitcode("add","a,acc");
7550                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7551                         size >= MSB16+offr && offr != LSB )
7552                         pic14_emitcode("xch","a,%s",
7553                         aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7554                 else      
7555                         aopPut(AOP(result),"a",LSB+offr);
7556         }
7557         
7558         if(size >= MSB16+offr){
7559                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7560                         l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7561                         MOVA(l);
7562                 }
7563                 pic14_emitcode("rlc","a");
7564                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7565                         size >= MSB24+offr && offr != LSB)
7566                         pic14_emitcode("xch","a,%s",
7567                         aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7568                 else      
7569                         aopPut(AOP(result),"a",MSB16+offr);
7570         }
7571         
7572         if(size >= MSB24+offr){
7573                 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7574                         l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7575                         MOVA(l);
7576                 }
7577                 pic14_emitcode("rlc","a");
7578                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7579                         size >= MSB32+offr && offr != LSB )
7580                         pic14_emitcode("xch","a,%s",
7581                         aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7582                 else      
7583                         aopPut(AOP(result),"a",MSB24+offr);
7584         }
7585         
7586         if(size > MSB32+offr){
7587                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7588                         l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7589                         MOVA(l);  
7590                 }
7591                 pic14_emitcode("rlc","a");
7592                 aopPut(AOP(result),"a",MSB32+offr);
7593         }
7594         if(offr != LSB)
7595                 aopPut(AOP(result),zero,LSB);       
7596 }
7597
7598 /*-----------------------------------------------------------------*/
7599 /* genlshFour - shift four byte by a known amount != 0             */
7600 /*-----------------------------------------------------------------*/
7601 static void genlshFour (operand *result, operand *left, int shCount)
7602 {
7603         int size;
7604         
7605         FENTRY;
7606         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7607         size = AOP_SIZE(result);
7608         
7609         /* if shifting more that 3 bytes */
7610         if (shCount >= 24 ) {
7611                 shCount -= 24;
7612                 if (shCount)
7613                 /* lowest order of left goes to the highest
7614                 order of the destination */
7615                 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7616                 else
7617                         movLeft2Result(left, LSB, result, MSB32);
7618                 aopPut(AOP(result),zero,LSB);
7619                 aopPut(AOP(result),zero,MSB16);
7620                 aopPut(AOP(result),zero,MSB32);
7621                 return;
7622         }
7623         
7624         /* more than two bytes */
7625         else if ( shCount >= 16 ) {
7626                 /* lower order two bytes goes to higher order two bytes */
7627                 shCount -= 16;
7628                 /* if some more remaining */
7629                 if (shCount)
7630                         shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7631                 else {
7632                         movLeft2Result(left, MSB16, result, MSB32);
7633                         movLeft2Result(left, LSB, result, MSB24);
7634                 }
7635                 aopPut(AOP(result),zero,MSB16);
7636                 aopPut(AOP(result),zero,LSB);
7637                 return;
7638         }    
7639         
7640         /* if more than 1 byte */
7641         else if ( shCount >= 8 ) {
7642                 /* lower order three bytes goes to higher order  three bytes */
7643                 shCount -= 8;
7644                 if(size == 2){
7645                         if(shCount)
7646                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7647                         else
7648                                 movLeft2Result(left, LSB, result, MSB16);
7649                 }
7650                 else{   /* size = 4 */
7651                         if(shCount == 0){
7652                                 movLeft2Result(left, MSB24, result, MSB32);
7653                                 movLeft2Result(left, MSB16, result, MSB24);
7654                                 movLeft2Result(left, LSB, result, MSB16);
7655                                 aopPut(AOP(result),zero,LSB);
7656                         }
7657                         else if(shCount == 1)
7658                                 shiftLLong(left, result, MSB16);
7659                         else{
7660                                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7661                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7662                                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7663                                 aopPut(AOP(result),zero,LSB);
7664                         }
7665                 }
7666         }
7667         
7668         /* 1 <= shCount <= 7 */
7669         else if(shCount <= 2){
7670                 shiftLLong(left, result, LSB);
7671                 if(shCount == 2)
7672                         shiftLLong(result, result, LSB);
7673         }
7674         /* 3 <= shCount <= 7, optimize */
7675         else{
7676                 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7677                 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7678                 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7679         }
7680 }
7681 #endif
7682
7683 #if 0
7684 /*-----------------------------------------------------------------*/
7685 /* genLeftShiftLiteral - left shifting by known count              */
7686 /*-----------------------------------------------------------------*/
7687 static void genLeftShiftLiteral (operand *left,
7688                                                                  operand *right,
7689                                                                  operand *result,
7690                                                                  iCode *ic)
7691 {    
7692         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7693         //int size;
7694         
7695         FENTRY;
7696         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7697         freeAsmop(right,NULL,ic,TRUE);
7698         
7699         aopOp(left,ic,FALSE);
7700         aopOp(result,ic,FALSE);
7701
7702         size = getSize(operandType(result));
7703         
7704 #if VIEW_SIZE
7705         pic14_emitcode("; shift left ","result %d, left %d",size,
7706                 AOP_SIZE(left));
7707 #endif
7708         
7709         /* I suppose that the left size >= result size */
7710         if(shCount == 0){
7711                 while(size--){
7712                         movLeft2Result(left, size, result, size);
7713                 }
7714         }
7715         
7716         else if(shCount >= (size * 8))
7717                 while(size--)
7718                         aopPut(AOP(result),zero,size);
7719                 else{
7720                         switch (size) {
7721                         case 1:
7722                                 genlshOne (result,left,shCount);
7723                                 break;
7724                                 
7725                         case 2:
7726                         case 3:
7727                                 genlshTwo (result,left,shCount);
7728                                 break;
7729                                 
7730                         case 4:
7731                                 genlshFour (result,left,shCount);
7732                                 break;
7733                         }
7734                 }
7735                 freeAsmop(left,NULL,ic,TRUE);
7736                 freeAsmop(result,NULL,ic,TRUE);
7737 }
7738 #endif
7739
7740 /*-----------------------------------------------------------------*
7741 * genMultiAsm - repeat assembly instruction for size of register.
7742 * if endian == 1, then the high byte (i.e base address + size of 
7743 * register) is used first else the low byte is used first;
7744 *-----------------------------------------------------------------*/
7745 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7746 {
7747         
7748         int offset = 0;
7749         
7750         FENTRY;
7751         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7752         
7753         if(!reg)
7754                 return;
7755         
7756         if(!endian) {
7757                 endian = 1;
7758         } else {
7759                 endian = -1;
7760                 offset = size-1;
7761         }
7762         
7763         while(size--) {
7764                 emitpcode(poc,    popGet(AOP(reg),offset));
7765                 offset += endian;
7766         }
7767         
7768 }
7769
7770 #if 0
7771 /*-----------------------------------------------------------------*/
7772 /* genLeftShift - generates code for left shifting                 */
7773 /*-----------------------------------------------------------------*/
7774 static void genLeftShift (iCode *ic)
7775 {
7776         operand *left,*right, *result;
7777         int size, offset;
7778         unsigned long lit = 0L;
7779         char *l;
7780         symbol *tlbl , *tlbl1;
7781         pCodeOp *pctemp;
7782         
7783         FENTRY;
7784         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7785         
7786         right = IC_RIGHT(ic);
7787         left  = IC_LEFT(ic);
7788         result = IC_RESULT(ic);
7789         
7790         aopOp(right,ic,FALSE);
7791         aopOp(left,ic,FALSE);
7792         aopOp(result,ic,FALSE);
7793         
7794         
7795         /* if the shift count is known then do it 
7796         as efficiently as possible */
7797         if (AOP_TYPE(right) == AOP_LIT) {
7798                 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7799                 return ;
7800         }
7801         
7802         /* shift count is unknown then we have to form 
7803         a loop get the loop count in B : Note: we take
7804         only the lower order byte since shifting
7805         more that 32 bits make no sense anyway, ( the
7806         largest size of an object can be only 32 bits ) */  
7807         
7808         /* this code fails for RIGHT == RESULT */
7809         assert (!pic14_sameRegs (AOP(right), AOP(result)));
7810         
7811         /* now move the left to the result if they are not the
7812         same */
7813         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7814                 AOP_SIZE(result) > 1) {
7815                 
7816                 size = AOP_SIZE(result);
7817                 offset=0;
7818                 while (size--) {
7819                         l = aopGet(AOP(left),offset,FALSE,TRUE);
7820                         if (*l == '@' && (IS_AOP_PREG(result))) {
7821                                 
7822                                 pic14_emitcode("mov","a,%s",l);
7823                                 aopPut(AOP(result),"a",offset);
7824                         } else {
7825                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7826                                 emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7827                                 //aopPut(AOP(result),l,offset);
7828                         }
7829                         offset++;
7830                 }
7831         }
7832         
7833         if(AOP_TYPE(left) == AOP_LIT)
7834                 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7835
7836         size = AOP_SIZE(result);
7837         
7838         /* if it is only one byte then */
7839         if (size == 1) {
7840                 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7841                         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7842                         emitpcode(POC_ANDLW,  popGetLit(0xf0));
7843                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7844                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7845                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7846                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7847                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7848                         emitpcode(POC_RLFW,   popGet(AOP(result),0));
7849                         emitpcode(POC_ANDLW,  popGetLit(0xfe));
7850                         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7851                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7852                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7853                 } else {
7854                         
7855                         tlbl = newiTempLabel(NULL);
7856                         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7857                                 mov2w (AOP(left), 0);
7858                                 emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7859                         }
7860                         
7861                         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7862                         emitpcode(POC_RRF,    popGet(AOP(result),0));
7863                         emitpLabel(tlbl->key);
7864                         emitpcode(POC_RLF,    popGet(AOP(result),0));
7865                         emitpcode(POC_ADDLW,  popGetLit(1));
7866                         emitSKPC;
7867                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7868                 }
7869                 goto release ;
7870         }
7871         
7872         if (pic14_sameRegs(AOP(left),AOP(result))) {
7873                 
7874                 tlbl = newiTempLabel(NULL);
7875                 emitpcode(POC_COMFW,  popGet(AOP(right),0));
7876                 genMultiAsm(POC_RRF, result, size,1);
7877                 emitpLabel(tlbl->key);
7878                 genMultiAsm(POC_RLF, result, size,0);
7879                 emitpcode(POC_ADDLW,  popGetLit(1));
7880                 emitSKPC;
7881                 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7882                 goto release;
7883         }
7884         
7885         //tlbl = newiTempLabel(NULL);
7886         //offset = 0 ;   
7887         //tlbl1 = newiTempLabel(NULL);
7888         
7889         //reAdjustPreg(AOP(result));    
7890         
7891         //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7892         //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7893         //l = aopGet(AOP(result),offset,FALSE,FALSE);
7894         //MOVA(l);
7895         //pic14_emitcode("add","a,acc");         
7896         //aopPut(AOP(result),"a",offset++);
7897         //while (--size) {
7898         //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7899         //  MOVA(l);
7900         //  pic14_emitcode("rlc","a");         
7901         //  aopPut(AOP(result),"a",offset++);
7902         //}
7903         //reAdjustPreg(AOP(result));
7904         
7905         //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7906         //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7907         
7908         
7909         tlbl = newiTempLabel(NULL);
7910         tlbl1= newiTempLabel(NULL);
7911         
7912         size = AOP_SIZE(result);
7913         offset = 1;
7914         
7915         pctemp = popGetTempReg();  /* grab a temporary working register. */
7916         
7917         emitpcode(POC_MOVFW, popGet(AOP(right),0));
7918         
7919         /* offset should be 0, 1 or 3 */
7920         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7921         emitSKPNZ;
7922         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7923         
7924         emitpcode(POC_MOVWF, pctemp);
7925         
7926         
7927         emitpLabel(tlbl->key);
7928         
7929         emitCLRC;
7930         emitpcode(POC_RLF,  popGet(AOP(result),0));
7931         while(--size)
7932                 emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7933         
7934         emitpcode(POC_DECFSZ,  pctemp);
7935         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7936         emitpLabel(tlbl1->key);
7937         
7938         popReleaseTempReg(pctemp);
7939         
7940         
7941 release:
7942         freeAsmop (right,NULL,ic,TRUE);
7943         freeAsmop(left,NULL,ic,TRUE);
7944         freeAsmop(result,NULL,ic,TRUE);
7945 }
7946 #endif
7947
7948 #if 0
7949 /*-----------------------------------------------------------------*/
7950 /* genrshOne - right shift a one byte quantity by known count      */
7951 /*-----------------------------------------------------------------*/
7952 static void genrshOne (operand *result, operand *left,
7953                                            int shCount, int sign)
7954 {
7955         FENTRY;
7956         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7957         shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7958 }
7959
7960 /*-----------------------------------------------------------------*/
7961 /* genrshTwo - right shift two bytes by known amount != 0          */
7962 /*-----------------------------------------------------------------*/
7963 static void genrshTwo (operand *result,operand *left,
7964                                            int shCount, int sign)
7965 {
7966         FENTRY;
7967         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7968         /* if shCount >= 8 */
7969         if (shCount >= 8) {
7970                 shCount -= 8 ;
7971                 if (shCount)
7972                         shiftR1Left2Result(left, MSB16, result, LSB,
7973                         shCount, sign);
7974                 else
7975                         movLeft2Result(left, MSB16, result, LSB);
7976                 
7977                 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7978                 
7979                 if(sign) {
7980                         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7981                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7982                 }
7983         }
7984         
7985         /*  1 <= shCount <= 7 */
7986         else
7987                 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7988 }
7989
7990 /*-----------------------------------------------------------------*/
7991 /* shiftRLong - shift right one long from left to result           */
7992 /* offl = LSB or MSB16                                             */
7993 /*-----------------------------------------------------------------*/
7994 static void shiftRLong (operand *left, int offl,
7995                                                 operand *result, int sign)
7996 {
7997         int size, same;
7998         
7999         FENTRY;
8000         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8001         
8002         size = AOP_SIZE(left);
8003         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
8004         
8005         if (sign)
8006                 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
8007         else
8008                 emitCLRC;
8009
8010         assert (offl >= 0 && offl < size);
8011
8012         same = pic14_sameRegs (AOP(left), AOP(result));
8013
8014         /* perform the shift */
8015         while (size--)
8016         {
8017                 if (same && !offl) {
8018                         emitpcode (POC_RRF, popGet (AOP(result), size));
8019                 } else {
8020                         emitpcode (POC_RRFW, popGet (AOP(left), size));
8021                         emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
8022                 }
8023         } // while
8024
8025         addSign (result, AOP_SIZE(left) - offl, sign);
8026 }
8027
8028 /*-----------------------------------------------------------------*/
8029 /* genrshFour - shift four byte by a known amount != 0             */
8030 /*-----------------------------------------------------------------*/
8031 static void genrshFour (operand *result, operand *left,
8032                                                 int shCount, int sign)
8033 {
8034         FENTRY;
8035         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8036         /* if shifting more that 3 bytes */
8037         if(shCount >= 24 ) {
8038                 shCount -= 24;
8039                 if(shCount)
8040                         shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8041                 else
8042                         movLeft2Result(left, MSB32, result, LSB);
8043                 
8044                 addSign(result, MSB16, sign);
8045         }
8046         else if(shCount >= 16){
8047                 shCount -= 16;
8048                 if(shCount)
8049                         shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8050                 else{
8051                         movLeft2Result(left, MSB24, result, LSB);
8052                         movLeft2Result(left, MSB32, result, MSB16);
8053                 }
8054                 addSign(result, MSB24, sign);
8055         }
8056         else if(shCount >= 8){
8057                 shCount -= 8;
8058                 if(shCount == 1)
8059                         shiftRLong(left, MSB16, result, sign);
8060                 else if(shCount == 0){
8061                         movLeft2Result(left, MSB16, result, LSB);
8062                         movLeft2Result(left, MSB24, result, MSB16);
8063                         movLeft2Result(left, MSB32, result, MSB24);
8064                         addSign(result, MSB32, sign);
8065                 }
8066                 else{
8067                         shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8068                         shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8069                         /* the last shift is signed */
8070                         shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8071                         addSign(result, MSB32, sign);
8072                 }
8073         }
8074         else{   /* 1 <= shCount <= 7 */
8075                 if(shCount <= 2){
8076                         shiftRLong(left, LSB, result, sign);
8077                         if(shCount == 2)
8078                                 shiftRLong(result, LSB, result, sign);
8079                 }
8080                 else{
8081                         shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8082                         shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8083                         shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8084                 }
8085         }
8086 }
8087
8088 /*-----------------------------------------------------------------*/
8089 /* genRightShiftLiteral - right shifting by known count            */
8090 /*-----------------------------------------------------------------*/
8091 static void genRightShiftLiteral (operand *left,
8092                                                                   operand *right,
8093                                                                   operand *result,
8094                                                                   iCode *ic,
8095                                                                   int sign)
8096 {    
8097         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8098         int lsize,res_size;
8099         
8100         FENTRY;
8101         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8102         freeAsmop(right,NULL,ic,TRUE);
8103         
8104         aopOp(left,ic,FALSE);
8105         aopOp(result,ic,FALSE);
8106         
8107 #if VIEW_SIZE
8108         pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8109                 AOP_SIZE(left));
8110 #endif
8111         
8112         lsize = pic14_getDataSize(left);
8113         res_size = pic14_getDataSize(result);
8114         /* test the LEFT size !!! */
8115         
8116         /* I suppose that the left size >= result size */
8117         if(shCount == 0){
8118                 while(res_size--)
8119                         movLeft2Result(left, res_size, result, res_size);
8120         }
8121         
8122         else if(shCount >= (lsize * 8)){
8123                 
8124                 if(res_size == 1) {
8125                         emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8126                         if(sign) {
8127                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8128                                 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8129                         }
8130                 } else {
8131                         
8132                         if(sign) {
8133                                 emitpcode(POC_MOVLW, popGetLit(0));
8134                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8135                                 emitpcode(POC_MOVLW, popGetLit(0xff));
8136                                 while(res_size--)
8137                                         emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8138                                 
8139                         } else {
8140                                 
8141                                 while(res_size--)
8142                                         emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8143                         }
8144                 }
8145         } else {
8146                 
8147                 switch (res_size) {
8148                 case 1:
8149                         genrshOne (result,left,shCount,sign);
8150                         break;
8151                         
8152                 case 2:
8153                         genrshTwo (result,left,shCount,sign);
8154                         break;
8155                         
8156                 case 4:
8157                         genrshFour (result,left,shCount,sign);
8158                         break;
8159                 default :
8160                         break;
8161                 }
8162                 
8163         }
8164
8165         freeAsmop(left,NULL,ic,TRUE);
8166         freeAsmop(result,NULL,ic,TRUE);
8167 }
8168 #endif
8169
8170 #if 0
8171 /*-----------------------------------------------------------------*/
8172 /* genSignedRightShift - right shift of signed number              */
8173 /*-----------------------------------------------------------------*/
8174 static void genSignedRightShift (iCode *ic)
8175 {
8176         operand *right, *left, *result;
8177         int size, offset;
8178         //  char *l;
8179         symbol *tlbl, *tlbl1 ;
8180         pCodeOp *pctemp;
8181         
8182         //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8183         
8184         /* we do it the hard way put the shift count in b
8185         and loop thru preserving the sign */
8186         FENTRY;
8187         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8188         
8189         right = IC_RIGHT(ic);
8190         left  = IC_LEFT(ic);
8191         result = IC_RESULT(ic);
8192         
8193         aopOp(right,ic,FALSE);  
8194         aopOp(left,ic,FALSE);
8195         aopOp(result,ic,FALSE);
8196         
8197         
8198         if ( AOP_TYPE(right) == AOP_LIT) {
8199                 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8200                 //genRightShiftLiteral (left,right,result,ic,1);
8201                 return ;
8202         }
8203         /* shift count is unknown then we have to form 
8204         a loop get the loop count in B : Note: we take
8205         only the lower order byte since shifting
8206         more that 32 bits make no sense anyway, ( the
8207         largest size of an object can be only 32 bits ) */  
8208         
8209         //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8210         //pic14_emitcode("inc","b");
8211         //freeAsmop (right,NULL,ic,TRUE);
8212         //aopOp(left,ic,FALSE);
8213         //aopOp(result,ic,FALSE);
8214         
8215         /* now move the left to the result if they are not the
8216         same */
8217         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
8218                 AOP_SIZE(result) > 1) {
8219                 
8220                 size = AOP_SIZE(result);
8221                 offset=0;
8222                 while (size--) { 
8223                         /*
8224                         l = aopGet(AOP(left),offset,FALSE,TRUE);
8225                         if (*l == '@' && IS_AOP_PREG(result)) {
8226                                 pic14_emitcode("mov","a,%s",l);
8227                                 aopPut(AOP(result),"a",offset);
8228                         } else
8229                         aopPut(AOP(result),l,offset);
8230                         */
8231                         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
8232                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
8233                         
8234                         offset++;
8235                 }
8236         }
8237         
8238         /* mov the highest order bit to OVR */    
8239         tlbl = newiTempLabel(NULL);
8240         tlbl1= newiTempLabel(NULL);
8241         
8242         size = AOP_SIZE(result);
8243         offset = size - 1;
8244         
8245         pctemp = popGetTempReg();  /* grab a temporary working register. */
8246         
8247         emitpcode(POC_MOVFW, popGet(AOP(right),0));
8248         
8249         /* offset should be 0, 1 or 3 */
8250         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8251         emitSKPNZ;
8252         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
8253         
8254         emitpcode(POC_MOVWF, pctemp);
8255         
8256         
8257         emitpLabel(tlbl->key);
8258         
8259         emitpcode(POC_RLFW,  popGet(AOP(result),offset));
8260         emitpcode(POC_RRF,   popGet(AOP(result),offset));
8261         
8262         while(--size) {
8263                 emitpcode(POC_RRF,   popGet(AOP(result),--offset));
8264         }
8265         
8266         emitpcode(POC_DECFSZ,  pctemp);
8267         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8268         emitpLabel(tlbl1->key);
8269         
8270         popReleaseTempReg(pctemp);
8271 #if 0
8272         size = AOP_SIZE(result);
8273         offset = size - 1;
8274         pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8275         pic14_emitcode("rlc","a");
8276         pic14_emitcode("mov","ov,c");
8277         /* if it is only one byte then */
8278         if (size == 1) {
8279                 l = aopGet(AOP(left),0,FALSE,FALSE);
8280                 MOVA(l);
8281                 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8282                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8283                 pic14_emitcode("mov","c,ov");
8284                 pic14_emitcode("rrc","a");
8285                 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8286                 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8287                 aopPut(AOP(result),"a",0);
8288                 goto release ;
8289         }
8290         
8291         reAdjustPreg(AOP(result));
8292         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8293         pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
8294         pic14_emitcode("mov","c,ov");
8295         while (size--) {
8296                 l = aopGet(AOP(result),offset,FALSE,FALSE);
8297                 MOVA(l);
8298                 pic14_emitcode("rrc","a");         
8299                 aopPut(AOP(result),"a",offset--);
8300         }
8301         reAdjustPreg(AOP(result));
8302         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8303         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8304         
8305 release:
8306 #endif
8307         
8308         freeAsmop(left,NULL,ic,TRUE);
8309         freeAsmop(result,NULL,ic,TRUE);
8310         freeAsmop(right,NULL,ic,TRUE);
8311 }
8312 #endif
8313
8314 /*-----------------------------------------------------------------*/
8315 /* loadSignToC - load the operand's sign bit into CARRY            */
8316 /*-----------------------------------------------------------------*/
8317
8318 static void loadSignToC (operand *op)
8319 {
8320         FENTRY;
8321         assert (op && AOP(op) && AOP_SIZE(op));
8322
8323         emitCLRC;
8324         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8325         emitSETC;
8326 }
8327
8328 /*-----------------------------------------------------------------*/
8329 /* genRightShift - generate code for right shifting                */
8330 /*-----------------------------------------------------------------*/
8331 static void genGenericShift (iCode *ic, int shiftRight)
8332 {
8333         operand *right, *left, *result;
8334         sym_link *retype ;
8335         int size;
8336         symbol *tlbl, *tlbl1, *inverselbl;
8337         
8338         FENTRY;
8339         /* if signed then we do it the hard way preserve the
8340         sign bit moving it inwards */
8341         retype = getSpec(operandType(IC_RESULT(ic)));
8342         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8343         
8344         /* signed & unsigned types are treated the same : i.e. the
8345         signed is NOT propagated inwards : quoting from the
8346         ANSI - standard : "for E1 >> E2, is equivalent to division
8347         by 2**E2 if unsigned or if it has a non-negative value,
8348         otherwise the result is implementation defined ", MY definition
8349         is that the sign does not get propagated */
8350         
8351         right = IC_RIGHT(ic);
8352         left  = IC_LEFT(ic);
8353         result = IC_RESULT(ic);
8354         
8355         aopOp(right,ic,FALSE);
8356         aopOp(left,ic,FALSE);
8357         aopOp(result,ic,FALSE);
8358         
8359         /* if the shift count is known then do it 
8360         as efficiently as possible */
8361         if (AOP_TYPE(right) == AOP_LIT) {
8362                 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8363                 if (lit < 0)
8364                 {
8365                         lit = -lit;
8366                         shiftRight = !shiftRight;
8367                 }
8368                 
8369                 if (shiftRight)
8370                         shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8371                 else
8372                         shiftLeft_Left2ResultLit (left, result, lit);
8373                 //genRightShiftLiteral (left,right,result,ic, 0);
8374                 return ;
8375         }
8376         
8377         /* shift count is unknown then we have to form 
8378         a loop get the loop count in B : Note: we take
8379         only the lower order byte since shifting
8380         more that 32 bits make no sense anyway, ( the
8381         largest size of an object can be only 32 bits ) */  
8382
8383         /* we must not overwrite the shift counter */
8384         assert (!pic14_sameRegs(AOP(right),AOP(result)));
8385         
8386         /* now move the left to the result if they are not the
8387         same */
8388         if (!pic14_sameRegs(AOP(left),AOP(result)))
8389         {
8390                 size = min(AOP_SIZE(result), AOP_SIZE(left));
8391                 while (size--) {
8392                         mov2w(AOP(left), size);
8393                         movwf(AOP(result), size);
8394                 }
8395                 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8396         }
8397         
8398         tlbl = newiTempLabel(NULL);
8399         tlbl1= newiTempLabel(NULL);
8400         inverselbl = NULL;
8401         size = AOP_SIZE(result);
8402
8403         mov2w(AOP(right),0);
8404         if (!SPEC_USIGN(operandType(right)))
8405         {
8406                 inverselbl = newiTempLabel(NULL);
8407                 /* signed shift count -- invert shift direction for c<0 */
8408                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8409                 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8410         } // if
8411         emitpcode(POC_SUBLW, popGetLit(0));     /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8412         /* check for `a = b >> c' with `-c == 0' */
8413         emitSKPNZ;
8414         emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8415         emitpLabel(tlbl->key);
8416         /* propagate the sign bit inwards for SIGNED result */
8417         if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8418         genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8419         emitpcode(POC_ADDLW,  popGetLit(1));    /* clears CARRY (unless W==0 afterwards) */
8420         emitSKPC;
8421         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8422
8423         if (!SPEC_USIGN(operandType(right)))
8424         {
8425                 symbol *inv_loop = newiTempLabel(NULL);
8426
8427                 shiftRight = !shiftRight;       /* invert shift direction */
8428                 
8429                 /* we came here from the code above -- we are done */
8430                 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8431                 
8432                 /* emit code for shifting N<0 steps, count is already in W */
8433                 emitpLabel(inverselbl->key);
8434                 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8435                 emitpLabel(inv_loop->key);
8436                 /* propagate the sign bit inwards for SIGNED result */
8437                 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8438                 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8439                 emitpcode(POC_ADDLW, popGetLit(1));
8440                 emitSKPC;
8441                 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8442         } // if
8443         
8444         emitpLabel(tlbl1->key);
8445         
8446         freeAsmop(left,NULL,ic,TRUE);
8447         freeAsmop (right,NULL,ic,TRUE);
8448         freeAsmop(result,NULL,ic,TRUE);
8449 }
8450
8451 static void genRightShift (iCode *ic)
8452 {
8453         genGenericShift(ic, 1);
8454 }
8455
8456 static void genLeftShift (iCode *ic)
8457 {
8458         genGenericShift(ic, 0);
8459 }
8460
8461 /*-----------------------------------------------------------------*/
8462 /* SetIrp - Set IRP bit                                            */
8463 /*-----------------------------------------------------------------*/
8464 void SetIrp(operand *result) {
8465         FENTRY;
8466         if (AOP_TYPE(result) == AOP_LIT) {
8467                 unsigned lit = (unsigned)operandLitValue(result);
8468                 if (lit&0x100)
8469                         emitSETIRP;
8470                 else
8471                         emitCLRIRP;
8472         } else {
8473                 if (PCOP(AOP(result))->type == PO_LITERAL) {
8474                         int addrs = PCOL(AOP(result))->lit;
8475                         if (addrs & 0x100)
8476                                 emitSETIRP;
8477                         else
8478                                 emitCLRIRP;
8479                 } else {
8480                         emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8481                         if(AOP_SIZE(result) > 1) {
8482                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8483                                 emitSETIRP;
8484                         }
8485                 }
8486         }
8487 }
8488
8489 static void
8490 setup_fsr (operand *ptr)
8491 {
8492   mov2w_op(ptr, 0);
8493   emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8494
8495   /* also setup-up IRP */
8496   SetIrp (ptr);
8497 }
8498
8499 /*-----------------------------------------------------------------*/
8500 /* emitPtrByteGet - emits code to get a byte into WREG from an     */
8501 /*                  arbitrary pointer (__code, __data, generic)    */
8502 /*-----------------------------------------------------------------*/
8503 static void
8504 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8505 {
8506     FENTRY;
8507     switch (p_type)
8508     {
8509     case POINTER:
8510     case FPOINTER:
8511       if (!alreadyAddressed) setup_fsr (src);
8512       emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8513       break;
8514     
8515     case CPOINTER:
8516       assert( AOP_SIZE(src) == 2 );
8517       mov2w_op(src, 0);
8518       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8519       mov2w_op(src, 1);
8520       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8521       emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE));   /* GPOINTER tag for __code space */
8522       call_libraryfunc ("__gptrget1");
8523       break;
8524     
8525     case GPOINTER:
8526       assert( AOP_SIZE(src) == 3 );
8527       mov2w_op(src, 0);
8528       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8529       mov2w_op(src, 1);
8530       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8531       mov2w_op(src, 2);
8532       call_libraryfunc ("__gptrget1");
8533       break;
8534     
8535     default:
8536       assert( !"unhandled pointer type" );
8537       break;
8538     }
8539 }
8540
8541 /*-----------------------------------------------------------------*/
8542 /* emitPtrByteSet - emits code to set a byte from src through a    */
8543 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR).       */
8544 /*-----------------------------------------------------------------*/
8545 static void
8546 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8547 {
8548     FENTRY;
8549     switch (p_type)
8550     {
8551     case POINTER:
8552     case FPOINTER:
8553       if (!alreadyAddressed) setup_fsr (dst);
8554       emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8555       break;
8556     
8557     case CPOINTER:
8558       assert( !"trying to assign to __code pointer" );
8559       break;
8560     
8561     case GPOINTER:
8562       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8563       mov2w_op(dst, 0);
8564       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8565       mov2w_op(dst, 1);
8566       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8567       mov2w_op(dst, 2);
8568       call_libraryfunc ("__gptrput1");
8569       break;
8570
8571     default:
8572       assert( !"unhandled pointer type" );
8573       break;
8574     }
8575 }
8576
8577 /*-----------------------------------------------------------------*/
8578 /* genUnpackBits - generates code for unpacking bits               */
8579 /*-----------------------------------------------------------------*/
8580 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8581 {    
8582   int rsize;            /* result size */
8583   sym_link *etype;      /* bitfield type information */
8584   int blen;             /* bitfield length */
8585   int bstr;             /* bitfield starting bit within byte */
8586
8587   FENTRY;
8588   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8589   etype = getSpec(operandType(result));
8590   rsize = getSize (operandType (result));
8591   blen = SPEC_BLEN (etype);
8592   bstr = SPEC_BSTR (etype);
8593
8594   /* single bit field case */
8595   if (blen == 1) {
8596     if (ifx) { /* that is for an if statement */
8597       pCodeOp *pcop;
8598       resolvedIfx rIfx;
8599       resolveIfx(&rIfx,ifx);
8600       if (ptype == -1) /* direct */
8601         pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8602       else
8603         pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8604       emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8605       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8606       ifx->generated=1;
8607     } else {
8608       int i;
8609       assert (!pic14_sameRegs (AOP(result), AOP(left)));
8610       for (i=0; i < AOP_SIZE(result); i++)
8611         emitpcode (POC_CLRF, popGet (AOP(result), i));
8612
8613       switch (ptype)
8614       {
8615       case -1:
8616         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8617         /* adjust result below */
8618         break;
8619         
8620       case POINTER:
8621       case FPOINTER:
8622       case GPOINTER:
8623       case CPOINTER:
8624         emitPtrByteGet (left, ptype, FALSE);
8625         emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8626         emitSKPZ;
8627         /* adjust result below */
8628         break;
8629         
8630       default:
8631         assert( !"unhandled pointer type" );
8632       } // switch
8633
8634       /* move sign-/zero extended bit to result */
8635       if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8636         emitpcode (POC_INCF, popGet (AOP(result), 0));
8637       } else {
8638         emitpcode (POC_DECF, popGet (AOP(result), 0));
8639       }
8640       addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8641     }
8642     return;
8643   }
8644   else if (blen <= 8 && ((blen + bstr) <= 8))
8645   {
8646     /* blen > 1 */
8647     int i;
8648
8649     for (i=0; i < AOP_SIZE(result); i++)
8650       emitpcode (POC_CLRF, popGet (AOP(result), i));
8651
8652     switch (ptype)
8653     {
8654     case -1:
8655       mov2w(AOP(left), 0);
8656       break;
8657       
8658     case POINTER:
8659     case FPOINTER:
8660     case GPOINTER:
8661     case CPOINTER:
8662       emitPtrByteGet (left, ptype, FALSE);
8663       break;
8664       
8665     default:
8666       assert( !"unhandled pointer type" );
8667     } // switch
8668
8669     if (blen < 8)
8670       emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8671     movwf(AOP(result), 0);
8672     AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8673
8674     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8675     {
8676       /* signed bitfield */
8677       assert (bstr + blen > 0);
8678       emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8679       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8680       emitpcode(POC_IORWF, popGet(AOP(result),0));
8681     }
8682     addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8683     return;
8684   }
8685
8686   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8687 }
8688
8689 #if 1
8690 /*-----------------------------------------------------------------*/
8691 /* genDataPointerGet - generates code when ptr offset is known     */
8692 /*-----------------------------------------------------------------*/
8693 static void genDataPointerGet (operand *left, 
8694         operand *result, 
8695         iCode *ic)
8696 {
8697         int size , offset = 0;
8698                 
8699         FENTRY;
8700         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8701         
8702         
8703         /* optimization - most of the time, left and result are the same
8704         * address, but different types. for the pic code, we could omit
8705         * the following
8706         */
8707         aopOp(result,ic,TRUE);
8708         
8709         if (pic14_sameRegs (AOP(left), AOP(result)))
8710                 return;
8711         
8712         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8713         
8714         //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8715         
8716         size = AOP_SIZE(result);
8717         if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8718         
8719         offset = 0;
8720         while (size--) {
8721                 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8722                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8723                 offset++;
8724         }
8725         
8726         freeAsmop(left,NULL,ic,TRUE);
8727         freeAsmop(result,NULL,ic,TRUE);
8728 }
8729 #endif
8730
8731 /*-----------------------------------------------------------------*/
8732 /* genNearPointerGet - pic14_emitcode for near pointer fetch       */
8733 /*-----------------------------------------------------------------*/
8734 static void genNearPointerGet (operand *left, 
8735                                                            operand *result, 
8736                                                            iCode *ic)
8737 {
8738         asmop *aop = NULL;
8739         sym_link *ltype = operandType(left);
8740         sym_link *rtype = operandType(result);
8741         sym_link *retype= getSpec(rtype);      /* bitfield type information */
8742         int direct = 0;
8743
8744         FENTRY;
8745         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8746         
8747         
8748         aopOp(left,ic,FALSE);
8749         
8750         /* if left is rematerialisable and
8751         result is not bit variable type and
8752         the left is pointer to data space i.e
8753         lower 128 bytes of space */
8754         if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8755                 !IS_BITVAR(retype)         &&
8756                 PIC_IS_DATA_PTR(ltype)) {
8757                 genDataPointerGet (left,result,ic);
8758                 return ;
8759         }
8760         
8761         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8762         aopOp (result,ic,FALSE);
8763         
8764         /* Check if can access directly instead of via a pointer */
8765         if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8766                 && AOP_SIZE(result) == 1)
8767         {
8768                 direct = 1;
8769         }
8770
8771         if (IS_BITFIELD(getSpec(operandType(result)))) 
8772         {
8773                 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8774                 goto release;
8775         }
8776         
8777         /* If the pointer value is not in a the FSR then need to put it in */
8778         /* Must set/reset IRP bit for use with FSR. */
8779         if (!direct)
8780           setup_fsr (left);
8781         
8782 //      sym_link *etype;
8783         /* if bitfield then unpack the bits */
8784         {
8785                 /* we have can just get the values */
8786                 int size = AOP_SIZE(result);
8787                 int offset = 0 ;  
8788                 
8789                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8790                 
8791                 while(size--) {
8792                         if (direct)
8793                                 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8794                         else
8795                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8796                         if (AOP_TYPE(result) == AOP_LIT) {
8797                                 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8798                         } else {
8799                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8800                         }
8801                         if (size && !direct)
8802                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8803                         offset++;
8804                 }
8805         }
8806         
8807         /* now some housekeeping stuff */
8808         if (aop) {
8809                 /* we had to allocate for this iCode */
8810                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8811                 freeAsmop(NULL,aop,ic,TRUE);
8812         } else { 
8813                 /* we did not allocate which means left
8814                 already in a pointer register, then
8815                 if size > 0 && this could be used again
8816                 we have to point it back to where it 
8817                 belongs */
8818                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8819                 if (AOP_SIZE(result) > 1 &&
8820                         !OP_SYMBOL(left)->remat &&
8821                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8822                         ic->depth )) {
8823                         int size = AOP_SIZE(result) - 1;
8824                         while (size--)
8825                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8826                 }
8827         }
8828         
8829 release:
8830         /* done */
8831         freeAsmop(left,NULL,ic,TRUE);
8832         freeAsmop(result,NULL,ic,TRUE);
8833
8834 }
8835
8836 #if 0
8837 /*-----------------------------------------------------------------*/
8838 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8839 /*-----------------------------------------------------------------*/
8840 static void genPagedPointerGet (operand *left, 
8841                                                                 operand *result, 
8842                                                                 iCode *ic)
8843 {
8844         asmop *aop = NULL;
8845         regs *preg = NULL ;
8846         char *rname ;
8847         sym_link *rtype, *retype;    
8848         
8849         FENTRY;
8850         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8851         
8852         rtype = operandType(result);
8853         retype= getSpec(rtype);
8854         
8855         aopOp(left,ic,FALSE);
8856         
8857         /* if the value is already in a pointer register
8858         then don't need anything more */
8859         if (!AOP_INPREG(AOP(left))) {
8860                 /* otherwise get a free pointer register */
8861                 aop = newAsmop(0);
8862                 preg = getFreePtr(ic,&aop,FALSE);
8863                 pic14_emitcode("mov","%s,%s",
8864                         preg->name,
8865                         aopGet(AOP(left),0,FALSE,TRUE));
8866                 rname = preg->name ;
8867         } else
8868                 rname = aopGet(AOP(left),0,FALSE,FALSE);
8869         
8870         freeAsmop(left,NULL,ic,TRUE);
8871         aopOp (result,ic,FALSE);
8872         
8873         /* if bitfield then unpack the bits */
8874         if (IS_BITFIELD(retype)) 
8875                 genUnpackBits (result,left,rname,PPOINTER,0);
8876         else {
8877                 /* we have can just get the values */
8878                 int size = AOP_SIZE(result);
8879                 int offset = 0 ;  
8880                 
8881                 while (size--) {
8882                         
8883                         pic14_emitcode("movx","a,@%s",rname);
8884                         aopPut(AOP(result),"a",offset);
8885                         
8886                         offset++ ;
8887                         
8888                         if (size)
8889                                 pic14_emitcode("inc","%s",rname);
8890                 }
8891         }
8892         
8893         /* now some housekeeping stuff */
8894         if (aop) {
8895                 /* we had to allocate for this iCode */
8896                 freeAsmop(NULL,aop,ic,TRUE);
8897         } else { 
8898         /* we did not allocate which means left
8899         already in a pointer register, then
8900         if size > 0 && this could be used again
8901         we have to point it back to where it 
8902                 belongs */
8903                 if (AOP_SIZE(result) > 1 &&
8904                         !OP_SYMBOL(left)->remat &&
8905                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8906                         ic->depth )) {
8907                         int size = AOP_SIZE(result) - 1;
8908                         while (size--)
8909                                 pic14_emitcode("dec","%s",rname);
8910                 }
8911         }
8912         
8913         /* done */
8914         freeAsmop(result,NULL,ic,TRUE);
8915         
8916         
8917 }
8918
8919 /*-----------------------------------------------------------------*/
8920 /* genFarPointerGet - gget value from far space                    */
8921 /*-----------------------------------------------------------------*/
8922 static void genFarPointerGet (operand *left,
8923                                                           operand *result, iCode *ic)
8924 {
8925         int size, offset ;
8926         sym_link *retype = getSpec(operandType(result));
8927         
8928         FENTRY;
8929         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8930         
8931         aopOp(left,ic,FALSE);
8932         
8933         /* if the operand is already in dptr 
8934         then we do nothing else we move the value to dptr */
8935         if (AOP_TYPE(left) != AOP_STR) {
8936                 /* if this is remateriazable */
8937                 if (AOP_TYPE(left) == AOP_IMMD)
8938                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8939                 else { /* we need to get it byte by byte */
8940                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8941                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8942                         if (options.model == MODEL_FLAT24)
8943                         {
8944                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8945                         }
8946                 }
8947         }
8948         /* so dptr know contains the address */
8949         freeAsmop(left,NULL,ic,TRUE);
8950         aopOp(result,ic,FALSE);
8951         
8952         /* if bit then unpack */
8953         if (IS_BITFIELD(retype)) 
8954                 genUnpackBits(result,left,"dptr",FPOINTER,0);
8955         else {
8956                 size = AOP_SIZE(result);
8957                 offset = 0 ;
8958                 
8959                 while (size--) {
8960                         pic14_emitcode("movx","a,@dptr");
8961                         aopPut(AOP(result),"a",offset++);
8962                         if (size)
8963                                 pic14_emitcode("inc","dptr");
8964                 }
8965         }
8966         
8967         freeAsmop(result,NULL,ic,TRUE);
8968 }
8969 #endif
8970
8971 #if 0
8972 /*-----------------------------------------------------------------*/
8973 /* genCodePointerGet - get value from code space                  */
8974 /*-----------------------------------------------------------------*/
8975 static void genCodePointerGet (operand *left,
8976                                                            operand *result, iCode *ic)
8977 {
8978         int size, offset ;
8979         sym_link *retype = getSpec(operandType(result));
8980         
8981         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8982         
8983         aopOp(left,ic,FALSE);
8984         
8985         /* if the operand is already in dptr 
8986         then we do nothing else we move the value to dptr */
8987         if (AOP_TYPE(left) != AOP_STR) {
8988                 /* if this is remateriazable */
8989                 if (AOP_TYPE(left) == AOP_IMMD)
8990                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8991                 else { /* we need to get it byte by byte */
8992                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8993                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8994                         if (options.model == MODEL_FLAT24)
8995                         {
8996                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8997                         }
8998                 }
8999         }
9000         /* so dptr know contains the address */
9001         freeAsmop(left,NULL,ic,TRUE);
9002         aopOp(result,ic,FALSE);
9003         
9004         /* if bit then unpack */
9005         if (IS_BITFIELD(retype)) 
9006                 genUnpackBits(result,left,"dptr",CPOINTER,0);
9007         else {
9008                 size = AOP_SIZE(result);
9009                 offset = 0 ;
9010                 
9011                 while (size--) {
9012                         pic14_emitcode("clr","a");
9013                         pic14_emitcode("movc","a,@a+dptr");
9014                         aopPut(AOP(result),"a",offset++);
9015                         if (size)
9016                                 pic14_emitcode("inc","dptr");
9017                 }
9018         }
9019         
9020         freeAsmop(result,NULL,ic,TRUE);
9021 }
9022 #endif
9023 /*-----------------------------------------------------------------*/
9024 /* genGenPointerGet - gget value from generic pointer space        */
9025 /*-----------------------------------------------------------------*/
9026 static void genGenPointerGet (operand *left,
9027                                                           operand *result, iCode *ic)
9028 {
9029         FENTRY;
9030         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9031         aopOp(left,ic,FALSE);
9032         aopOp(result,ic,FALSE);
9033         
9034         
9035         DEBUGpic14_AopType(__LINE__,left,NULL,result);
9036
9037         if (IS_BITFIELD(getSpec(operandType(result))))
9038         {
9039           genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
9040           return;
9041         }
9042
9043         {
9044           /* emit call to __gptrget */
9045           char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
9046           int size = AOP_SIZE(result);
9047           int idx = 0;
9048
9049           assert (size > 0 && size <= 4);
9050
9051           /* pass arguments */
9052           assert (AOP_SIZE(left) == 3);
9053           mov2w(AOP(left), 0);
9054           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9055           mov2w(AOP(left), 1);
9056           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9057           mov2w(AOP(left), 2);
9058           call_libraryfunc (func[size]);
9059           
9060           /* save result */
9061           movwf (AOP(result), --size);
9062           while (size--) {
9063             emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
9064             movwf (AOP(result), size);
9065           } // while
9066         }
9067         
9068         freeAsmop(left,NULL,ic,TRUE);
9069         freeAsmop(result,NULL,ic,TRUE);
9070         
9071 }
9072
9073 /*-----------------------------------------------------------------*/
9074 /* genConstPointerGet - get value from const generic pointer space */
9075 /*-----------------------------------------------------------------*/
9076 static void genConstPointerGet (operand *left,
9077                                                                 operand *result, iCode *ic)
9078 {
9079         //sym_link *retype = getSpec(operandType(result));
9080         #if 0
9081         symbol *albl, *blbl;//, *clbl;
9082         pCodeOp *pcop;
9083         #endif
9084         PIC_OPCODE poc;
9085         int i, size, lit;
9086         
9087         FENTRY;
9088         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9089         aopOp(left,ic,FALSE);
9090         aopOp(result,ic,FALSE);
9091         
9092         size = AOP_SIZE(result);
9093         
9094         DEBUGpic14_AopType(__LINE__,left,NULL,result);
9095         
9096         DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9097
9098         lit = op_isLitLike (left);
9099         poc = lit ? POC_MOVLW : POC_MOVFW;
9100
9101         if (IS_BITFIELD(getSpec(operandType(result))))
9102         {
9103                 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9104                 goto release;
9105         }
9106
9107         {
9108                 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9109                 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9110                 assert (size > 0 && size <= 4);
9111                 
9112                 mov2w_op(left, 0);
9113                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9114                 mov2w_op(left, 1);
9115                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9116                 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9117                 call_libraryfunc (func[size]);
9118
9119                 movwf(AOP(result),size-1);
9120                 for (i = 1; i < size; i++)
9121                 {
9122                         emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9123                         movwf(AOP(result),size - 1 - i);
9124                 } // for
9125         }
9126         
9127 release:
9128         freeAsmop(left,NULL,ic,TRUE);
9129         freeAsmop(result,NULL,ic,TRUE);
9130         
9131 }
9132 /*-----------------------------------------------------------------*/
9133 /* genPointerGet - generate code for pointer get                   */
9134 /*-----------------------------------------------------------------*/
9135 static void genPointerGet (iCode *ic)
9136 {
9137         operand *left, *result ;
9138         sym_link *type, *etype;
9139         int p_type = -1;
9140         
9141         FENTRY;
9142         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9143         
9144         left = IC_LEFT(ic);
9145         result = IC_RESULT(ic) ;
9146         
9147         /* depending on the type of pointer we need to
9148         move it to the correct pointer register */
9149         type = operandType(left);
9150         etype = getSpec(type);
9151         
9152         if (IS_PTR_CONST(type))
9153                 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9154         
9155         /* if left is of type of pointer then it is simple */
9156         if (IS_PTR(type) && !IS_FUNC(type->next)) 
9157                 p_type = DCL_TYPE(type);
9158         else {
9159                 /* we have to go by the storage class */
9160                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9161                 
9162                 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9163                 
9164                 if (SPEC_OCLS(etype)->codesp ) {
9165                         DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9166                         //p_type = CPOINTER ; 
9167                 }
9168                 else
9169                         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9170                                 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9171                         /*p_type = FPOINTER ;*/ 
9172                         else
9173                                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9174                                         DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9175                                 /*        p_type = PPOINTER; */
9176                                 else
9177                                         if (SPEC_OCLS(etype) == idata )
9178                                                 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9179                                         /*      p_type = IPOINTER; */
9180                                         else
9181                                                 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9182                                         /*      p_type = POINTER ; */
9183         }
9184         
9185         /* now that we have the pointer type we assign
9186         the pointer values */
9187         switch (p_type) {
9188                 
9189         case POINTER: 
9190         case FPOINTER:
9191         //case IPOINTER:
9192                 genNearPointerGet (left,result,ic);
9193                 break;
9194 /*
9195         case PPOINTER:
9196                 genPagedPointerGet(left,result,ic);
9197                 break;
9198                 
9199         case FPOINTER:
9200                 genFarPointerGet (left,result,ic);
9201                 break;
9202 */              
9203         case CPOINTER:
9204                 genConstPointerGet (left,result,ic);
9205                 break;
9206                 
9207         case GPOINTER:
9208                 genGenPointerGet (left,result,ic);
9209                 break;
9210         default:
9211                 assert ( !"unhandled pointer type" );
9212                 break;
9213         }
9214         
9215 }
9216
9217 /*-----------------------------------------------------------------*/
9218 /* genPackBits - generates code for packed bit storage             */
9219 /*-----------------------------------------------------------------*/
9220 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9221 {
9222   int blen;             /* bitfield length */
9223   int bstr;             /* bitfield starting bit within byte */
9224   int litval;           /* source literal value (if AOP_LIT) */
9225   unsigned char mask;   /* bitmask within current byte */
9226
9227   FENTRY;
9228   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9229
9230   blen = SPEC_BLEN (etype);
9231   bstr = SPEC_BSTR (etype);
9232
9233   /* If the bitfield length is less than a byte and does not cross byte boundaries */
9234   if ((blen <= 8) && ((bstr + blen) <= 8))
9235   {
9236     mask = ((unsigned char) (0xFF << (blen + bstr)) |
9237             (unsigned char) (0xFF >> (8 - bstr)));
9238
9239     if (AOP_TYPE (right) == AOP_LIT)
9240     {
9241       /* Case with a bitfield length <8 and literal source */
9242       int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9243       if (blen == 1) {
9244         pCodeOp *pcop;
9245         
9246         switch (p_type)
9247         {
9248         case -1:
9249           if (AOP(result)->type == AOP_PCODE)
9250             pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9251           else
9252             pcop = popGet(AOP(result),0);
9253           emitpcode(lit?POC_BSF:POC_BCF,pcop);
9254           break;
9255         
9256         case POINTER:
9257         case FPOINTER:
9258           setup_fsr (result);
9259           emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9260           break;
9261         
9262         case CPOINTER:
9263           assert( !"trying to assign to bitfield via pointer to __code space" );
9264           break;
9265         
9266         case GPOINTER:
9267           emitPtrByteGet(result, p_type, FALSE);
9268           if (lit) {
9269             emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9270           } else {
9271             emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9272           }
9273           emitPtrByteSet(result, p_type, TRUE);
9274           break;
9275         
9276         default:
9277           assert( !"unhandled pointer type" );
9278           break;
9279         } // switch (p_type)
9280       } else {
9281         /* blen > 1 */
9282         litval = lit << bstr;
9283         litval &= (~mask) & 0x00ff;
9284         
9285         switch (p_type)
9286         {
9287         case -1:
9288           mov2w (AOP(result), 0);
9289           if ((litval|mask) != 0x00ff)
9290             emitpcode(POC_ANDLW, popGetLit (mask));
9291           if (litval != 0x00)
9292             emitpcode(POC_IORLW, popGetLit (litval));
9293           movwf (AOP(result), 0);
9294           break;
9295         
9296         case POINTER:
9297         case FPOINTER:
9298         case GPOINTER:
9299           emitPtrByteGet(result, p_type, FALSE);
9300           if ((litval|mask) != 0x00ff)
9301             emitpcode(POC_ANDLW, popGetLit (mask));
9302           if (litval != 0x00)
9303             emitpcode(POC_IORLW, popGetLit (litval));
9304           emitPtrByteSet(result, p_type, TRUE);
9305           break;
9306         
9307         case CPOINTER:
9308           assert( !"trying to assign to bitfield via pointer to __code space" );
9309           break;
9310         
9311         default:
9312           assert( !"unhandled pointer type" );
9313           break;
9314         } // switch
9315       } // if (blen > 1)
9316     }
9317     else
9318     {
9319       /* right is no literal */
9320       if (blen==1) {
9321         switch (p_type)
9322         {
9323         case -1:
9324           /* Note more efficient code, of pre clearing bit then only setting it if required,
9325            * can only be done if it is known that the result is not a SFR */
9326           emitpcode(POC_RRFW,popGet(AOP(right),0));
9327           emitSKPC;
9328           emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9329           emitSKPNC;
9330           emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9331           break;
9332         
9333         case POINTER:
9334         case FPOINTER:
9335         case GPOINTER:
9336           emitPtrByteGet (result, p_type, FALSE);
9337           emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9338           emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9339           emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9340           emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9341           emitPtrByteSet (result, p_type, TRUE);
9342           break;
9343         
9344         case CPOINTER:
9345           assert( !"trying to assign to bitfield via pointer to __code space" );
9346           break;
9347         
9348         default:
9349           assert( !"unhandled pointer type" );
9350           break;
9351         } // switch
9352         return;
9353       } else {
9354         /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9355         pCodeOp *temp = popGetTempReg ();
9356
9357         mov2w (AOP(right), 0);
9358         if (blen < 8) {
9359           emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9360         }
9361         emitpcode(POC_MOVWF, temp);
9362         if (bstr) {
9363           AccLsh (temp, bstr);
9364         }
9365         
9366         switch (p_type)
9367         {
9368         case -1:
9369           mov2w (AOP(result), 0);
9370           emitpcode(POC_ANDLW, popGetLit (mask));
9371           emitpcode(POC_IORFW, temp);
9372           movwf (AOP(result), 0);
9373           break;
9374         
9375         case POINTER:
9376         case FPOINTER:
9377         case GPOINTER:
9378           emitPtrByteGet (result, p_type, FALSE);
9379           emitpcode(POC_ANDLW, popGetLit (mask));
9380           emitpcode(POC_IORFW, temp);
9381           emitPtrByteSet (result, p_type, TRUE);
9382           break;
9383         
9384         case CPOINTER:
9385           assert( !"trying to assign to bitfield via pointer to __code space" );
9386           break;
9387         
9388         default:
9389           assert( !"unhandled pointer type" );
9390           break;
9391         } // switch
9392
9393         popReleaseTempReg (temp);
9394       } // if (blen > 1)
9395     } // if (AOP(right)->type != AOP_LIT)
9396     return;
9397   } // if (blen <= 8 && ((blen + bstr) <= 8))
9398
9399   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9400 }
9401
9402 /*-----------------------------------------------------------------*/
9403 /* genDataPointerSet - remat pointer to data space                 */
9404 /*-----------------------------------------------------------------*/
9405 static void genDataPointerSet(operand *right,
9406         operand *result,
9407         iCode *ic)
9408 {
9409         int size, offset = 0 ;
9410         int ressize;
9411         
9412         FENTRY;
9413         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9414         aopOp(right,ic,FALSE);
9415         aopOp(result,ic,FALSE);
9416         
9417         assert (IS_SYMOP(result));
9418         assert (IS_PTR(OP_SYM_TYPE(result)));
9419         
9420         if (AOP_TYPE(right) == AOP_LIT)
9421           size = 4;
9422         else
9423           size = AOP_SIZE(right);
9424         ressize = getSize(OP_SYM_ETYPE(result));
9425         if (size > ressize) size = ressize;
9426         //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9427         
9428         //assert( !"what's going on here?" );
9429
9430         /*
9431         if ( AOP_TYPE(result) == AOP_PCODE) {
9432         fprintf(stderr,"genDataPointerSet   %s, %d\n",
9433         AOP(result)->aopu.pcop->name,
9434         PCOI(AOP(result)->aopu.pcop)->offset);
9435         }
9436         */
9437         
9438         // tsd, was l+1 - the underline `_' prefix was being stripped
9439         while (size--) {
9440                 emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
9441                 
9442                 if (AOP_TYPE(right) == AOP_LIT) {
9443                         unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
9444                         //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9445                         if(lit&0xff) {
9446                                 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9447                                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9448                         } else {
9449                                 emitpcode(POC_CLRF, popGet(AOP(result), offset));
9450                         }
9451                 } else {
9452                         //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9453                         emitpcode(POC_MOVFW, popGet(AOP(right), offset));
9454                         emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9455                 }
9456                 
9457                 offset++;
9458         }
9459         
9460         freeAsmop(right,NULL,ic,TRUE);
9461         freeAsmop(result,NULL,ic,TRUE);
9462 }
9463
9464 /*-----------------------------------------------------------------*/
9465 /* genNearPointerSet - pic14_emitcode for near pointer put         */
9466 /*-----------------------------------------------------------------*/
9467 static void genNearPointerSet (operand *right,
9468                                                            operand *result, 
9469                                                            iCode *ic)
9470 {
9471         asmop *aop = NULL;
9472         sym_link *ptype = operandType(result);
9473         sym_link *retype = getSpec(operandType(right));
9474         sym_link *letype = getSpec(ptype);
9475         int direct = 0;
9476         
9477         
9478         FENTRY;
9479         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9480         aopOp(result,ic,FALSE);
9481         
9482 #if 1
9483         /* if the result is rematerializable &
9484         in data space & not a bit variable */
9485         //if (AOP_TYPE(result) == AOP_IMMD &&
9486         if (AOP_TYPE(result) == AOP_PCODE &&
9487                 PIC_IS_DATA_PTR(ptype) &&
9488                 !IS_BITVAR (retype) &&
9489                 !IS_BITVAR (letype)) {
9490                 genDataPointerSet (right,result,ic);
9491                 freeAsmop(result,NULL,ic,TRUE);
9492                 return;
9493         }
9494 #endif
9495
9496         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9497         aopOp(right,ic,FALSE);
9498         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9499         
9500         /* Check if can access directly instead of via a pointer */
9501         if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9502                 direct = 1;
9503         }
9504         
9505         if (IS_BITFIELD (letype))
9506         {
9507           genPackBits (letype, result, right, direct?-1:POINTER);
9508           return;
9509         }
9510         
9511         /* If the pointer value is not in a the FSR then need to put it in */
9512         /* Must set/reset IRP bit for use with FSR. */
9513         /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9514         if (!direct)
9515                 setup_fsr (result);
9516
9517         {
9518                 /* we have can just get the values */
9519                 int size = AOP_SIZE(right);
9520                 int offset = 0 ;    
9521                 
9522                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9523                 while (size--) {
9524                         char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9525                         if (*l == '@' ) {
9526                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9527                         } else {
9528                                 if (AOP_TYPE(right) == AOP_LIT) {
9529                                         emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9530                                 } else {
9531                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9532                                 }
9533                                 if (direct)
9534                                         emitpcode(POC_MOVWF,popGet(AOP(result),0));
9535                                 else
9536                                         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9537                         }
9538                         if (size && !direct)
9539                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9540                         offset++;
9541                 }
9542         }
9543         
9544         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9545         /* now some housekeeping stuff */
9546         if (aop) {
9547                 /* we had to allocate for this iCode */
9548                 freeAsmop(NULL,aop,ic,TRUE);
9549         } else { 
9550                 /* we did not allocate which means left
9551                 already in a pointer register, then
9552                 if size > 0 && this could be used again
9553                 we have to point it back to where it 
9554                 belongs */
9555                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9556                 if (AOP_SIZE(right) > 1 &&
9557                         !OP_SYMBOL(result)->remat &&
9558                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9559                         ic->depth )) {
9560                         int size = AOP_SIZE(right) - 1;
9561                         while (size--)
9562                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9563                 }
9564         }
9565         
9566         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9567         /* done */
9568
9569         freeAsmop(right,NULL,ic,TRUE);
9570         freeAsmop(result,NULL,ic,TRUE);
9571 }
9572
9573 #if 0
9574 /*-----------------------------------------------------------------*/
9575 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
9576 /*-----------------------------------------------------------------*/
9577 static void genPagedPointerSet (operand *right,
9578                                                                 operand *result, 
9579                                                                 iCode *ic)
9580 {
9581         asmop *aop = NULL;
9582         regs *preg = NULL ;
9583         char *rname , *l;
9584         sym_link *retype;
9585         
9586         FENTRY;
9587         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9588         
9589         retype= getSpec(operandType(right));
9590         
9591         aopOp(result,ic,FALSE);
9592         
9593         /* if the value is already in a pointer register
9594         then don't need anything more */
9595         if (!AOP_INPREG(AOP(result))) {
9596                 /* otherwise get a free pointer register */
9597                 aop = newAsmop(0);
9598                 preg = getFreePtr(ic,&aop,FALSE);
9599                 pic14_emitcode("mov","%s,%s",
9600                         preg->name,
9601                         aopGet(AOP(result),0,FALSE,TRUE));
9602                 rname = preg->name ;
9603         } else
9604                 rname = aopGet(AOP(result),0,FALSE,FALSE);
9605         
9606         freeAsmop(result,NULL,ic,TRUE);
9607         aopOp (right,ic,FALSE);
9608         
9609         /* if bitfield then unpack the bits */
9610         if (IS_BITFIELD(retype)) 
9611                 genPackBits (retype,result,right,rname,PPOINTER);
9612         else {
9613                 /* we have can just get the values */
9614                 int size = AOP_SIZE(right);
9615                 int offset = 0 ;  
9616                 
9617                 while (size--) {
9618                         l = aopGet(AOP(right),offset,FALSE,TRUE);
9619                         
9620                         MOVA(l);
9621                         pic14_emitcode("movx","@%s,a",rname);
9622                         
9623                         if (size)
9624                                 pic14_emitcode("inc","%s",rname);
9625                         
9626                         offset++;
9627                 }
9628         }
9629         
9630         /* now some housekeeping stuff */
9631         if (aop) {
9632                 /* we had to allocate for this iCode */
9633                 freeAsmop(NULL,aop,ic,TRUE);
9634         } else { 
9635         /* we did not allocate which means left
9636         already in a pointer register, then
9637         if size > 0 && this could be used again
9638         we have to point it back to where it 
9639                 belongs */
9640                 if (AOP_SIZE(right) > 1 &&
9641                         !OP_SYMBOL(result)->remat &&
9642                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9643                         ic->depth )) {
9644                         int size = AOP_SIZE(right) - 1;
9645                         while (size--)
9646                                 pic14_emitcode("dec","%s",rname);
9647                 }
9648         }
9649         
9650         /* done */
9651         freeAsmop(right,NULL,ic,TRUE);
9652         
9653         
9654 }
9655
9656 /*-----------------------------------------------------------------*/
9657 /* genFarPointerSet - set value from far space                     */
9658 /*-----------------------------------------------------------------*/
9659 static void genFarPointerSet (operand *right,
9660                                                           operand *result, iCode *ic)
9661 {
9662         int size, offset ;
9663         sym_link *retype = getSpec(operandType(right));
9664         
9665         FENTRY;
9666         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9667         aopOp(result,ic,FALSE);
9668         
9669         /* if the operand is already in dptr 
9670         then we do nothing else we move the value to dptr */
9671         if (AOP_TYPE(result) != AOP_STR) {
9672                 /* if this is remateriazable */
9673                 if (AOP_TYPE(result) == AOP_IMMD)
9674                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9675                 else { /* we need to get it byte by byte */
9676                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9677                         pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9678                         if (options.model == MODEL_FLAT24)
9679                         {
9680                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9681                         }
9682                 }
9683         }
9684         /* so dptr know contains the address */
9685         freeAsmop(result,NULL,ic,TRUE);
9686         aopOp(right,ic,FALSE);
9687         
9688         /* if bit then unpack */
9689         if (IS_BITFIELD(retype)) 
9690                 genPackBits(retype,result,right,"dptr",FPOINTER);
9691         else {
9692                 size = AOP_SIZE(right);
9693                 offset = 0 ;
9694                 
9695                 while (size--) {
9696                         char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9697                         MOVA(l);
9698                         pic14_emitcode("movx","@dptr,a");
9699                         if (size)
9700                                 pic14_emitcode("inc","dptr");
9701                 }
9702         }
9703         
9704         freeAsmop(right,NULL,ic,TRUE);
9705 }
9706 #endif
9707
9708 /*-----------------------------------------------------------------*/
9709 /* genGenPointerSet - set value from generic pointer space         */
9710 /*-----------------------------------------------------------------*/
9711 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9712 {
9713         sym_link *retype = getSpec(operandType(result));
9714         
9715         FENTRY;
9716         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9717         aopOp(right,ic,FALSE);
9718         aopOp(result,ic,FALSE);
9719
9720         
9721         DEBUGpic14_AopType(__LINE__,right,NULL,result);
9722
9723         if (IS_BITFIELD(retype))
9724         {
9725           genPackBits (retype, result, right, GPOINTER);
9726           return;
9727         }
9728
9729         {
9730           /* emit call to __gptrput */
9731           char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9732           int size = AOP_SIZE(right);
9733           int idx = 0;
9734
9735           assert (size == getSize(OP_SYM_ETYPE(result)));
9736           assert (size > 0 && size <= 4);
9737
9738           /* pass arguments */
9739           /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9740           {
9741             int off = size;
9742             idx = 2;
9743             while (off--)
9744             {
9745               mov2w_op (right, off);
9746               emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9747             }
9748             idx = 0;
9749           }
9750           /* - address */
9751           assert (AOP_SIZE(result) == 3);
9752           mov2w(AOP(result), 0);
9753           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9754           mov2w(AOP(result), 1);
9755           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9756           mov2w(AOP(result), 2);
9757           call_libraryfunc (func[size]);
9758         }
9759         
9760         freeAsmop(right,NULL,ic,TRUE);
9761         freeAsmop(result,NULL,ic,TRUE);
9762 }
9763
9764 /*-----------------------------------------------------------------*/
9765 /* genPointerSet - stores the value into a pointer location        */
9766 /*-----------------------------------------------------------------*/
9767 static void genPointerSet (iCode *ic)
9768 {    
9769         operand *right, *result ;
9770         sym_link *type, *etype;
9771         int p_type;
9772         
9773         FENTRY;
9774         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9775         
9776         right = IC_RIGHT(ic);
9777         result = IC_RESULT(ic) ;
9778         
9779         /* depending on the type of pointer we need to
9780         move it to the correct pointer register */
9781         type = operandType(result);
9782         etype = getSpec(type);
9783         /* if left is of type of pointer then it is simple */
9784         if (IS_PTR(type) && !IS_FUNC(type->next)) {
9785                 p_type = DCL_TYPE(type);
9786         }
9787         else {
9788                 /* we have to go by the storage class */
9789                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9790                 
9791                 /*  if (SPEC_OCLS(etype)->codesp ) { */
9792                 /*      p_type = CPOINTER ;  */
9793                 /*  } */
9794                 /*  else */
9795                 /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9796                 /*    p_type = FPOINTER ; */
9797                 /*      else */
9798                 /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9799                 /*        p_type = PPOINTER ; */
9800                 /*    else */
9801                 /*        if (SPEC_OCLS(etype) == idata ) */
9802                 /*      p_type = IPOINTER ; */
9803                 /*        else */
9804                 /*      p_type = POINTER ; */
9805         }
9806         
9807         /* now that we have the pointer type we assign
9808         the pointer values */
9809         switch (p_type) {
9810                 
9811         case POINTER:
9812         case FPOINTER:
9813         //case IPOINTER:
9814                 genNearPointerSet (right,result,ic);
9815                 break;
9816 /*
9817         case PPOINTER:
9818                 genPagedPointerSet (right,result,ic);
9819                 break;
9820                 
9821         case FPOINTER:
9822                 genFarPointerSet (right,result,ic);
9823                 break;
9824 */
9825         case GPOINTER:
9826                 genGenPointerSet (right,result,ic);
9827                 break;
9828                 
9829         default:
9830                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9831                         "genPointerSet: illegal pointer type");
9832         }
9833 }
9834
9835 /*-----------------------------------------------------------------*/
9836 /* genIfx - generate code for Ifx statement                        */
9837 /*-----------------------------------------------------------------*/
9838 static void genIfx (iCode *ic, iCode *popIc)
9839 {
9840         operand *cond = IC_COND(ic);
9841         int isbit =0;
9842         
9843         FENTRY;
9844         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9845         
9846         aopOp(cond,ic,FALSE);
9847         
9848         /* get the value into acc */
9849         if (AOP_TYPE(cond) != AOP_CRY)
9850                 pic14_toBoolean(cond);
9851         else
9852                 isbit = 1;
9853         
9854         /* if there was something to be popped then do it */
9855         if (popIc)
9856                 genIpop(popIc);
9857         
9858         if (isbit)
9859         {
9860                 /* This assumes that CARRY is set iff cond is true */
9861                 if (IC_TRUE(ic))
9862                 {
9863                         assert (!IC_FALSE(ic));
9864                         emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9865                         //emitSKPNC;
9866                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9867                 } else {
9868                         assert (IC_FALSE(ic));
9869                         emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9870                         //emitSKPC;
9871                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9872                 }
9873                 if (0)
9874                 {
9875                         static int hasWarned = 0;
9876                         if (!hasWarned)
9877                         {
9878                                 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9879                                 hasWarned = 1;
9880                         }
9881                 }
9882         }
9883         else
9884         {
9885                 /* now Z is set iff !cond */
9886                 if (IC_TRUE(ic))
9887                 {
9888                         assert (!IC_FALSE(ic));
9889                         emitSKPZ;
9890                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9891                 } else {
9892                         emitSKPNZ;
9893                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9894                 }
9895         }
9896         
9897         ic->generated = 1;
9898         
9899         /* the result is now in the accumulator */
9900         freeAsmop(cond,NULL,ic,TRUE);
9901 }
9902
9903 /*-----------------------------------------------------------------*/
9904 /* genAddrOf - generates code for address of                       */
9905 /*-----------------------------------------------------------------*/
9906 static void genAddrOf (iCode *ic)
9907 {
9908         operand *right, *result, *left;
9909         int size, offset ;
9910         
9911         FENTRY;
9912         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9913         
9914         
9915         //aopOp(IC_RESULT(ic),ic,FALSE);
9916         
9917         aopOp((left=IC_LEFT(ic)),ic,FALSE);
9918         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9919         aopOp((result=IC_RESULT(ic)),ic,TRUE);
9920         
9921         DEBUGpic14_AopType(__LINE__,left,right,result);
9922         assert (IS_SYMOP (left));
9923         
9924         /* sanity check: generic pointers to code space are not yet supported,
9925          * pionters to codespace must not be assigned addresses of __data values. */
9926  #if 0
9927         fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9928         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)));
9929         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)));
9930         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)));
9931         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)));
9932 #endif
9933
9934         if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9935           fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9936                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9937                 OP_SYMBOL(left)->name);
9938         } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9939           fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9940                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9941                 OP_SYMBOL(left)->name);
9942         }
9943         
9944         size = AOP_SIZE(IC_RESULT(ic));
9945         if (IS_GENPTR(OP_SYM_TYPE(result))) {
9946                 /* strip tag */
9947                 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9948         }
9949         offset = 0;
9950         
9951         while (size--) {
9952                 /* fixing bug #863624, reported from (errolv) */
9953                 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9954                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9955                 
9956 #if 0
9957                 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9958                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9959 #endif
9960                 offset++;
9961         }
9962
9963         if (IS_GENPTR(OP_SYM_TYPE(result)))
9964         {
9965                 /* provide correct tag */
9966                 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9967                 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9968                 movwf (AOP(result), 2);
9969         }
9970         
9971         freeAsmop(left,NULL,ic,FALSE);
9972         freeAsmop(result,NULL,ic,TRUE);
9973         
9974 }
9975
9976 #if 0
9977 /*-----------------------------------------------------------------*/
9978 /* genFarFarAssign - assignment when both are in far space         */
9979 /*-----------------------------------------------------------------*/
9980 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9981 {
9982         int size = AOP_SIZE(right);
9983         int offset = 0;
9984         char *l ;
9985         /* first push the right side on to the stack */
9986         while (size--) {
9987                 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9988                 MOVA(l);
9989                 pic14_emitcode ("push","acc");
9990         }
9991         
9992         freeAsmop(right,NULL,ic,FALSE);
9993         /* now assign DPTR to result */
9994         aopOp(result,ic,FALSE);
9995         size = AOP_SIZE(result);
9996         while (size--) {
9997                 pic14_emitcode ("pop","acc");
9998                 aopPut(AOP(result),"a",--offset);
9999         }
10000         freeAsmop(result,NULL,ic,FALSE);
10001         
10002 }
10003 #endif
10004
10005 /*-----------------------------------------------------------------*/
10006 /* genAssign - generate code for assignment                        */
10007 /*-----------------------------------------------------------------*/
10008 static void genAssign (iCode *ic)
10009 {
10010         operand *result, *right;
10011         int size, offset,know_W;
10012         unsigned long lit = 0L;
10013         
10014         result = IC_RESULT(ic);
10015         right  = IC_RIGHT(ic) ;
10016         
10017         FENTRY;
10018         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10019         
10020         /* if they are the same */
10021         if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10022                 return ;
10023         
10024         aopOp(right,ic,FALSE);
10025         aopOp(result,ic,TRUE);
10026         
10027         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10028         
10029         /* if they are the same registers */
10030         if (pic14_sameRegs(AOP(right),AOP(result)))
10031                 goto release;
10032
10033         /* special case: assign from __code */
10034         if (!IS_ITEMP(right)                            /* --> iTemps never reside in __code */
10035                 && IS_SYMOP (right)                     /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
10036                 && !IS_FUNC(OP_SYM_TYPE(right))         /* --> we would want its address instead of the first instruction */
10037                 && !IS_CODEPTR(OP_SYM_TYPE(right))      /* --> get symbols address instread */
10038                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
10039         {
10040           emitpComment ("genAssign from CODESPACE");
10041           genConstPointerGet (right, result, ic);
10042           goto release;
10043         }
10044         
10045         /* just for symmetry reasons... */
10046         if (!IS_ITEMP(result)
10047                 && IS_SYMOP (result)
10048                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
10049         {
10050           assert ( !"cannot write to CODESPACE" );
10051         }
10052
10053         /* if the result is a bit */
10054         if (AOP_TYPE(result) == AOP_CRY) {
10055                 
10056         /* if the right size is a literal then
10057                 we know what the value is */
10058                 if (AOP_TYPE(right) == AOP_LIT) {
10059                         
10060                         emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10061                                 popGet(AOP(result),0));
10062                         
10063                         if (((int) operandLitValue(right))) 
10064                                 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10065                                 AOP(result)->aopu.aop_dir,
10066                                 AOP(result)->aopu.aop_dir);
10067                         else
10068                                 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10069                                 AOP(result)->aopu.aop_dir,
10070                                 AOP(result)->aopu.aop_dir);
10071                         goto release;
10072                 }
10073                 
10074                 /* the right is also a bit variable */
10075                 if (AOP_TYPE(right) == AOP_CRY) {
10076                         emitpcode(POC_BCF,    popGet(AOP(result),0));
10077                         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10078                         emitpcode(POC_BSF,    popGet(AOP(result),0));
10079                         
10080                         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10081                                 AOP(result)->aopu.aop_dir,
10082                                 AOP(result)->aopu.aop_dir);
10083                         pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10084                                 AOP(right)->aopu.aop_dir,
10085                                 AOP(right)->aopu.aop_dir);
10086                         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10087                                 AOP(result)->aopu.aop_dir,
10088                                 AOP(result)->aopu.aop_dir);
10089                         goto release ;
10090                 }
10091                 
10092                 /* we need to or */
10093                 emitpcode(POC_BCF,    popGet(AOP(result),0));
10094                 pic14_toBoolean(right);
10095                 emitSKPZ;
10096                 emitpcode(POC_BSF,    popGet(AOP(result),0));
10097                 //aopPut(AOP(result),"a",0);
10098                 goto release ;
10099         }
10100         
10101         /* bit variables done */
10102         /* general case */
10103         size = AOP_SIZE(result);
10104         offset = 0 ;
10105         if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10106                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10107                 if(aopIdx(AOP(result),0) == 4) {
10108                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10109                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10110                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10111                         goto release;
10112                 } else
10113                         DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10114         }
10115         
10116         know_W=-1;
10117         while (size--) {
10118         
10119                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10120                 if(AOP_TYPE(right) == AOP_LIT) {
10121                         lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
10122                         if(lit&0xff) {
10123                                 if(know_W != (int)(lit&0xff))
10124                                         emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10125                                 know_W = lit&0xff;
10126                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10127                         } else
10128                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10129                         
10130                 } else if (AOP_TYPE(right) == AOP_CRY) {
10131                         emitpcode(POC_CLRF, popGet(AOP(result),offset));
10132                         if(offset == 0) {
10133                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10134                                 emitpcode(POC_INCF, popGet(AOP(result),0));
10135                         }
10136                 } else {
10137                         mov2w_op (right, offset);
10138                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10139                 }
10140                 
10141                 offset++;
10142         }
10143         
10144         
10145 release:
10146         freeAsmop (right,NULL,ic,FALSE);
10147         freeAsmop (result,NULL,ic,TRUE);
10148 }   
10149
10150 /*-----------------------------------------------------------------*/
10151 /* genJumpTab - genrates code for jump table                       */
10152 /*-----------------------------------------------------------------*/
10153 static void genJumpTab (iCode *ic)
10154 {
10155         symbol *jtab;
10156         char *l;
10157         
10158         FENTRY;
10159         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10160         
10161         aopOp(IC_JTCOND(ic),ic,FALSE);
10162         /* get the condition into accumulator */
10163         l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10164         MOVA(l);
10165         /* multiply by three */
10166         pic14_emitcode("add","a,acc");
10167         pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10168         
10169         jtab = newiTempLabel(NULL);
10170         pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10171         pic14_emitcode("jmp","@a+dptr");
10172         pic14_emitcode("","%05d_DS_:",jtab->key+100);
10173         
10174         emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10175         emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10176         emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10177         emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10178         emitSKPNC;
10179         emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10180         emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10181         emitpLabel(jtab->key);
10182         
10183         freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10184         
10185         /* now generate the jump labels */
10186         for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10187         jtab = setNextItem(IC_JTLABELS(ic))) {
10188                 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10189                 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10190                 
10191         }
10192         
10193 }
10194
10195 /*-----------------------------------------------------------------*/
10196 /* genMixedOperation - gen code for operators between mixed types  */
10197 /*-----------------------------------------------------------------*/
10198 /*
10199 TSD - Written for the PIC port - but this unfortunately is buggy.
10200 This routine is good in that it is able to efficiently promote 
10201 types to different (larger) sizes. Unfortunately, the temporary
10202 variables that are optimized out by this routine are sometimes
10203 used in other places. So until I know how to really parse the 
10204 iCode tree, I'm going to not be using this routine :(.
10205 */
10206 static int genMixedOperation (iCode *ic)
10207 {
10208         FENTRY;
10209 #if 0
10210         operand *result = IC_RESULT(ic);
10211         sym_link *ctype = operandType(IC_LEFT(ic));
10212         operand *right = IC_RIGHT(ic);
10213         int ret = 0;
10214         int big,small;
10215         int offset;
10216         
10217         iCode *nextic;
10218         operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10219         
10220         pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10221         
10222         nextic = ic->next;
10223         if(!nextic)
10224                 return 0;
10225         
10226         nextright = IC_RIGHT(nextic);
10227         nextleft  = IC_LEFT(nextic);
10228         nextresult = IC_RESULT(nextic);
10229         
10230         aopOp(right,ic,FALSE);
10231         aopOp(result,ic,FALSE);
10232         aopOp(nextright,  nextic, FALSE);
10233         aopOp(nextleft,   nextic, FALSE);
10234         aopOp(nextresult, nextic, FALSE);
10235         
10236         if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10237                 
10238                 operand *t = right;
10239                 right = nextright;
10240                 nextright = t; 
10241                 
10242                 pic14_emitcode(";remove right +","");
10243                 
10244         } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10245         /*
10246         operand *t = right;
10247         right = nextleft;
10248         nextleft = t; 
10249                 */
10250                 pic14_emitcode(";remove left +","");
10251         } else
10252                 return 0;
10253         
10254         big = AOP_SIZE(nextleft);
10255         small = AOP_SIZE(nextright);
10256         
10257         switch(nextic->op) {
10258                 
10259         case '+':
10260                 pic14_emitcode(";optimize a +","");
10261                 /* if unsigned or not an integral type */
10262                 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10263                         pic14_emitcode(";add a bit to something","");
10264                 } else {
10265                         
10266                         pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10267                         
10268                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10269                                 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10270                                 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10271                         } else
10272                                 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10273                         
10274                         offset = 0;
10275                         while(--big) {
10276                                 
10277                                 offset++;
10278                                 
10279                                 if(--small) {
10280                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10281                                                 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10282                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10283                                         }
10284                                         
10285                                         pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10286                                         emitSKPNC;
10287                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10288                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10289                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10290                                         pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10291                                         pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10292                                         
10293                                 } else {
10294                                         pic14_emitcode("rlf","known_zero,w");
10295                                         
10296                                         /*
10297                                         if right is signed
10298                                         btfsc  right,7
10299                                         addlw ff
10300                                         */
10301                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10302                                                 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10303                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10304                                         } else {
10305                                                 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10306                                         }
10307                                 }
10308                         }
10309                         ret = 1;
10310                 }
10311         }
10312         ret = 1;
10313         
10314 release:
10315         freeAsmop(right,NULL,ic,TRUE);
10316         freeAsmop(result,NULL,ic,TRUE);
10317         freeAsmop(nextright,NULL,ic,TRUE);
10318         freeAsmop(nextleft,NULL,ic,TRUE);
10319         if(ret)
10320                 nextic->generated = 1;
10321         
10322         return ret;
10323 #else
10324         return 0;
10325 #endif
10326 }
10327 /*-----------------------------------------------------------------*/
10328 /* genCast - gen code for casting                                  */
10329 /*-----------------------------------------------------------------*/
10330 static void genCast (iCode *ic)
10331 {
10332         operand *result = IC_RESULT(ic);
10333         sym_link *restype = operandType(result);
10334         sym_link *rtype = operandType(IC_RIGHT(ic));
10335         operand *right = IC_RIGHT(ic);
10336         int size, offset ;
10337         
10338         FENTRY;
10339         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10340         /* if they are equivalent then do nothing */
10341         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10342                 return ;
10343         
10344         aopOp(right,ic,FALSE) ;
10345         aopOp(result,ic,FALSE);
10346         
10347         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10348         
10349         /* if the result is a bit */
10350         if (AOP_TYPE(result) == AOP_CRY) {
10351                 assert(!"assigning to bit variables is not supported");
10352         }
10353         
10354         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10355                 int offset = 1;
10356                 size = AOP_SIZE(result);
10357                 
10358                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10359                 
10360                 emitpcode(POC_CLRF,   popGet(AOP(result),0));
10361                 emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10362                 emitpcode(POC_INCF,   popGet(AOP(result),0));
10363                 
10364                 while (size--)
10365                         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
10366                 
10367                 goto release;
10368         }
10369         
10370         if (IS_PTR(restype))
10371         {
10372           operand *result = IC_RESULT(ic);
10373           //operand *left = IC_LEFT(ic);
10374           operand *right = IC_RIGHT(ic);
10375           int tag = 0xff;
10376           
10377           /* copy common part */
10378           int max, size = AOP_SIZE(result);
10379           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10380           DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10381
10382           /* warn if we discard generic opinter tag */
10383           if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10384           {
10385             //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10386           } // if
10387
10388           max = size;
10389           while (size--)
10390           {
10391             mov2w_op (right, size);
10392             movwf (AOP(result), size);
10393           } // while
10394
10395           /* upcast into generic pointer type? */
10396           if (IS_GENPTR(restype)
10397                 && (size < AOP_SIZE(result))
10398                 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10399           {
10400             //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10401             if (IS_PTR(rtype))
10402             {
10403               switch (DCL_TYPE(rtype))
10404               {
10405               case POINTER:     /* __data */
10406               case FPOINTER:    /* __data */
10407                 assert (AOP_SIZE(right) == 2);
10408                 tag = GPTRTAG_DATA;
10409                 break;
10410
10411               case CPOINTER:    /* __code */
10412                 assert (AOP_SIZE(right) == 2);
10413                 tag = GPTRTAG_CODE;
10414                 break;
10415                 
10416               case GPOINTER:    /* unknown destination, __data or __code */
10417                 /* assume __data space (address of immediate) */
10418                 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10419                 if (AOP(right)->code)
10420                   tag = GPTRTAG_CODE;
10421                 else
10422                   tag = GPTRTAG_DATA;
10423                 break;
10424                 
10425               default:
10426                 assert (!"unhandled pointer type");
10427               } // switch
10428             } else {
10429               /* convert other values into pointers to __data space */
10430               tag = GPTRTAG_DATA;
10431             }
10432
10433             assert (AOP_SIZE(result) == 3);
10434             if (tag == 0) {
10435               emitpcode(POC_CLRF, popGet(AOP(result), 2));
10436             } else {
10437               emitpcode(POC_MOVLW, popGetLit(tag));
10438               movwf(AOP(result), 2);
10439             }
10440           } else {
10441             addSign(result, max, 0);
10442           } // if
10443           goto release;
10444         }
10445         
10446         /* if they are the same size : or less */
10447         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10448                 
10449                 /* if they are in the same place */
10450                 if (pic14_sameRegs(AOP(right),AOP(result)))
10451                         goto release;
10452                 
10453                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10454                 if (IS_PTR_CONST(rtype))
10455                         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10456                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10457                         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10458                 
10459                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10460                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10461                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
10462                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10463                         emitpcode(POC_MOVWF, popGet(AOP(result),1));
10464                         if(AOP_SIZE(result) <2)
10465                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10466                         
10467                 } else {
10468                         
10469                         /* if they in different places then copy */
10470                         size = AOP_SIZE(result);
10471                         offset = 0 ;
10472                         while (size--) {
10473                                 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10474                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10475                                 
10476                                 //aopPut(AOP(result),
10477                                 // aopGet(AOP(right),offset,FALSE,FALSE),
10478                                 // offset);
10479                                 
10480                                 offset++;
10481                         }
10482                 }
10483                 goto release;
10484         }
10485         
10486         /* so we now know that the size of destination is greater
10487         than the size of the source.
10488         Now, if the next iCode is an operator then we might be
10489         able to optimize the operation without performing a cast.
10490         */
10491         if(0 && genMixedOperation(ic)) {
10492                 /* XXX: cannot optimize: must copy regs! */
10493                 goto release;
10494         }
10495         
10496         /* we move to result for the size of source */
10497         size = AOP_SIZE(right);
10498         offset = 0 ;
10499         while (size--) {
10500                 emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
10501                 emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
10502                 offset++;
10503         }
10504
10505         addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10506
10507 release:
10508         freeAsmop(right,NULL,ic,TRUE);
10509         freeAsmop(result,NULL,ic,TRUE);
10510         
10511 }
10512
10513 /*-----------------------------------------------------------------*/
10514 /* genDjnz - generate decrement & jump if not zero instrucion      */
10515 /*-----------------------------------------------------------------*/
10516 static int genDjnz (iCode *ic, iCode *ifx)
10517 {
10518         symbol *lbl, *lbl1;
10519         FENTRY;
10520         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10521         
10522         if (!ifx)
10523                 return 0;
10524         
10525                 /* if the if condition has a false label
10526         then we cannot save */
10527         if (IC_FALSE(ifx))
10528                 return 0;
10529         
10530                 /* if the minus is not of the form 
10531         a = a - 1 */
10532         if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10533                 !IS_OP_LITERAL(IC_RIGHT(ic)))
10534                 return 0;
10535         
10536         if (operandLitValue(IC_RIGHT(ic)) != 1)
10537                 return 0;
10538         
10539                 /* if the size of this greater than one then no
10540         saving */
10541         if (getSize(operandType(IC_RESULT(ic))) > 1)
10542                 return 0;
10543         
10544         /* otherwise we can save BIG */
10545         lbl = newiTempLabel(NULL);
10546         lbl1= newiTempLabel(NULL);
10547         
10548         aopOp(IC_RESULT(ic),ic,FALSE);
10549         
10550         if (IS_AOP_PREG(IC_RESULT(ic))) {
10551                 pic14_emitcode("dec","%s",
10552                         aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10553                 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10554                 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10555         } else {  
10556                 
10557                 
10558                 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10559                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10560                 
10561                 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10562                 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10563                 
10564         }
10565         /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10566         /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10567         /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10568         /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10569         
10570         
10571         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10572         ifx->generated = 1;
10573         return 1;
10574 }
10575
10576 /*-----------------------------------------------------------------*/
10577 /* genReceive - generate code for a receive iCode                  */
10578 /*-----------------------------------------------------------------*/
10579 static void genReceive (iCode *ic)
10580 {
10581         FENTRY;
10582         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10583         
10584         if (isOperandInFarSpace(IC_RESULT(ic)) &&
10585                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10586                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10587                 
10588                 int size = getSize(operandType(IC_RESULT(ic)));
10589                 int offset =  fReturnSizePic - size;
10590                 while (size--) {
10591                         pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10592                                 fReturn[fReturnSizePic - offset - 1] : "acc"));
10593                         offset++;
10594                 }
10595                 aopOp(IC_RESULT(ic),ic,FALSE);
10596                 size = AOP_SIZE(IC_RESULT(ic));
10597                 offset = 0;
10598                 while (size--) {
10599                         pic14_emitcode ("pop","acc");
10600                         aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10601                 }
10602                 
10603         } else {
10604                 _G.accInUse++;
10605                 aopOp(IC_RESULT(ic),ic,FALSE);
10606                 _G.accInUse--;
10607                 GpsuedoStkPtr = ic->parmBytes; // address used arg on stack
10608                 assignResultValue(IC_RESULT(ic));
10609         }
10610         
10611         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10612 }
10613
10614 /*-----------------------------------------------------------------*/
10615 /* genDummyRead - generate code for dummy read of volatiles        */
10616 /*-----------------------------------------------------------------*/
10617 static void
10618 genDummyRead (iCode * ic)
10619 {
10620         FENTRY;
10621         pic14_emitcode ("; genDummyRead","");
10622         pic14_emitcode ("; not implemented","");
10623         
10624         ic = ic;
10625 }
10626
10627 /*-----------------------------------------------------------------*/
10628 /* genpic14Code - generate code for pic14 based controllers        */
10629 /*-----------------------------------------------------------------*/
10630 /*
10631 * At this point, ralloc.c has gone through the iCode and attempted
10632 * to optimize in a way suitable for a PIC. Now we've got to generate
10633 * PIC instructions that correspond to the iCode.
10634 *
10635 * Once the instructions are generated, we'll pass through both the
10636 * peep hole optimizer and the pCode optimizer.
10637 *-----------------------------------------------------------------*/
10638
10639 void genpic14Code (iCode *lic)
10640 {
10641         iCode *ic;
10642         int cln = 0;
10643         const char *cline;
10644         
10645         FENTRY;
10646         lineHead = lineCurr = NULL;
10647         
10648         pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10649         addpBlock(pb);
10650         
10651         /* if debug information required */
10652         if (options.debug && currFunc) { 
10653                 if (currFunc) {
10654                         debugFile->writeFunction (currFunc, lic);
10655                 }
10656         }
10657         
10658         
10659         for (ic = lic ; ic ; ic = ic->next ) {
10660                 
10661                 //DEBUGpic14_emitcode(";ic","");
10662                 //fprintf (stderr, "in ic loop\n");
10663                 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10664                 //ic->lineno, printCLine(ic->filename, ic->lineno));
10665                 
10666                 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10667                   cln = ic->lineno;
10668                   //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10669                   cline = printCLine (ic->filename, ic->lineno);
10670                   if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10671                   addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10672                   //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10673                 }
10674                 
10675                 if (options.iCodeInAsm) {
10676                   emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10677                 }
10678                 /* if the result is marked as
10679                 spilt and rematerializable or code for
10680                 this has already been generated then
10681                 do nothing */
10682                 if (resultRemat(ic) || ic->generated ) 
10683                         continue ;
10684                 
10685                 /* depending on the operation */
10686                 switch (ic->op) {
10687                 case '!' :
10688                         genNot(ic);
10689                         break;
10690                         
10691                 case '~' :
10692                         genCpl(ic);
10693                         break;
10694                         
10695                 case UNARYMINUS:
10696                         genUminus (ic);
10697                         break;
10698                         
10699                 case IPUSH:
10700                         genIpush (ic);
10701                         break;
10702                         
10703                 case IPOP:
10704                         /* IPOP happens only when trying to restore a 
10705                         spilt live range, if there is an ifx statement
10706                         following this pop then the if statement might
10707                         be using some of the registers being popped which
10708                         would destory the contents of the register so
10709                         we need to check for this condition and handle it */
10710                         if (ic->next            && 
10711                                 ic->next->op == IFX &&
10712                                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10713                                 genIfx (ic->next,ic);
10714                         else
10715                                 genIpop (ic);
10716                         break; 
10717                         
10718                 case CALL:
10719                         genCall (ic);
10720                         break;
10721                         
10722                 case PCALL:
10723                         genPcall (ic);
10724                         break;
10725                         
10726                 case FUNCTION:
10727                         genFunction (ic);
10728                         break;
10729                         
10730                 case ENDFUNCTION:
10731                         genEndFunction (ic);
10732                         break;
10733                         
10734                 case RETURN:
10735                         genRet (ic);
10736                         break;
10737                         
10738                 case LABEL:
10739                         genLabel (ic);
10740                         break;
10741                         
10742                 case GOTO:
10743                         genGoto (ic);
10744                         break;
10745                         
10746                 case '+' :
10747                         genPlus (ic) ;
10748                         break;
10749                         
10750                 case '-' :
10751                         if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10752                                 genMinus (ic);
10753                         break;
10754                         
10755                 case '*' :
10756                         genMult (ic);
10757                         break;
10758                         
10759                 case '/' :
10760                         genDiv (ic) ;
10761                         break;
10762                         
10763                 case '%' :
10764                         genMod (ic);
10765                         break;
10766                         
10767                 case '>' :
10768                         genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));         
10769                         break;
10770                         
10771                 case '<' :
10772                         genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10773                         break;
10774                         
10775                 case LE_OP:
10776                 case GE_OP:
10777                 case NE_OP:
10778                         
10779                         /* note these two are xlated by algebraic equivalence
10780                         during parsing SDCC.y */
10781                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10782                                 "got '>=' or '<=' shouldn't have come here");
10783                         break;  
10784                         
10785                 case EQ_OP:
10786                         genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10787                         break;      
10788                         
10789                 case AND_OP:
10790                         genAndOp (ic);
10791                         break;
10792                         
10793                 case OR_OP:
10794                         genOrOp (ic);
10795                         break;
10796                         
10797                 case '^' :
10798                         genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10799                         break;
10800                         
10801                 case '|' :
10802                         genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10803                         break;
10804                         
10805                 case BITWISEAND:
10806                         genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10807                         break;
10808                         
10809                 case INLINEASM:
10810                         genInline (ic);
10811                         break;
10812                         
10813                 case RRC:
10814                         genRRC (ic);
10815                         break;
10816                         
10817                 case RLC:
10818                         genRLC (ic);
10819                         break;
10820                         
10821                 case GETHBIT:
10822                         genGetHbit (ic);
10823                         break;
10824                         
10825                 case LEFT_OP:
10826                         genLeftShift (ic);
10827                         break;
10828                         
10829                 case RIGHT_OP:
10830                         genRightShift (ic);
10831                         break;
10832                         
10833                 case GET_VALUE_AT_ADDRESS:
10834                         genPointerGet(ic);
10835                         break;
10836                         
10837                 case '=' :
10838                         if (POINTER_SET(ic))
10839                                 genPointerSet(ic);
10840                         else
10841                                 genAssign(ic);
10842                         break;
10843                         
10844                 case IFX:
10845                         genIfx (ic,NULL);
10846                         break;
10847                         
10848                 case ADDRESS_OF:
10849                         genAddrOf (ic);
10850                         break;
10851                         
10852                 case JUMPTABLE:
10853                         genJumpTab (ic);
10854                         break;
10855                         
10856                 case CAST:
10857                         genCast (ic);
10858                         break;
10859                         
10860                 case RECEIVE:
10861                         genReceive(ic);
10862                         break;
10863                         
10864                 case SEND:
10865                         addSet(&_G.sendSet,ic);
10866                         break;
10867                         
10868                 case DUMMY_READ_VOLATILE:
10869                         genDummyRead (ic);
10870                         break;
10871                         
10872                 default :
10873                         fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10874                         ic = ic;
10875                         break;
10876                 }
10877         }
10878
10879         
10880         /* now we are ready to call the
10881         peep hole optimizer */
10882         if (!options.nopeep) {
10883                 peepHole (&lineHead);
10884         }
10885         /* now do the actual printing */
10886         printLine (lineHead,codeOutFile);
10887         
10888 #ifdef PCODE_DEBUG
10889         DFPRINTF((stderr,"printing pBlock\n\n"));
10890         printpBlock(stdout,pb);
10891 #endif
10892         
10893         return;
10894 }
10895
10896 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10897  * (meaning: representing its own address) or not (referencing its contents).
10898  * This can only be decided based on the operand's type. */
10899 int
10900 aop_isLitLike (asmop *aop)
10901 {
10902   assert (aop);
10903   if (aop->type == AOP_LIT) return 1;
10904 if (aop->type == AOP_IMMD) return 1;
10905   if ((aop->type == AOP_PCODE) &&
10906                 ((aop->aopu.pcop->type == PO_LITERAL)))
10907   {
10908     /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10909      * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10910     return 1;
10911   }
10912   return 0;
10913 }
10914
10915 int
10916 op_isLitLike (operand *op)
10917 {
10918   assert (op);
10919   if (aop_isLitLike (AOP(op))) return 1;
10920   if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10921   if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;
10922   return 0;
10923 }