* src/SDCCpeeph.c: made labelHashEntry global, made pcDistance, FBYNAME static,
[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         char *lbp = 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         lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
326         
327         if(debug_verbose)
328                 addpCode2pBlock(pb,newpCodeCharP(lb));
329         
330         va_end(ap);
331 }
332
333 /*-----------------------------------------------------------------*/
334 /* pic14_emitDebuggerSymbol - associate the current code location  */
335 /*       with a debugger symbol                                                                            */
336 /*-----------------------------------------------------------------*/
337 void
338 pic14_emitDebuggerSymbol (char * debugSym)
339 {
340         _G.debugLine = 1;
341         pic14_emitcode ("", ";%s ==.", debugSym);
342         _G.debugLine = 0;
343 }
344
345 #if 0
346 /*-----------------------------------------------------------------*/
347 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
348 /*-----------------------------------------------------------------*/
349 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
350 {
351         bool r0iu = FALSE , r1iu = FALSE;
352         bool r0ou = FALSE , r1ou = FALSE;
353         
354         /* the logic: if r0 & r1 used in the instruction
355         then we are in trouble otherwise */
356         
357         /* first check if r0 & r1 are used by this
358         instruction, in which case we are in trouble */
359         if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
360                 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
361         {
362                 goto endOfWorld;          
363         }
364         
365         r0ou = bitVectBitValue(ic->rMask,R0_IDX);
366         r1ou = bitVectBitValue(ic->rMask,R1_IDX);
367         
368         /* if no usage of r0 then return it */
369         if (!r0iu && !r0ou) {
370                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
371                 (*aopp)->type = AOP_R0;
372                 
373                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
374         }
375         
376         /* if no usage of r1 then return it */
377         if (!r1iu && !r1ou) {
378                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
379                 (*aopp)->type = AOP_R1;
380                 
381                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
382         }    
383         
384         /* now we know they both have usage */
385         /* if r0 not used in this instruction */
386         if (!r0iu) {
387                 /* push it if not already pushed */
388                 if (!_G.r0Pushed) {
389                         //pic14_emitcode ("push","%s",
390                         //                pic14_regWithIdx(R0_IDX)->dname);
391                         _G.r0Pushed++ ;
392                 }
393                 
394                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
395                 (*aopp)->type = AOP_R0;
396                 
397                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
398         }
399         
400         /* if r1 not used then */
401         
402         if (!r1iu) {
403                 /* push it if not already pushed */
404                 if (!_G.r1Pushed) {
405                         //pic14_emitcode ("push","%s",
406                         //                pic14_regWithIdx(R1_IDX)->dname);
407                         _G.r1Pushed++ ;
408                 }
409                 
410                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
411                 (*aopp)->type = AOP_R1;
412                 return pic14_regWithIdx(R1_IDX);
413         }
414         
415 endOfWorld :
416         /* I said end of world but not quite end of world yet */
417         /* if this is a result then we can push it on the stack*/
418         if (result) {
419                 (*aopp)->type = AOP_STK;        
420                 return NULL;
421         }
422         
423         /* other wise this is true end of the world */
424         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
425                 "getFreePtr should never reach here");
426         exit(0);
427 }
428 #endif
429
430 /*-----------------------------------------------------------------*/
431 /* newAsmop - creates a new asmOp                                                                  */
432 /*-----------------------------------------------------------------*/
433 asmop *newAsmop (short type)
434 {
435         asmop *aop;
436         
437         aop = Safe_calloc(1,sizeof(asmop));
438         aop->type = type;
439         return aop;
440 }
441
442 static void genSetDPTR(int n)
443 {
444         if (!n)
445         {
446                 pic14_emitcode(";", "Select standard DPTR");
447                 pic14_emitcode("mov", "dps, #0x00");
448         }
449         else
450         {
451                 pic14_emitcode(";", "Select alternate DPTR");
452                 pic14_emitcode("mov", "dps, #0x01");
453         }
454 }
455
456 /*-----------------------------------------------------------------*/
457 /* resolveIfx - converts an iCode ifx into a form more useful for  */
458 /*                              generating code                                                                    */
459 /*-----------------------------------------------------------------*/
460 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
461 {
462         if(!resIfx) 
463                 return;
464         
465         //  DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
466         
467         resIfx->condition = 1;  /* assume that the ifx is true */
468         resIfx->generated = 0;  /* indicate that the ifx has not been used */
469         
470         if(!ifx) {
471                 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL);      / * oops, there is no ifx. so create a label */
472                                                                                         /*
473                                                                                         DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
474                                                                                         __FUNCTION__,__LINE__,resIfx->lbl->key);
475                 */
476         } else {
477                 if(IC_TRUE(ifx)) {
478                         resIfx->lbl = IC_TRUE(ifx);
479                 } else {
480                         resIfx->lbl = IC_FALSE(ifx);
481                         resIfx->condition = 0;
482                 }
483                 /*
484                 if(IC_TRUE(ifx)) 
485                 DEBUGpic14_emitcode("; ***","ifx true is non-null");
486                 if(IC_FALSE(ifx)) 
487                 DEBUGpic14_emitcode("; ***","ifx false is non-null");
488                 */
489         }
490         
491         //  DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
492         
493 }
494 /*-----------------------------------------------------------------*/
495 /* pointerCode - returns the code for a pointer type                       */
496 /*-----------------------------------------------------------------*/
497 #if 0
498 static int pointerCode (sym_link *etype)
499 {
500         
501         return PTR_TYPE(SPEC_OCLS(etype));
502         
503 }
504 #endif
505
506 /*-----------------------------------------------------------------*/
507 /* aopForSym - for a true symbol                                                                   */
508 /*-----------------------------------------------------------------*/
509 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
510 {
511         asmop *aop;
512         memmap *space= SPEC_OCLS(sym->etype);
513         
514         DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
515         /* if already has one */
516         if (sym->aop)
517                 return sym->aop;
518         
519 #if 0
520         /* assign depending on the storage class */
521         /* if it is on the stack or indirectly addressable */
522         /* space we need to assign either r0 or r1 to it         */    
523         if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
524                 sym->aop = aop = newAsmop(0);
525                 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
526                 aop->size = getSize(sym->type);
527                 
528                 /* now assign the address of the variable to 
529                 the pointer register */
530                 if (aop->type != AOP_STK) {
531                         
532                         if (sym->onStack) {
533                                 if ( _G.accInUse )
534                                         pic14_emitcode("push","acc");
535                                 
536                                 pic14_emitcode("mov","a,_bp");
537                                 pic14_emitcode("add","a,#0x%02x",
538                                         ((sym->stack < 0) ?
539                                         ((char)(sym->stack - _G.nRegsSaved )) :
540                                 ((char)sym->stack)) & 0xff);
541                                 pic14_emitcode("mov","%s,a",
542                                         aop->aopu.aop_ptr->name);
543                                 
544                                 if ( _G.accInUse )
545                                         pic14_emitcode("pop","acc");
546                         } else
547                                 pic14_emitcode("mov","%s,#%s",
548                                 aop->aopu.aop_ptr->name,
549                                 sym->rname);
550                         aop->paged = space->paged;
551                 } else
552                         aop->aopu.aop_stk = sym->stack;
553                 return aop;
554         }
555         
556         if (sym->onStack && options.stack10bit)
557         {
558                 /* It's on the 10 bit stack, which is located in
559                 * far data space.
560                 */
561                 
562                 //DEBUGpic14_emitcode(";","%d",__LINE__);
563                 
564                 if ( _G.accInUse )
565                         pic14_emitcode("push","acc");
566                 
567                 pic14_emitcode("mov","a,_bp");
568                 pic14_emitcode("add","a,#0x%02x",
569                         ((sym->stack < 0) ?
570                         ((char)(sym->stack - _G.nRegsSaved )) :
571                 ((char)sym->stack)) & 0xff);
572                 
573                 genSetDPTR(1);
574                 pic14_emitcode ("mov","dpx1,#0x40");
575                 pic14_emitcode ("mov","dph1,#0x00");
576                 pic14_emitcode ("mov","dpl1, a");
577                 genSetDPTR(0);
578                 
579                 if ( _G.accInUse )
580                         pic14_emitcode("pop","acc");
581                 
582                 sym->aop = aop = newAsmop(AOP_DPTR2);
583                 aop->size = getSize(sym->type); 
584                 return aop;
585         }
586 #endif
587
588         //DEBUGpic14_emitcode(";","%d",__LINE__);
589         /* if in bit space */
590         if (IN_BITSPACE(space)) {
591                 sym->aop = aop = newAsmop (AOP_CRY);
592                 aop->aopu.aop_dir = sym->rname ;
593                 aop->size = getSize(sym->type);
594                 //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
595                 return aop;
596         }
597         /* if it is in direct space */
598         if (IN_DIRSPACE(space)) {
599                 sym->aop = aop = newAsmop (AOP_DIR);
600                 aop->aopu.aop_dir = sym->rname ;
601                 aop->size = getSize(sym->type);
602                 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
603                 return aop;
604         }
605         
606         /* special case for a function */
607         if (IS_FUNC(sym->type)) {   
608                 
609                 sym->aop = aop = newAsmop(AOP_PCODE);
610                 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
611                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
612                 PCOI(aop->aopu.pcop)->_function = 1;
613                 PCOI(aop->aopu.pcop)->index = 0;
614                 aop->size = FPTRSIZE; 
615                 /*
616                 sym->aop = aop = newAsmop(AOP_IMMD);    
617                 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
618                 strcpy(aop->aopu.aop_immd,sym->rname);
619                 aop->size = FPTRSIZE; 
620                 */
621                 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
622                 return aop;
623         }
624         
625         if (IS_ARRAY(sym->type)) {
626                 sym->aop = aop = newAsmop(AOP_PCODE);
627                 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
628                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
629                 PCOI(aop->aopu.pcop)->_function = 0;
630                 PCOI(aop->aopu.pcop)->index = 0;
631                 aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
632                 
633                 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
634                 return aop;
635         }
636         
637         /* only remaining is far space */
638         /* in which case DPTR gets the address */
639         sym->aop = aop = newAsmop(AOP_PCODE);
640         
641         aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
642         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
643         PCOI(aop->aopu.pcop)->index = 0;
644         
645         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
646                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
647         
648         allocDirReg (IC_LEFT(ic));
649         
650         aop->size = FPTRSIZE;
651         /*
652         DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
653         sym->aop = aop = newAsmop(AOP_DPTR);
654         pic14_emitcode ("mov","dptr,#%s", sym->rname);
655         aop->size = getSize(sym->type);
656         
657           DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
658         */
659         
660         /* if it is in code space */
661         if (IN_CODESPACE(space))
662                 aop->code = 1;
663         
664         return aop;       
665 }
666
667 /*-----------------------------------------------------------------*/
668 /* aopForRemat - rematerialzes an object                                                   */
669 /*-----------------------------------------------------------------*/
670 static asmop *aopForRemat (operand *op) // x symbol *sym)
671 {
672         symbol *sym = OP_SYMBOL(op);
673         iCode *ic = NULL;
674         asmop *aop = newAsmop(AOP_PCODE);
675         int val = 0;
676         int offset = 0;
677         
678         ic = sym->rematiCode;
679
680         DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
681         if(IS_OP_POINTER(op)) {
682                 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
683         }
684         for (;;) {
685                 if (ic->op == '+') {
686                         val += (int) operandLitValue(IC_RIGHT(ic));
687                 } else if (ic->op == '-') {
688                         val -= (int) operandLitValue(IC_RIGHT(ic));
689                 } else
690                         break;
691                 
692                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
693         }
694         
695         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
696         aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
697         PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
698         PCOI(aop->aopu.pcop)->index = val;
699         
700         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
701                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
702                 val, IS_PTR_CONST(operandType(op)));
703         
704         //      DEBUGpic14_emitcode(";","aop type  %s",AopType(AOP_TYPE(IC_LEFT(ic))));
705         
706         allocDirReg (IC_LEFT(ic));
707         
708         return aop;              
709 }
710
711 int aopIdx (asmop *aop, int offset)
712 {
713         if(!aop)
714                 return -1;
715         
716         if(aop->type !=  AOP_REG)
717                 return -2;
718         
719         return aop->aopu.aop_reg[offset]->rIdx;
720         
721 }
722 /*-----------------------------------------------------------------*/
723 /* regsInCommon - two operands have some registers in common       */
724 /*-----------------------------------------------------------------*/
725 static bool regsInCommon (operand *op1, operand *op2)
726 {
727         symbol *sym1, *sym2;
728         int i;
729         
730         /* if they have registers in common */
731         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
732                 return FALSE ;
733         
734         sym1 = OP_SYMBOL(op1);
735         sym2 = OP_SYMBOL(op2);
736         
737         if (sym1->nRegs == 0 || sym2->nRegs == 0)
738                 return FALSE ;
739         
740         for (i = 0 ; i < sym1->nRegs ; i++) {
741                 int j;
742                 if (!sym1->regs[i])
743                         continue ;
744                 
745                 for (j = 0 ; j < sym2->nRegs ;j++ ) {
746                         if (!sym2->regs[j])
747                                 continue ;
748                         
749                         if (sym2->regs[j] == sym1->regs[i])
750                                 return TRUE ;
751                 }
752         }
753         
754         return FALSE ;
755 }
756
757 /*-----------------------------------------------------------------*/
758 /* operandsEqu - equivalent                                                                        */
759 /*-----------------------------------------------------------------*/
760 static bool operandsEqu ( operand *op1, operand *op2)
761 {
762         symbol *sym1, *sym2;
763         
764         /* if they not symbols */
765         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
766                 return FALSE;
767         
768         sym1 = OP_SYMBOL(op1);
769         sym2 = OP_SYMBOL(op2);
770         
771         /* if both are itemps & one is spilt
772         and the other is not then false */
773         if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
774                 sym1->isspilt != sym2->isspilt )
775                 return FALSE ;
776         
777         /* if they are the same */
778         if (sym1 == sym2)
779                 return TRUE ;
780         
781         if (sym1->rname[0] && sym2->rname[0]
782                 && strcmp (sym1->rname, sym2->rname) == 0)
783                 return TRUE;
784         
785         
786         /* if left is a tmp & right is not */
787         if (IS_ITEMP(op1)  && 
788                 !IS_ITEMP(op2) &&
789                 sym1->isspilt  &&
790                 (sym1->usl.spillLoc == sym2))
791                 return TRUE;
792         
793         if (IS_ITEMP(op2)  && 
794                 !IS_ITEMP(op1) &&
795                 sym2->isspilt  &&
796                 sym1->level > 0 &&
797                 (sym2->usl.spillLoc == sym1))
798                 return TRUE ;
799         
800         return FALSE ;
801 }
802
803 /*-----------------------------------------------------------------*/
804 /* pic14_sameRegs - two asmops have the same registers             */
805 /*-----------------------------------------------------------------*/
806 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
807 {
808         int i;
809         
810         if (aop1 == aop2)
811                 return TRUE ;
812         
813         if (aop1->type != AOP_REG ||
814                 aop2->type != AOP_REG )
815                 return FALSE ;
816         
817         if (aop1->size != aop2->size )
818                 return FALSE ;
819         
820         for (i = 0 ; i < aop1->size ; i++ )
821                 if (aop1->aopu.aop_reg[i] !=
822                         aop2->aopu.aop_reg[i] )
823                         return FALSE ;
824                 
825                 return TRUE ;
826 }
827
828 /*-----------------------------------------------------------------*/
829 /* aopOp - allocates an asmop for an operand  :                    */
830 /*-----------------------------------------------------------------*/
831 void aopOp (operand *op, iCode *ic, bool result)
832 {
833         asmop *aop;
834         symbol *sym;
835         int i;
836         
837         if (!op)
838                 return ;
839         
840         /* if this a literal */
841         if (IS_OP_LITERAL(op)) {
842                 op->aop = aop = newAsmop(AOP_LIT);
843                 aop->aopu.aop_lit = op->operand.valOperand;
844                 aop->size = getSize(operandType(op));
845                 return;
846         }
847         
848         {
849                 sym_link *type = operandType(op);
850                 if(IS_PTR_CONST(type))
851                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
852         }
853         
854         /* if already has a asmop then continue */
855         if (op->aop)
856                 return ;
857         
858         /* if the underlying symbol has a aop */
859         if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
860                 DEBUGpic14_emitcode(";","%d",__LINE__);
861                 op->aop = OP_SYMBOL(op)->aop;
862                 return;
863         }
864         
865         /* if this is a true symbol */
866         if (IS_TRUE_SYMOP(op)) {          
867                 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
868                 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
869                 return ;
870         }
871         
872         /* this is a temporary : this has
873         only four choices :
874         a) register
875         b) spillocation
876         c) rematerialize 
877         d) conditional   
878         e) can be a return use only */
879         
880         sym = OP_SYMBOL(op);
881         
882         
883         /* if the type is a conditional */
884         if (sym->regType == REG_CND) {
885                 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
886                 aop->size = 0;
887                 return;
888         }
889         
890         /* if it is spilt then two situations
891         a) is rematerialize 
892         b) has a spill location */
893         if (sym->isspilt || sym->nRegs == 0) {
894                 
895                 DEBUGpic14_emitcode(";","%d",__LINE__);
896                 /* rematerialize it NOW */
897                 if (sym->remat) {
898                         
899                         sym->aop = op->aop = aop = aopForRemat (op);
900                         aop->size = getSize(sym->type);
901                         //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
902                         return;
903                 }
904                 
905 #if 0
906                 /* WREG is not usable as an ordinary operand with PIC architecture,
907                  * one might introduce a scratch register that can be used to make
908                  * WREG accesible as an operand... disable WREG for now */
909                 if (sym->accuse) {
910                         int i;
911                         aop = op->aop = sym->aop = newAsmop(AOP_ACC);
912                         aop->size = getSize(sym->type);
913                         for ( i = 0 ; i < 2 ; i++ )
914                                 aop->aopu.aop_str[i] = accUse[i];
915                         DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
916                         return;  
917                 }
918 #endif
919                 
920                 if (sym->ruonly ) {
921                         if(sym->isptr) {        // && sym->uptr 
922                                 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
923                                 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
924                                 
925                                 //PCOI(aop->aopu.pcop)->_const = 0;
926                                 //PCOI(aop->aopu.pcop)->index = 0;
927                                 /*
928                                 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
929                                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
930                                 */
931                                 //allocDirReg (IC_LEFT(ic));
932                                 
933                                 aop->size = getSize(sym->type);
934                                 DEBUGpic14_emitcode(";","%d",__LINE__);
935                                 return;
936                                 
937                         } else {
938                                 
939                                 unsigned i;
940                                 
941                                 aop = op->aop = sym->aop = newAsmop(AOP_STR);
942                                 aop->size = getSize(sym->type);
943                                 for ( i = 0 ; i < fReturnSizePic ; i++ )
944                                         aop->aopu.aop_str[i] = fReturn[i];
945                                 
946                                 DEBUGpic14_emitcode(";","%d",__LINE__);
947                                 return;
948                         }
949                 }
950                 
951                 /* else spill location  */
952                 if (sym->usl.spillLoc)
953                 {
954                         asmop *oldAsmOp = NULL;
955
956                         if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
957                         {
958                                 /* force a new aop if sizes differ */
959                                 oldAsmOp = sym->usl.spillLoc->aop;
960                                 sym->usl.spillLoc->aop = NULL;
961                         }
962                         DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
963                                 __FUNCTION__,__LINE__,
964                                 sym->usl.spillLoc->rname,
965                                 sym->rname, sym->usl.spillLoc->offset);
966                 
967                         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
968                         if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
969                         {
970                                 /* Don't reuse the new aop, go with the last one */
971                                 sym->usl.spillLoc->aop = oldAsmOp;
972                         }
973                         //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
974                         aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
975                                 getSize(sym->type), 
976                                 sym->usl.spillLoc->offset);
977                         aop->size = getSize(sym->type);
978                 
979                         return;
980                 }
981         }
982         
983         {
984                 sym_link *type = operandType(op);
985                 if(IS_PTR_CONST(type)) 
986                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
987         }
988         
989         /* must be in a register */
990         DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
991         sym->aop = op->aop = aop = newAsmop(AOP_REG);
992         aop->size = sym->nRegs;
993         for ( i = 0 ; i < sym->nRegs ;i++)
994                 aop->aopu.aop_reg[i] = sym->regs[i];
995 }
996
997 /*-----------------------------------------------------------------*/
998 /* freeAsmop - free up the asmop given to an operand                       */
999 /*----------------------------------------------------------------*/
1000 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1001 {       
1002         asmop *aop ;
1003         
1004         if (!op)
1005                 aop = aaop;
1006         else 
1007                 aop = op->aop;
1008         
1009         if (!aop)
1010                 return ;
1011         
1012         if (aop->freed)
1013                 goto dealloc; 
1014         
1015         aop->freed = 1;
1016         
1017         /* depending on the asmop type only three cases need work AOP_RO
1018         , AOP_R1 && AOP_STK */
1019 #if 0
1020         switch (aop->type) {
1021         case AOP_R0 :
1022                 if (_G.r0Pushed ) {
1023                         if (pop) {
1024                                 pic14_emitcode ("pop","ar0");     
1025                                 _G.r0Pushed--;
1026                         }
1027                 }
1028                 bitVectUnSetBit(ic->rUsed,R0_IDX);
1029                 break;
1030                 
1031         case AOP_R1 :
1032                 if (_G.r1Pushed ) {
1033                         if (pop) {
1034                                 pic14_emitcode ("pop","ar1");
1035                                 _G.r1Pushed--;
1036                         }
1037                 }
1038                 bitVectUnSetBit(ic->rUsed,R1_IDX);                      
1039                 break;
1040                 
1041         case AOP_STK :
1042                 {
1043                         int sz = aop->size;      
1044                         int stk = aop->aopu.aop_stk + aop->size;
1045                         bitVectUnSetBit(ic->rUsed,R0_IDX);
1046                         bitVectUnSetBit(ic->rUsed,R1_IDX);                
1047                         
1048                         getFreePtr(ic,&aop,FALSE);
1049                         
1050                         if (options.stack10bit)
1051                         {
1052                                 /* I'm not sure what to do here yet... */
1053                                 /* #STUB */
1054                                 fprintf(stderr, 
1055                                         "*** Warning: probably generating bad code for "
1056                                         "10 bit stack mode.\n");
1057                         }
1058                         
1059                         if (stk) {
1060                                 pic14_emitcode ("mov","a,_bp");
1061                                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1062                                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1063                         } else {
1064                                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1065                         }
1066                         
1067                         while (sz--) {
1068                                 pic14_emitcode("pop","acc");
1069                                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1070                                 if (!sz) break;
1071                                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1072                         }
1073                         op->aop = aop;
1074                         freeAsmop(op,NULL,ic,TRUE);
1075                         if (_G.r0Pushed) {
1076                                 pic14_emitcode("pop","ar0");
1077                                 _G.r0Pushed--;
1078                         }
1079                         
1080                         if (_G.r1Pushed) {
1081                                 pic14_emitcode("pop","ar1");
1082                                 _G.r1Pushed--;
1083                         }         
1084                 }
1085         }
1086 #endif
1087         
1088 dealloc:
1089         /* all other cases just dealloc */
1090         if (op ) {
1091                 op->aop = NULL;
1092                 if (IS_SYMOP(op)) {
1093                         OP_SYMBOL(op)->aop = NULL;      
1094                         /* if the symbol has a spill */
1095                         if (SPIL_LOC(op))
1096                                 SPIL_LOC(op)->aop = NULL;
1097                 }
1098         }
1099 }
1100
1101 /*-----------------------------------------------------------------*/
1102 /* aopGet - for fetching value of the aop                                                  */
1103 /*-----------------------------------------------------------------*/
1104 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1105 {
1106         char *s = buffer ;
1107         char *rs;
1108         
1109         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1110         /* offset is greater than
1111         size then zero */
1112         if (offset > (aop->size - 1) &&
1113                 aop->type != AOP_LIT)
1114                 return zero;
1115         
1116         /* depending on type */
1117         switch (aop->type) {
1118                 
1119         case AOP_R0:
1120         case AOP_R1:
1121                 DEBUGpic14_emitcode(";","%d",__LINE__);
1122                 /* if we need to increment it */           
1123                 while (offset > aop->coff) {            
1124                         pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);    
1125                         aop->coff++;
1126                 }
1127                 
1128                 while (offset < aop->coff) {
1129                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1130                         aop->coff--;
1131                 }
1132                 
1133                 aop->coff = offset ;
1134                 if (aop->paged) {
1135                         pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1136                         return (dname ? "acc" : "a");
1137                 }               
1138                 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1139                 rs = Safe_calloc(1,strlen(s)+1);
1140                 strcpy(rs,s);   
1141                 return rs;
1142                 
1143         case AOP_DPTR:
1144         case AOP_DPTR2:
1145                 DEBUGpic14_emitcode(";","%d",__LINE__);
1146                 if (aop->type == AOP_DPTR2)
1147                 {
1148                         genSetDPTR(1);
1149                 }
1150                 
1151                 while (offset > aop->coff) {
1152                         pic14_emitcode ("inc","dptr");
1153                         aop->coff++;
1154                 }
1155                 
1156                 while (offset < aop->coff) {            
1157                         pic14_emitcode("lcall","__decdptr");
1158                         aop->coff--;
1159                 }
1160                 
1161                 aop->coff = offset;
1162                 if (aop->code) {
1163                         pic14_emitcode("clr","a");
1164                         pic14_emitcode("movc","a,@a+dptr");
1165                 }
1166                 else {
1167                         pic14_emitcode("movx","a,@dptr");
1168                 }
1169                 
1170                 if (aop->type == AOP_DPTR2)
1171                 {
1172                         genSetDPTR(0);
1173                 }
1174                 
1175                 return (dname ? "acc" : "a");
1176                 
1177                 
1178         case AOP_IMMD:
1179                 if (bit16) 
1180                         sprintf (s,"%s",aop->aopu.aop_immd);
1181                 else
1182                         if (offset) 
1183                                 sprintf(s,"(%s >> %d)",
1184                                 aop->aopu.aop_immd,
1185                                 offset*8);
1186                         else
1187                                 sprintf(s,"%s",
1188                                 aop->aopu.aop_immd);
1189                         DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1190                         rs = Safe_calloc(1,strlen(s)+1);
1191                         strcpy(rs,s);   
1192                         return rs;
1193                         
1194         case AOP_DIR:
1195                 if (offset) {
1196                         sprintf(s,"(%s + %d)",
1197                                 aop->aopu.aop_dir,
1198                                 offset);
1199                         DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1200                 } else
1201                         sprintf(s,"%s",aop->aopu.aop_dir);
1202                 rs = Safe_calloc(1,strlen(s)+1);
1203                 strcpy(rs,s);   
1204                 return rs;
1205                 
1206         case AOP_REG:
1207                 //if (dname) 
1208                 //        return aop->aopu.aop_reg[offset]->dname;
1209                 //else
1210                 return aop->aopu.aop_reg[offset]->name;
1211                 
1212         case AOP_CRY:
1213                 //pic14_emitcode(";","%d",__LINE__);
1214                 return aop->aopu.aop_dir;
1215                 
1216         case AOP_ACC:
1217                 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1218                 return "AOP_accumulator_bug";
1219                 
1220         case AOP_LIT:
1221                 sprintf(s, "0x%02x", pic14aopLiteral (aop->aopu.aop_lit, offset));
1222                 rs = Safe_strdup(s);
1223                 return rs;
1224                 
1225         case AOP_STR:
1226                 aop->coff = offset ;
1227                 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1228                         dname)
1229                         return "acc";
1230                 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1231                 
1232                 return aop->aopu.aop_str[offset];
1233                 
1234         case AOP_PCODE:
1235                 {
1236                         pCodeOp *pcop = aop->aopu.pcop;
1237                         DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1238                         if(pcop->name) {
1239                                 if (offset) {
1240                                         DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1241                                         sprintf(s,"(%s+%d)", pcop->name,offset);
1242                                 } else {
1243                                         DEBUGpic14_emitcode(";","%s",pcop->name);
1244                                         sprintf(s,"%s", pcop->name);
1245                                 }
1246                         } else
1247                                 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1248                         
1249                 }
1250                 rs = Safe_calloc(1,strlen(s)+1);
1251                 strcpy(rs,s);   
1252                 return rs;
1253                 
1254   }
1255   
1256   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1257           "aopget got unsupported aop->type");
1258   exit(0);
1259 }
1260
1261
1262 /*-----------------------------------------------------------------*/
1263 /* popGetTempReg - create a new temporary pCodeOp                                  */
1264 /*-----------------------------------------------------------------*/
1265 pCodeOp *popGetTempReg(void)
1266 {
1267         
1268         pCodeOp *pcop;
1269         
1270         pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1271         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1272                 PCOR(pcop)->r->wasUsed=1;
1273                 PCOR(pcop)->r->isFree=0;
1274         }
1275         
1276         return pcop;
1277 }
1278
1279 /*-----------------------------------------------------------------*/
1280 /* popReleaseTempReg - create a new temporary pCodeOp                              */
1281 /*-----------------------------------------------------------------*/
1282 void popReleaseTempReg(pCodeOp *pcop)
1283 {
1284         
1285         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1286                 PCOR(pcop)->r->isFree = 1;
1287         
1288 }
1289 /*-----------------------------------------------------------------*/
1290 /* popGetLabel - create a new pCodeOp of type PO_LABEL                     */
1291 /*-----------------------------------------------------------------*/
1292 pCodeOp *popGetLabel(unsigned int key)
1293 {
1294         
1295         DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1296         
1297         if(key>(unsigned int)max_key)
1298                 max_key = key;
1299         
1300         return newpCodeOpLabel(NULL,key+100+labelOffset);
1301 }
1302
1303 /*-------------------------------------------------------------------*/
1304 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1305 /*-------------------------------------------------------------------*/
1306 pCodeOp *popGetHighLabel(unsigned int key)
1307 {
1308         pCodeOp *pcop;
1309         pcop = popGetLabel(key);
1310         PCOLAB(pcop)->offset = 1;
1311         return pcop;
1312 }
1313
1314 /*-----------------------------------------------------------------*/
1315 /* popGetLit - asm operator to pcode operator conversion                           */
1316 /*-----------------------------------------------------------------*/
1317 pCodeOp *popGetLit(unsigned int lit)
1318 {
1319         
1320         return newpCodeOpLit((unsigned char)lit);
1321 }
1322
1323 /*-----------------------------------------------------------------*/
1324 /* popGetImmd - asm operator to pcode immediate conversion                 */
1325 /*-----------------------------------------------------------------*/
1326 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1327 {
1328         
1329         return newpCodeOpImmd(name, offset,index, 0, is_func);
1330 }
1331
1332 extern set *externs;
1333
1334 /*-----------------------------------------------------------------*/
1335 /* popGetWithString - asm operator to pcode operator conversion                    */
1336 /*-----------------------------------------------------------------*/
1337 pCodeOp *popGetWithString(char *str, int isExtern)
1338 {
1339         pCodeOp *pcop;
1340         
1341         
1342         if(!str) {
1343                 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1344                 exit (1);
1345         }
1346         
1347         pcop = newpCodeOp(str,PO_STR);
1348         PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1349
1350         return pcop;
1351 }
1352
1353 pCodeOp *popGetExternal (char *str)
1354 {
1355         pCodeOp *pcop = popGetWithString (str, 1);
1356         
1357         if (str) {
1358           symbol *sym;
1359           bool found = 0;
1360
1361           for (sym = setFirstItem (externs); !found && sym; sym = setNextItem (externs))
1362           {
1363             if (!strcmp (str, sym->rname))
1364               found = 1;
1365           }
1366           
1367           if (!found)
1368           {
1369             sym = newSymbol(str, 0);
1370             strncpy(sym->rname, str, SDCC_NAME_MAX);
1371             addSet (&externs, sym);
1372           } // if
1373         }
1374         return pcop;
1375 }
1376
1377 /*-----------------------------------------------------------------*/
1378 /* popRegFromString -                                                                                      */
1379 /*-----------------------------------------------------------------*/
1380 pCodeOp *popRegFromString(char *str, int size, int offset)
1381 {
1382         
1383         pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1384         pcop->type = PO_DIR;
1385         
1386         DEBUGpic14_emitcode(";","%d",__LINE__);
1387         
1388         if(!str)
1389                 str = "BAD_STRING";
1390         
1391         pcop->name = Safe_calloc(1,strlen(str)+1);
1392         strcpy(pcop->name,str);
1393         
1394         //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1395         
1396         PCOR(pcop)->r = dirregWithName(pcop->name);
1397         if(PCOR(pcop)->r == NULL) {
1398                 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1399                 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1400                 DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1401         } else {
1402                 DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1403         }
1404         PCOR(pcop)->instance = offset;
1405         
1406         return pcop;
1407 }
1408
1409 /*-----------------------------------------------------------------*/
1410 /*-----------------------------------------------------------------*/
1411 pCodeOp *popRegFromIdx(int rIdx)
1412 {
1413         pCodeOp *pcop;
1414         
1415         DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1416                 __FUNCTION__,__LINE__,rIdx);
1417         
1418         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1419         
1420         PCOR(pcop)->rIdx = rIdx;
1421         PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1422         PCOR(pcop)->r->isFree = 0;
1423         PCOR(pcop)->r->wasUsed = 1;
1424         
1425         pcop->type = PCOR(pcop)->r->pc_type;
1426         
1427         
1428         return pcop;
1429 }
1430
1431 /*-----------------------------------------------------------------*/
1432 /* popGet - asm operator to pcode operator conversion                      */
1433 /*-----------------------------------------------------------------*/
1434 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1435 {
1436         //char *s = buffer ;
1437         //char *rs;
1438         
1439         pCodeOp *pcop;
1440         
1441         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1442         /* offset is greater than
1443         size then zero */
1444
1445         assert (aop);
1446
1447
1448         /* XXX: still needed for BIT operands (AOP_CRY) */
1449         if (offset > (aop->size - 1) &&
1450                 aop->type != AOP_LIT &&
1451                 aop->type != AOP_PCODE)
1452         {
1453                 printf( "%s: (offset[%d] > AOP_SIZE(op)[%d]-1) && AOP_TYPE(op) != AOP_LIT)\n", __FUNCTION__, offset, aop->size);
1454                 return NULL;  //zero;
1455         }
1456         
1457         /* depending on type */
1458         switch (aop->type) {
1459                 
1460         case AOP_R0:
1461         case AOP_R1:
1462         case AOP_DPTR:
1463         case AOP_DPTR2:
1464         case AOP_ACC:
1465                 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1466                 return NULL;
1467                 
1468         case AOP_IMMD:
1469                 DEBUGpic14_emitcode(";","%d",__LINE__);
1470                 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1471                 
1472         case AOP_DIR:
1473                 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1474 #if 0
1475                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1476                 pcop->type = PO_DIR;
1477                 
1478                 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1479                 strcpy(pcop->name,aop->aopu.aop_dir);   
1480                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1481                 if(PCOR(pcop)->r == NULL) {
1482                         //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1483                         PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1484                         DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1485                 } else {
1486                         DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1487                 }
1488                 PCOR(pcop)->instance = offset;
1489                 
1490                 return pcop;
1491 #endif
1492                 
1493         case AOP_REG:
1494                 {
1495                         int rIdx;
1496                         assert (offset < aop->size);
1497                         rIdx = aop->aopu.aop_reg[offset]->rIdx;
1498                         
1499                         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1500                         PCOR(pcop)->rIdx = rIdx;
1501                         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1502                         PCOR(pcop)->r->wasUsed=1;
1503                         PCOR(pcop)->r->isFree=0;
1504                         
1505                         PCOR(pcop)->instance = offset;
1506                         pcop->type = PCOR(pcop)->r->pc_type;
1507                         //rs = aop->aopu.aop_reg[offset]->name;
1508                         DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1509                         return pcop;
1510                 }
1511                 
1512         case AOP_CRY:
1513                 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1514                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1515                 //if(PCOR(pcop)->r == NULL)
1516                 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1517                 return pcop;
1518                 
1519         case AOP_LIT:
1520                 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1521                 
1522         case AOP_STR:
1523                 DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1524                 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1525                 /*
1526                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1527                 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1528                 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1529                 pcop->type = PCOR(pcop)->r->pc_type;
1530                 pcop->name = PCOR(pcop)->r->name;
1531                 
1532                   return pcop;
1533                 */
1534                 
1535         case AOP_PCODE:
1536                 pcop = NULL;
1537                 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1538                         __LINE__, 
1539                         ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1540                 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1541                 switch (aop->aopu.pcop->type)
1542                 {
1543                 case PO_IMMEDIATE:
1544                   pcop = pCodeOpCopy (aop->aopu.pcop);
1545                   /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1546                    * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1547                   PCOI(pcop)->index += offset;
1548                   //PCOI(pcop)->offset = 0;
1549                   break;
1550                 case PO_DIR:
1551                   pcop = pCodeOpCopy (aop->aopu.pcop);
1552                   PCOR(pcop)->instance = offset;
1553                   break;
1554                 default:
1555                   assert ( !"unhandled pCode type" );
1556                   break;
1557                 } // switch
1558                 return pcop;
1559         }
1560         
1561         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1562                 "popGet got unsupported aop->type");
1563         exit(0);
1564 }
1565
1566 /*-----------------------------------------------------------------*/
1567 /* popGetAddr - access the low/high word of a symbol (immediate)   */
1568 /*              (for non-PO_IMMEDIATEs this is the same as popGet) */
1569 /*-----------------------------------------------------------------*/
1570 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1571 {
1572   if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1573   {
1574     pCodeOp *pcop = aop->aopu.pcop;
1575     assert (offset <= GPTRSIZE);
1576
1577     /* special case: index >= 2 should return GPOINTER-style values */
1578     if (offset == 2)
1579     {
1580       pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1581       return pcop;
1582     }
1583     
1584     pcop = pCodeOpCopy (pcop);
1585     /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1586      * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1587     PCOI(pcop)->offset += offset;
1588     PCOI(pcop)->index += index;
1589     //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);
1590     return pcop;
1591   } else {
1592     return popGet (aop, offset + index);
1593   }
1594 }
1595
1596 /*-----------------------------------------------------------------*/
1597 /* aopPut - puts a string for a aop                                                        */
1598 /*-----------------------------------------------------------------*/
1599 void aopPut (asmop *aop, char *s, int offset)
1600 {
1601         char *d = buffer ;
1602         symbol *lbl ;
1603         
1604         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1605         
1606         if (aop->size && offset > ( aop->size - 1)) {
1607                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1608                         "aopPut got offset > aop->size");
1609                 exit(0);
1610         }
1611         
1612         /* will assign value to value */
1613         /* depending on where it is ofcourse */
1614         switch (aop->type) {
1615         case AOP_DIR:
1616                 if (offset) {
1617                         sprintf(d,"(%s + %d)",
1618                                 aop->aopu.aop_dir,offset);
1619                         fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1620                         
1621                 } else
1622                         sprintf(d,"%s",aop->aopu.aop_dir);
1623                 
1624                 if (strcmp(d,s)) {
1625                         DEBUGpic14_emitcode(";","%d",__LINE__);
1626                         if(strcmp(s,"W"))
1627                                 pic14_emitcode("movf","%s,w",s);
1628                         pic14_emitcode("movwf","%s",d);
1629                         
1630                         if(strcmp(s,"W")) {
1631                                 pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1632                                 if(offset >= aop->size) {
1633                                         emitpcode(POC_CLRF,popGet(aop,offset));
1634                                         break;
1635                                 } else {
1636                                         emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1637                                 }
1638                         }
1639                         emitpcode(POC_MOVWF,popGet(aop,offset));
1640                 
1641                 }
1642                 break;
1643                 
1644         case AOP_REG:
1645                 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1646                         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1647                         /*
1648                         if (*s == '@'             ||
1649                         strcmp(s,"r0") == 0 ||
1650                         strcmp(s,"r1") == 0 ||
1651                         strcmp(s,"r2") == 0 ||
1652                         strcmp(s,"r3") == 0 ||
1653                         strcmp(s,"r4") == 0 ||
1654                         strcmp(s,"r5") == 0 ||
1655                         strcmp(s,"r6") == 0 || 
1656                         strcmp(s,"r7") == 0 )
1657                         pic14_emitcode("mov","%s,%s  ; %d",
1658                         aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1659                         else
1660                         */
1661                         
1662                         if(strcmp(s,"W")==0 )
1663                                 pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1664                         
1665                         pic14_emitcode("movwf","%s",
1666                                 aop->aopu.aop_reg[offset]->name);
1667                         
1668                         if(strcmp(s,zero)==0) {
1669                                 emitpcode(POC_CLRF,popGet(aop,offset));
1670                                 
1671                         } else if(strcmp(s,"W")==0) {
1672                                 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1673                                 pcop->type = PO_GPR_REGISTER;
1674                                 
1675                                 PCOR(pcop)->rIdx = -1;
1676                                 PCOR(pcop)->r = NULL;
1677                                 
1678                                 DEBUGpic14_emitcode(";","%d",__LINE__);
1679                                 pcop->name = Safe_strdup(s);
1680                                 emitpcode(POC_MOVFW,pcop);
1681                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1682                         } else if(strcmp(s,one)==0) {
1683                                 emitpcode(POC_CLRF,popGet(aop,offset));
1684                                 emitpcode(POC_INCF,popGet(aop,offset));
1685                         } else {
1686                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1687                         }
1688                 }
1689                 break;
1690                 
1691         case AOP_DPTR:
1692         case AOP_DPTR2:
1693                 
1694                 if (aop->type == AOP_DPTR2)
1695                 {
1696                         genSetDPTR(1);
1697                 }
1698                 
1699                 if (aop->code) {
1700                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1701                                 "aopPut writting to code space");
1702                         exit(0);
1703                 }
1704                 
1705                 while (offset > aop->coff) {
1706                         aop->coff++;
1707                         pic14_emitcode ("inc","dptr");
1708                 }
1709                 
1710                 while (offset < aop->coff) {
1711                         aop->coff-- ;
1712                         pic14_emitcode("lcall","__decdptr");
1713                 }
1714                 
1715                 aop->coff = offset;
1716                 
1717                 /* if not in accumulater */
1718                 MOVA(s);
1719                 
1720                 pic14_emitcode ("movx","@dptr,a");
1721                 
1722                 if (aop->type == AOP_DPTR2)
1723                 {
1724                         genSetDPTR(0);
1725                 }
1726                 break;
1727                 
1728         case AOP_R0:
1729         case AOP_R1:
1730                 while (offset > aop->coff) {
1731                         aop->coff++;
1732                         pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1733                 }
1734                 while (offset < aop->coff) {
1735                         aop->coff-- ;
1736                         pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1737                 }
1738                 aop->coff = offset;
1739                 
1740                 if (aop->paged) {
1741                         MOVA(s);                         
1742                         pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1743                         
1744                 } else
1745                         if (*s == '@') {
1746                                 MOVA(s);
1747                                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1748                         } else
1749                                 if (strcmp(s,"r0") == 0 ||
1750                                         strcmp(s,"r1") == 0 ||
1751                                         strcmp(s,"r2") == 0 ||
1752                                         strcmp(s,"r3") == 0 ||
1753                                         strcmp(s,"r4") == 0 ||
1754                                         strcmp(s,"r5") == 0 ||
1755                                         strcmp(s,"r6") == 0 || 
1756                                         strcmp(s,"r7") == 0 ) {
1757                                         char buffer[10];
1758                                         sprintf(buffer,"a%s",s);
1759                                         pic14_emitcode("mov","@%s,%s",
1760                                                 aop->aopu.aop_ptr->name,buffer);
1761                                 } else
1762                                         pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1763                                 
1764                                 break;
1765                                 
1766         case AOP_STK:
1767                 if (strcmp(s,"a") == 0)
1768                         pic14_emitcode("push","acc");
1769                 else
1770                         pic14_emitcode("push","%s",s);
1771                 
1772                 break;
1773                 
1774         case AOP_CRY:
1775                 /* if bit variable */
1776                 if (!aop->aopu.aop_dir) {
1777                         pic14_emitcode("clr","a");
1778                         pic14_emitcode("rlc","a");
1779                 } else {
1780                         if (s == zero) 
1781                                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1782                         else
1783                                 if (s == one)
1784                                         pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1785                                 else
1786                                         if (!strcmp(s,"c"))
1787                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1788                                         else {
1789                                                 lbl = newiTempLabel(NULL);
1790                                                 
1791                                                 if (strcmp(s,"a")) {
1792                                                         MOVA(s);
1793                                                 }
1794                                                 pic14_emitcode("clr","c");
1795                                                 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1796                                                 pic14_emitcode("cpl","c");
1797                                                 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1798                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1799                                         }
1800                 }
1801                 break;
1802                 
1803         case AOP_STR:
1804                 aop->coff = offset;
1805                 if (strcmp(aop->aopu.aop_str[offset],s))
1806                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1807                 break;
1808                 
1809         case AOP_ACC:
1810                 aop->coff = offset;
1811                 if (!offset && (strcmp(s,"acc") == 0))
1812                         break;
1813                 
1814                 if (strcmp(aop->aopu.aop_str[offset],s))
1815                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1816                 break;
1817                 
1818         default :
1819                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1820                         "aopPut got unsupported aop->type");
1821                 exit(0);
1822         }
1823         
1824 }
1825
1826 /*-----------------------------------------------------------------*/
1827 /* mov2w_op - generate either a MOVLW or MOVFW based operand type  */
1828 /*-----------------------------------------------------------------*/
1829 static void mov2w_op (operand *op, int offset)
1830 {
1831         assert (op);
1832         FENTRY;
1833
1834         /* for PO_IMMEDIATEs: use address or value? */
1835         if (op_isLitLike (op))
1836         {
1837                 /* access address of op */
1838                 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1839                 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1840                 {
1841                         if (offset == GPTRSIZE-1)
1842                                 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1843                         else
1844                                 emitpcode (POC_MOVLW, popGetLit (0));
1845                 }
1846                 else
1847                         emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1848         } else {
1849                 /* access value stored in op */
1850                 mov2w (AOP(op), offset);
1851         }
1852 }
1853
1854
1855 /*-----------------------------------------------------------------*/
1856 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1857 /*-----------------------------------------------------------------*/
1858 void mov2w (asmop *aop, int offset)
1859 {
1860         
1861         if(!aop)
1862                 return;
1863         
1864         DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1865         
1866         if ( aop_isLitLike (aop) )
1867                 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1868         else
1869                 emitpcode(POC_MOVFW,popGet(aop,offset));
1870         
1871 }
1872
1873 static void movwf (asmop *op, int offset)
1874 {
1875         emitpcode (POC_MOVWF, popGet(op, offset));
1876 }
1877
1878 static pCodeOp *get_argument_pcop (int idx)
1879 {
1880         assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1881         return popRegFromIdx (Gstack_base_addr - (idx - 1));
1882 }
1883
1884 static pCodeOp *get_return_val_pcop (int offset)
1885 {
1886         assert (offset > 0 && "the most significant byte is returned via WREG");
1887         return popRegFromIdx (Gstack_base_addr - (offset - 1));
1888 }
1889
1890 static void pass_argument (operand *op, int offset, int idx)
1891 {
1892         if (op)
1893                 mov2w_op (op, offset);
1894         if (idx != 0)
1895                 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1896 }
1897
1898 static void get_returnvalue (operand *op, int offset, int idx)
1899 {
1900         if (idx != 0)
1901                 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1902         movwf(AOP(op), offset);
1903 }
1904
1905 static void call_libraryfunc (char *name)
1906 {
1907   /* library code might reside in different page... */
1908   emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1909   /* call the library function */
1910   emitpcode (POC_CALL, popGetExternal (name));
1911   /* might return from different page... */
1912   emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1913 }
1914 #if 0
1915 /*-----------------------------------------------------------------*/
1916 /* reAdjustPreg - points a register back to where it should        */
1917 /*-----------------------------------------------------------------*/
1918 static void reAdjustPreg (asmop *aop)
1919 {
1920         int size ;
1921         
1922         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1923         aop->coff = 0;
1924         if ((size = aop->size) <= 1)
1925                 return ;
1926         size-- ;
1927         switch (aop->type) {
1928         case AOP_R0 :
1929         case AOP_R1 :
1930                 while (size--)
1931                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1932                 break;                  
1933         case AOP_DPTR :
1934         case AOP_DPTR2:
1935                 if (aop->type == AOP_DPTR2)
1936                 {
1937                         genSetDPTR(1);
1938                 } 
1939                 while (size--)
1940                 {
1941                         pic14_emitcode("lcall","__decdptr");
1942                 }
1943                 
1944                 if (aop->type == AOP_DPTR2)
1945                 {
1946                         genSetDPTR(0);
1947                 }
1948                 break;
1949                 
1950         }
1951         
1952 }
1953 #endif
1954
1955
1956 #if 0
1957 /*-----------------------------------------------------------------*/
1958 /* opIsGptr: returns non-zero if the passed operand is             */
1959 /* a generic pointer type.                                         */
1960 /*-----------------------------------------------------------------*/ 
1961 static int opIsGptr(operand *op)
1962 {
1963         sym_link *type = operandType(op);
1964         
1965         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1966         if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1967         {
1968                 return 1;
1969         }
1970         return 0;          
1971 }
1972 #endif
1973
1974 /*-----------------------------------------------------------------*/
1975 /* pic14_getDataSize - get the operand data size                   */
1976 /*-----------------------------------------------------------------*/
1977 int pic14_getDataSize(operand *op)
1978 {
1979         int size;
1980         
1981         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1982         
1983 #if 0
1984         size = getSize(OP_SYM_ETYPE(op));
1985         return size;
1986         //return AOP_SIZE(op);
1987         
1988         // tsd- in the pic port, the genptr size is 1, so this code here
1989         // fails. ( in the 8051 port, the size was 4).
1990 #else
1991         size = AOP_SIZE(op);
1992         if (IS_GENPTR(OP_SYM_TYPE(op)))
1993         {
1994                 sym_link *type = operandType(op);
1995                 if (IS_GENPTR(type))
1996                 {
1997                         /* generic pointer; arithmetic operations
1998                         * should ignore the high byte (pointer type).
1999                         */
2000                         size--;
2001                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2002                 }
2003         }
2004         return size;
2005 #endif
2006 }
2007
2008 /*-----------------------------------------------------------------*/
2009 /* pic14_outAcc - output Acc                                       */
2010 /*-----------------------------------------------------------------*/
2011 void pic14_outAcc(operand *result)
2012 {
2013         int size,offset;
2014         DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2015         DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
2016         
2017         
2018         size = pic14_getDataSize(result);
2019         if(size){
2020                 emitpcode(POC_MOVWF,popGet(AOP(result),0));
2021                 size--;
2022                 offset = 1;
2023                 /* unsigned or positive */
2024                 while(size--)
2025                         emitpcode(POC_CLRF,popGet(AOP(result),offset++));
2026         }
2027         
2028 }
2029
2030 /*-----------------------------------------------------------------*/
2031 /* pic14_outBitC - output a bit C                                  */
2032 /*-----------------------------------------------------------------*/
2033 void pic14_outBitC(operand *result)
2034 {
2035         
2036         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2037         /* if the result is bit */
2038         if (AOP_TYPE(result) == AOP_CRY) 
2039                 aopPut(AOP(result),"c",0);
2040         else {
2041                 pic14_emitcode("clr","a  ; %d", __LINE__);
2042                 pic14_emitcode("rlc","a");
2043                 pic14_outAcc(result);
2044         }
2045 }
2046
2047 /*-----------------------------------------------------------------*/
2048 /* pic14_toBoolean - emit code for orl a,operator(sizeop)          */
2049 /*-----------------------------------------------------------------*/
2050 void pic14_toBoolean(operand *oper)
2051 {
2052         int size = AOP_SIZE(oper);
2053         int offset = 0;
2054         
2055         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2056
2057         assert (size > 0);
2058
2059         if (size == 1) {
2060                 /* MOVFW does not load the flags... */
2061                 if (AOP_TYPE(oper) == AOP_ACC) {
2062                         emitpcode(POC_IORLW, popGetLit(0));
2063                         offset = 1;
2064                 } else {
2065                         emitpcode(POC_MOVLW, popGetLit(0));
2066                         offset = 0;
2067                 }
2068         } else {
2069                 if ( AOP_TYPE(oper) != AOP_ACC) {
2070                         emitpcode(POC_MOVFW,popGet(AOP(oper),0));
2071                         offset = 1;
2072                 }
2073         }
2074         
2075         while (offset < size) {
2076                 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
2077         }
2078         /* Z is set iff (oper == 0) */
2079 }
2080
2081
2082 /*-----------------------------------------------------------------*/
2083 /* genNot - generate code for ! operation                          */
2084 /*-----------------------------------------------------------------*/
2085 static void genNot (iCode *ic)
2086 {
2087         //symbol *tlbl;
2088         int size;
2089
2090         FENTRY;
2091         
2092         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2093         /* assign asmOps to operand & result */
2094         aopOp (IC_LEFT(ic),ic,FALSE);
2095         aopOp (IC_RESULT(ic),ic,TRUE);
2096         
2097         DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2098         /* if in bit space then a special case */
2099         if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2100                 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2101                         emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2102                         emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2103                 } else {
2104                         emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2105                         emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2106                         emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2107                 }
2108                 goto release;
2109         }
2110         
2111         size = AOP_SIZE(IC_LEFT(ic));
2112         mov2w (AOP(IC_LEFT(ic)),0);
2113         while (--size > 0)
2114         {
2115           if (op_isLitLike (IC_LEFT(ic)))
2116             emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2117           else
2118             emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2119         }
2120         emitpcode(POC_MOVLW, popGetLit (0));
2121         emitSKPNZ;
2122         emitpcode(POC_MOVLW, popGetLit (1));
2123         movwf(AOP(IC_RESULT(ic)), 0);
2124
2125         for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2126         {
2127           emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2128         }
2129         goto release;
2130         
2131 release:        
2132         /* release the aops */
2133         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2134         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2135 }
2136
2137
2138 /*-----------------------------------------------------------------*/
2139 /* genCpl - generate code for complement                                                   */
2140 /*-----------------------------------------------------------------*/
2141 static void genCpl (iCode *ic)
2142 {
2143         operand *left, *result;
2144         int size, offset=0;  
2145         
2146         FENTRY;
2147         
2148         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2149         aopOp((left = IC_LEFT(ic)),ic,FALSE);
2150         aopOp((result=IC_RESULT(ic)),ic,TRUE);
2151         
2152         /* if both are in bit space then 
2153         a special case */
2154         if (AOP_TYPE(result) == AOP_CRY &&
2155                 AOP_TYPE(left) == AOP_CRY ) { 
2156                 
2157                 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir); 
2158                 pic14_emitcode("cpl","c"); 
2159                 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir); 
2160                 goto release; 
2161         } 
2162         
2163         size = AOP_SIZE(result);
2164         if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2165         while (size--) {
2166                 
2167                 if(AOP_TYPE(left) == AOP_ACC) 
2168                         emitpcode(POC_XORLW, popGetLit(0xff));
2169                 else
2170                         emitpcode(POC_COMFW,popGet(AOP(left),offset));
2171                 
2172                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2173                 offset++;
2174         }
2175         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2176         
2177         
2178 release:
2179         /* release the aops */
2180         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2181         freeAsmop(result,NULL,ic,TRUE);
2182 }
2183
2184 /*-----------------------------------------------------------------*/
2185 /* genUminusFloat - unary minus for floating points                        */
2186 /*-----------------------------------------------------------------*/
2187 static void genUminusFloat(operand *op,operand *result)
2188 {
2189         int size ,offset =0 ;
2190         char *l;
2191         
2192         FENTRY;
2193
2194         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2195         /* for this we just need to flip the 
2196         first it then copy the rest in place */
2197         size = AOP_SIZE(op) - 1;
2198         l = aopGet(AOP(op),3,FALSE,FALSE);
2199         
2200         MOVA(l);          
2201         
2202         pic14_emitcode("cpl","acc.7");
2203         aopPut(AOP(result),"a",3);      
2204         
2205         while(size--) {
2206                 aopPut(AOP(result),
2207                         aopGet(AOP(op),offset,FALSE,FALSE),
2208                         offset);
2209                 offset++;
2210         }                
2211 }
2212
2213 /*-----------------------------------------------------------------*/
2214 /* genUminus - unary minus code generation                                                 */
2215 /*-----------------------------------------------------------------*/
2216 static void genUminus (iCode *ic)
2217 {
2218         int size, i;
2219         sym_link *optype, *rtype;
2220         
2221         FENTRY;
2222         
2223         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2224         /* assign asmops */
2225         aopOp(IC_LEFT(ic),ic,FALSE);
2226         aopOp(IC_RESULT(ic),ic,TRUE);
2227         
2228         /* if both in bit space then special
2229         case */
2230         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2231                 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2232                 
2233                 emitpcode(POC_BCF,       popGet(AOP(IC_RESULT(ic)),0));
2234                 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2235                 emitpcode(POC_BSF,       popGet(AOP(IC_RESULT(ic)),0));
2236                 
2237                 goto release; 
2238         } 
2239         
2240         optype = operandType(IC_LEFT(ic));
2241         rtype = operandType(IC_RESULT(ic));
2242         
2243         /* if float then do float stuff */
2244         if (IS_FLOAT(optype)) {
2245                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2246                 goto release;
2247         }
2248         
2249         /* otherwise subtract from zero by taking the 2's complement */
2250         size = AOP_SIZE(IC_LEFT(ic));
2251         
2252         for(i=0; i<size; i++) {
2253                 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2254                         emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
2255                 else {
2256                         emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2257                         emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2258                 }
2259         }
2260         
2261         emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
2262         for(i=1; i<size; i++) {
2263                 emitSKPNZ;
2264                 emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
2265         }
2266         
2267 release:
2268         /* release the aops */
2269         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2270         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);  
2271 }
2272
2273 /*-----------------------------------------------------------------*/
2274 /* saveRegisters - will look for a call and save the registers     */
2275 /*-----------------------------------------------------------------*/
2276 static void saveRegisters(iCode *lic) 
2277 {
2278         int i;
2279         iCode *ic;
2280         bitVect *rsave;
2281         sym_link *dtype;
2282         
2283         FENTRY;
2284
2285         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2286         /* look for call */
2287         for (ic = lic ; ic ; ic = ic->next) 
2288                 if (ic->op == CALL || ic->op == PCALL)
2289                         break;
2290                 
2291                 if (!ic) {
2292                         fprintf(stderr,"found parameter push with no function call\n");
2293                         return ;
2294                 }
2295                 
2296                 /* if the registers have been saved already then
2297                 do nothing */
2298                 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2299                         return ;
2300                 
2301                         /* find the registers in use at this time 
2302                 and push them away to safety */
2303                 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2304                         ic->rUsed);
2305                 
2306                 ic->regsSaved = 1;
2307                 if (options.useXstack) {
2308                         if (bitVectBitValue(rsave,R0_IDX))
2309                                 pic14_emitcode("mov","b,r0");
2310                         pic14_emitcode("mov","r0,%s",spname);
2311                         for (i = 0 ; i < pic14_nRegs ; i++) {
2312                                 if (bitVectBitValue(rsave,i)) {
2313                                         if (i == R0_IDX)
2314                                                 pic14_emitcode("mov","a,b");
2315                                         else
2316                                                 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2317                                         pic14_emitcode("movx","@r0,a");
2318                                         pic14_emitcode("inc","r0");
2319                                 }
2320                         }
2321                         pic14_emitcode("mov","%s,r0",spname);
2322                         if (bitVectBitValue(rsave,R0_IDX))
2323                                 pic14_emitcode("mov","r0,b");     
2324                 }// else
2325                 //for (i = 0 ; i < pic14_nRegs ; i++) {
2326                 //        if (bitVectBitValue(rsave,i))
2327                 //      pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2328                 //}
2329                 
2330                 dtype = operandType(IC_LEFT(ic));
2331                 if (currFunc && dtype && 
2332                         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2333                         IFFUNC_ISISR(currFunc->type) &&
2334                         !ic->bankSaved) 
2335                         
2336                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2337                 
2338 }
2339 /*-----------------------------------------------------------------*/
2340 /* unsaveRegisters - pop the pushed registers                                      */
2341 /*-----------------------------------------------------------------*/
2342 static void unsaveRegisters (iCode *ic)
2343 {
2344         int i;
2345         bitVect *rsave;
2346         
2347         FENTRY;
2348
2349         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2350         /* find the registers in use at this time 
2351         and push them away to safety */
2352         rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2353                 ic->rUsed);
2354         
2355         if (options.useXstack) {
2356                 pic14_emitcode("mov","r0,%s",spname); 
2357                 for (i =  pic14_nRegs ; i >= 0 ; i--) {
2358                         if (bitVectBitValue(rsave,i)) {
2359                                 pic14_emitcode("dec","r0");
2360                                 pic14_emitcode("movx","a,@r0");
2361                                 if (i == R0_IDX)
2362                                         pic14_emitcode("mov","b,a");
2363                                 else
2364                                         pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2365                         }       
2366                         
2367                 }
2368                 pic14_emitcode("mov","%s,r0",spname);
2369                 if (bitVectBitValue(rsave,R0_IDX))
2370                         pic14_emitcode("mov","r0,b");
2371         } //else
2372         //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2373         //      if (bitVectBitValue(rsave,i))
2374         //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2375         //}
2376         
2377 }  
2378
2379
2380 /*-----------------------------------------------------------------*/
2381 /* pushSide -                            */
2382 /*-----------------------------------------------------------------*/
2383 static void pushSide(operand * oper, int size)
2384 {
2385 #if 0
2386         int offset = 0;
2387         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2388         while (size--) {
2389                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2390                 if (AOP_TYPE(oper) != AOP_REG &&
2391                         AOP_TYPE(oper) != AOP_DIR &&
2392                         strcmp(l,"a") ) {
2393                         pic14_emitcode("mov","a,%s",l);
2394                         pic14_emitcode("push","acc");
2395                 } else
2396                         pic14_emitcode("push","%s",l);
2397         }
2398 #endif
2399 }
2400
2401 /*-----------------------------------------------------------------*/
2402 /* assignResultValue -                           */
2403 /*-----------------------------------------------------------------*/
2404 static void assignResultValue(operand * oper)
2405 {
2406         int size = AOP_SIZE(oper);
2407         int offset = 0;
2408         
2409         FENTRY;
2410
2411         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2412         
2413         DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2414         
2415         /* assign MSB first (passed via WREG) */
2416         while (size--) {
2417                 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2418                 GpsuedoStkPtr++;
2419         }
2420 }
2421
2422
2423 /*-----------------------------------------------------------------*/
2424 /* genIpush - genrate code for pushing this gets a little complex  */
2425 /*-----------------------------------------------------------------*/
2426 static void genIpush (iCode *ic)
2427 {
2428         FENTRY;
2429         
2430         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2431 #if 0
2432         int size, offset = 0 ;
2433         char *l;
2434         
2435         
2436         /* if this is not a parm push : ie. it is spill push 
2437         and spill push is always done on the local stack */
2438         if (!ic->parmPush) {
2439                 
2440                 /* and the item is spilt then do nothing */
2441                 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2442                         return ;
2443                 
2444                 aopOp(IC_LEFT(ic),ic,FALSE);
2445                 size = AOP_SIZE(IC_LEFT(ic));
2446                 /* push it on the stack */
2447                 while(size--) {
2448                         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2449                         if (*l == '#') {
2450                                 MOVA(l);
2451                                 l = "acc";
2452                         }
2453                         pic14_emitcode("push","%s",l);
2454                 }
2455                 return ;                
2456         }
2457         
2458         /* this is a paramter push: in this case we call
2459         the routine to find the call and save those
2460         registers that need to be saved */   
2461         saveRegisters(ic);
2462         
2463         /* then do the push */
2464         aopOp(IC_LEFT(ic),ic,FALSE);
2465         
2466         
2467         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2468         size = AOP_SIZE(IC_LEFT(ic));
2469         
2470         while (size--) {
2471                 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2472                 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2473                         AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2474                         strcmp(l,"a") ) {
2475                         pic14_emitcode("mov","a,%s",l);
2476                         pic14_emitcode("push","acc");
2477                 } else
2478                         pic14_emitcode("push","%s",l);
2479         }         
2480         
2481         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2482 #endif
2483 }
2484
2485 /*-----------------------------------------------------------------*/
2486 /* genIpop - recover the registers: can happen only for spilling   */
2487 /*-----------------------------------------------------------------*/
2488 static void genIpop (iCode *ic)
2489 {
2490         FENTRY;
2491
2492         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2493         assert (!"genIpop -- unimplemented");
2494 #if 0
2495         int size,offset ;
2496         
2497         
2498         /* if the temp was not pushed then */
2499         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2500                 return ;
2501         
2502         aopOp(IC_LEFT(ic),ic,FALSE);
2503         size = AOP_SIZE(IC_LEFT(ic));
2504         offset = (size-1);
2505         while (size--) 
2506                 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2507                 FALSE,TRUE));
2508         
2509         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2510 #endif
2511 }
2512
2513 /*-----------------------------------------------------------------*/
2514 /* unsaverbank - restores the resgister bank from stack                    */
2515 /*-----------------------------------------------------------------*/
2516 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2517 {
2518         FENTRY;
2519
2520         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2521 #if 0
2522         int i;
2523         asmop *aop ;
2524         regs *r = NULL;
2525         
2526         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2527         if (popPsw) {
2528                 if (options.useXstack) {
2529                         aop = newAsmop(0);
2530                         r = getFreePtr(ic,&aop,FALSE);
2531                         
2532                         
2533                         pic14_emitcode("mov","%s,_spx",r->name);
2534                         pic14_emitcode("movx","a,@%s",r->name);
2535                         pic14_emitcode("mov","psw,a");
2536                         pic14_emitcode("dec","%s",r->name);
2537                         
2538                 }else
2539                         pic14_emitcode ("pop","psw");
2540         }
2541         
2542         for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2543                 if (options.useXstack) {           
2544                         pic14_emitcode("movx","a,@%s",r->name);
2545                         //pic14_emitcode("mov","(%s+%d),a",
2546                         //         regspic14[i].base,8*bank+regspic14[i].offset);
2547                         pic14_emitcode("dec","%s",r->name);
2548                         
2549                 } else 
2550                         pic14_emitcode("pop",""); //"(%s+%d)",
2551                 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2552         }
2553         
2554         if (options.useXstack) {
2555                 
2556                 pic14_emitcode("mov","_spx,%s",r->name);
2557                 freeAsmop(NULL,aop,ic,TRUE);
2558                 
2559         }
2560 #endif 
2561 }
2562
2563 /*-----------------------------------------------------------------*/
2564 /* saverbank - saves an entire register bank on the stack                  */
2565 /*-----------------------------------------------------------------*/
2566 static void saverbank (int bank, iCode *ic, bool pushPsw)
2567 {
2568         FENTRY;
2569
2570         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2571 #if 0
2572         int i;
2573         asmop *aop ;
2574         regs *r = NULL;
2575         
2576         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2577         if (options.useXstack) {
2578                 
2579                 aop = newAsmop(0);
2580                 r = getFreePtr(ic,&aop,FALSE);  
2581                 pic14_emitcode("mov","%s,_spx",r->name);
2582                 
2583         }
2584         
2585         for (i = 0 ; i < pic14_nRegs ;i++) {
2586                 if (options.useXstack) {
2587                         pic14_emitcode("inc","%s",r->name);
2588                         //pic14_emitcode("mov","a,(%s+%d)",
2589                         //               regspic14[i].base,8*bank+regspic14[i].offset);
2590                         pic14_emitcode("movx","@%s,a",r->name);                 
2591                 } else 
2592                         pic14_emitcode("push","");// "(%s+%d)",
2593                 //regspic14[i].base,8*bank+regspic14[i].offset);
2594         }
2595         
2596         if (pushPsw) {
2597                 if (options.useXstack) {
2598                         pic14_emitcode("mov","a,psw");
2599                         pic14_emitcode("movx","@%s,a",r->name); 
2600                         pic14_emitcode("inc","%s",r->name);
2601                         pic14_emitcode("mov","_spx,%s",r->name);                 
2602                         freeAsmop (NULL,aop,ic,TRUE);
2603                         
2604                 } else
2605                         pic14_emitcode("push","psw");
2606                 
2607                 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2608         }
2609         ic->bankSaved = 1;
2610 #endif
2611 }
2612
2613 /*-----------------------------------------------------------------*/
2614 /* genCall - generates a call statement                                                    */
2615 /*-----------------------------------------------------------------*/
2616 static void genCall (iCode *ic)
2617 {
2618         sym_link *dtype;         
2619         symbol *sym;
2620         char *name;
2621         int isExtern;
2622         
2623         FENTRY;
2624
2625         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2626         
2627         /* if caller saves & we have not saved then */
2628         if (!ic->regsSaved)
2629                 saveRegisters(ic);
2630         
2631                 /* if we are calling a function that is not using
2632                 the same register bank then we need to save the
2633         destination registers on the stack */
2634         dtype = operandType(IC_LEFT(ic));
2635         if (currFunc && dtype && 
2636                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2637                 IFFUNC_ISISR(currFunc->type) &&
2638                 !ic->bankSaved) 
2639                 
2640                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2641         
2642         /* if send set is not empty the assign */
2643         if (_G.sendSet) {
2644                 iCode *sic;
2645                 /* For the Pic port, there is no data stack.
2646                 * So parameters passed to functions are stored
2647                 * in registers. (The pCode optimizer will get
2648                 * rid of most of these :).
2649                 */
2650                 int psuedoStkPtr=-1;
2651                 int firstTimeThruLoop = 1;
2652                 
2653                 _G.sendSet = reverseSet(_G.sendSet);
2654                 
2655                 /* First figure how many parameters are getting passed */
2656                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2657                 sic = setNextItem(_G.sendSet)) {
2658                         
2659                         aopOp(IC_LEFT(sic),sic,FALSE);
2660                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2661                         freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2662                 }
2663                 
2664                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2665                 sic = setNextItem(_G.sendSet)) {
2666                         int size, offset = 0;
2667                         
2668                         aopOp(IC_LEFT(sic),sic,FALSE);
2669                         size = AOP_SIZE(IC_LEFT(sic));
2670                         
2671                         while (size--) {
2672                                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2673                                         AopType(AOP_TYPE(IC_LEFT(sic))));
2674                                 
2675                                 if(!firstTimeThruLoop) {
2676                                         /* If this is not the first time we've been through the loop
2677                                         * then we need to save the parameter in a temporary
2678                                         * register. The last byte of the last parameter is
2679                                         * passed in W. */
2680                                         emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2681                                         
2682                                 }
2683                                 firstTimeThruLoop=0;
2684                                 
2685                                 mov2w_op (IC_LEFT(sic),  offset);
2686                                 offset++;
2687                         }
2688                         freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2689                 }
2690                 _G.sendSet = NULL;
2691         }
2692         /* make the call */
2693         sym = OP_SYMBOL(IC_LEFT(ic));
2694         name = sym->rname[0] ? sym->rname : sym->name;
2695         isExtern = IS_EXTERN(sym->etype) || pic14_inISR;
2696         if (isExtern) {
2697                 /* Extern functions and ISRs maybe on a different page;
2698                  * must call pagesel */
2699                 emitpcode(POC_PAGESEL,popGetWithString(name,1));
2700         }
2701         emitpcode(POC_CALL,popGetWithString(name,isExtern));
2702         if (isExtern) {
2703                 /* May have returned from a different page;
2704                  * must use pagesel to restore PCLATH before next
2705                  * goto or call instruction */
2706                 emitpcode(POC_PAGESEL,popGetWithString("$",0));
2707         }
2708         GpsuedoStkPtr=0;
2709         /* if we need assign a result value */
2710         if ((IS_ITEMP(IC_RESULT(ic)) && 
2711                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2712                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2713                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2714                 
2715                 _G.accInUse++;
2716                 aopOp(IC_RESULT(ic),ic,FALSE);
2717                 _G.accInUse--;
2718                 
2719                 assignResultValue(IC_RESULT(ic));
2720                 
2721                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2722                         AopType(AOP_TYPE(IC_RESULT(ic))));
2723                 
2724                 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2725         }
2726         
2727         /* if register bank was saved then pop them */
2728         if (ic->bankSaved)
2729                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2730         
2731         /* if we hade saved some registers then unsave them */
2732         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2733                 unsaveRegisters (ic);
2734         
2735         
2736 }
2737
2738 /*-----------------------------------------------------------------*/
2739 /* genPcall - generates a call by pointer statement                        */
2740 /*-----------------------------------------------------------------*/
2741 static void genPcall (iCode *ic)
2742 {
2743         sym_link *dtype;
2744         symbol *albl = newiTempLabel(NULL);
2745         symbol *blbl = newiTempLabel(NULL);
2746         PIC_OPCODE poc;
2747         pCodeOp *pcop;
2748         operand *left;
2749         
2750         FENTRY;
2751
2752         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2753         /* if caller saves & we have not saved then */
2754         if (!ic->regsSaved)
2755                 saveRegisters(ic);
2756         
2757                 /* if we are calling a function that is not using
2758                 the same register bank then we need to save the
2759         destination registers on the stack */
2760         dtype = operandType(IC_LEFT(ic));
2761         if (currFunc && dtype && 
2762                 IFFUNC_ISISR(currFunc->type) &&
2763                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2764                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2765         
2766         left = IC_LEFT(ic);
2767         aopOp(left,ic,FALSE);
2768         DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2769         
2770         poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2771         
2772         pushSide(IC_LEFT(ic), FPTRSIZE);
2773         
2774         /* if send set is not empty, assign parameters */
2775         if (_G.sendSet) {
2776                 
2777                 DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2778                 /* no way to pass args - W always gets used to make the call */
2779         }
2780         /* first idea - factor out a common helper function and call it.
2781         But don't know how to get it generated only once in its own block
2782         
2783         if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2784                 char *rname;
2785                 char *buffer;
2786                 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2787                 DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2788                 buffer = Safe_calloc(1,strlen(rname)+16);
2789                 sprintf(buffer, "%s_goto_helper", rname);
2790                 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2791                 free(buffer);
2792         }
2793         */
2794         emitpcode(POC_CALL,popGetLabel(albl->key));
2795         pcop = popGetLabel(blbl->key);
2796         emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2797         emitpcode(POC_GOTO,pcop);
2798         emitpLabel(albl->key);
2799         
2800         emitpcode(poc,popGetAddr(AOP(left),1,0));
2801         emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2802         emitpcode(poc,popGetAddr(AOP(left),0,0));
2803         emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2804         
2805         emitpLabel(blbl->key);
2806         
2807         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2808         
2809         /* if we need to assign a result value */
2810         if ((IS_ITEMP(IC_RESULT(ic)) &&
2811                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2812                 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2813                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2814                 
2815                 _G.accInUse++;
2816                 aopOp(IC_RESULT(ic),ic,FALSE);
2817                 _G.accInUse--;
2818
2819                 GpsuedoStkPtr = 0;
2820                 
2821                 assignResultValue(IC_RESULT(ic));
2822                 
2823                 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2824         }
2825         
2826         /* if register bank was saved then unsave them */
2827         if (currFunc && dtype && 
2828                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2829                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2830         
2831                 /* if we hade saved some registers then
2832         unsave them */
2833         if (ic->regsSaved)
2834                 unsaveRegisters (ic);
2835         
2836 }
2837
2838 /*-----------------------------------------------------------------*/
2839 /* resultRemat - result  is rematerializable                                       */
2840 /*-----------------------------------------------------------------*/
2841 static int resultRemat (iCode *ic)
2842 {
2843         //      DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2844         FENTRY;
2845
2846         if (SKIP_IC(ic) || ic->op == IFX)
2847                 return 0;
2848         
2849         if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2850                 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2851                 if (sym->remat && !POINTER_SET(ic)) 
2852                         return 1;
2853         }
2854         
2855         return 0;
2856 }
2857
2858 #if defined(__BORLANDC__) || defined(_MSC_VER)
2859 #define STRCASECMP stricmp
2860 #else
2861 #define STRCASECMP strcasecmp
2862 #endif
2863
2864 #if 0
2865 /*-----------------------------------------------------------------*/
2866 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2867 /*-----------------------------------------------------------------*/
2868 static bool inExcludeList(char *s)
2869 {
2870         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2871         int i =0;
2872         
2873         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2874         if (options.excludeRegs[i] &&
2875                 STRCASECMP(options.excludeRegs[i],"none") == 0)
2876                 return FALSE ;
2877         
2878         for ( i = 0 ; options.excludeRegs[i]; i++) {
2879                 if (options.excludeRegs[i] &&
2880                         STRCASECMP(s,options.excludeRegs[i]) == 0)
2881                         return TRUE;
2882         }
2883         return FALSE ;
2884 }
2885 #endif
2886
2887 /*-----------------------------------------------------------------*/
2888 /* genFunction - generated code for function entry                                 */
2889 /*-----------------------------------------------------------------*/
2890 static void genFunction (iCode *ic)
2891 {
2892         symbol *sym;
2893         sym_link *ftype;
2894         
2895         FENTRY;
2896
2897         DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2898         
2899         labelOffset += (max_key+4);
2900         max_key=0;
2901         GpsuedoStkPtr=0;
2902         _G.nRegsSaved = 0;
2903         /* create the function header */
2904         pic14_emitcode(";","-----------------------------------------");
2905         pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2906         pic14_emitcode(";","-----------------------------------------");
2907         
2908         /* prevent this symbol from being emitted as 'extern' */
2909         pic14_stringInSet(sym->rname, &pic14_localFunctions, 1);
2910
2911         pic14_emitcode("","%s:",sym->rname);
2912         addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2913         
2914         ftype = operandType(IC_LEFT(ic));
2915         
2916         /* if critical function then turn interrupts off */
2917         if (IFFUNC_ISCRITICAL(ftype))
2918                 pic14_emitcode("clr","ea");
2919         
2920                 /* here we need to generate the equates for the
2921         register bank if required */
2922 #if 0
2923         if (FUNC_REGBANK(ftype) != rbank) {
2924                 int i ;
2925                 
2926                 rbank = FUNC_REGBANK(ftype);
2927                 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2928                         if (strcmp(regspic14[i].base,"0") == 0)
2929                                 pic14_emitcode("","%s = 0x%02x",
2930                                 regspic14[i].dname,
2931                                 8*rbank+regspic14[i].offset);
2932                         else
2933                                 pic14_emitcode ("","%s = %s + 0x%02x",
2934                                 regspic14[i].dname,
2935                                 regspic14[i].base,
2936                                 8*rbank+regspic14[i].offset);
2937                 }
2938         }
2939 #endif
2940         
2941         /* if this is an interrupt service routine */
2942         pic14_inISR = 0;
2943         if (IFFUNC_ISISR(sym->type)) {
2944                 pic14_inISR = 1;
2945         /*  already done in pic14createInterruptVect() - delete me
2946         addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2947         emitpcodeNULLop(POC_NOP);
2948         emitpcodeNULLop(POC_NOP);
2949         emitpcodeNULLop(POC_NOP);
2950                 */
2951                 emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2952                 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2953                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2954                 emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2955                 emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2956                 emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2957                 emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2958                 
2959                 pBlockConvert2ISR(pb);
2960                 pic14_hasInterrupt = 1;
2961 #if 0  
2962                 if (!inExcludeList("acc"))              
2963                         pic14_emitcode ("push","acc");  
2964                 if (!inExcludeList("b"))
2965                         pic14_emitcode ("push","b");
2966                 if (!inExcludeList("dpl"))
2967                         pic14_emitcode ("push","dpl");
2968                 if (!inExcludeList("dph"))
2969                         pic14_emitcode ("push","dph");
2970                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2971                 {
2972                         pic14_emitcode ("push", "dpx");
2973                         /* Make sure we're using standard DPTR */
2974                         pic14_emitcode ("push", "dps");
2975                         pic14_emitcode ("mov", "dps, #0x00");
2976                         if (options.stack10bit)
2977                         { 
2978                                 /* This ISR could conceivably use DPTR2. Better save it. */
2979                                 pic14_emitcode ("push", "dpl1");
2980                                 pic14_emitcode ("push", "dph1");
2981                                 pic14_emitcode ("push", "dpx1");
2982                         }
2983                 }
2984                 /* if this isr has no bank i.e. is going to
2985                 run with bank 0 , then we need to save more
2986                 registers :-) */
2987                 if (!FUNC_REGBANK(sym->type)) {
2988                         
2989                 /* if this function does not call any other
2990                 function then we can be economical and
2991                         save only those registers that are used */
2992                         if (! IFFUNC_HASFCALL(sym->type)) {
2993                                 int i;
2994                                 
2995                                 /* if any registers used */
2996                                 if (sym->regsUsed) {
2997                                         /* save the registers used */
2998                                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2999                                                 if (bitVectBitValue(sym->regsUsed,i) ||
3000                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3001                                                         pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);               
3002                                         }
3003                                 }
3004                                 
3005                         } else {
3006                         /* this function has    a function call cannot
3007                         determines register usage so we will have the
3008                                 entire bank */
3009                                 saverbank(0,ic,FALSE);
3010                         }       
3011                 }
3012 #endif
3013         } else {
3014         /* if callee-save to be used for this function
3015                 then save the registers being used in this function */
3016                 if (IFFUNC_CALLEESAVES(sym->type)) {
3017                         int i;
3018                         
3019                         /* if any registers used */
3020                         if (sym->regsUsed) {
3021                                 /* save the registers used */
3022                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3023                                         if (bitVectBitValue(sym->regsUsed,i) ||
3024                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
3025                                                 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
3026                                                 _G.nRegsSaved++;
3027                                         }
3028                                 }
3029                         }
3030                 }
3031         }
3032         
3033         /* set the register bank to the desired value */
3034         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
3035                 pic14_emitcode("push","psw");
3036                 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);       
3037         }
3038         
3039         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3040                 
3041                 if (options.useXstack) {
3042                         pic14_emitcode("mov","r0,%s",spname);
3043                         pic14_emitcode("mov","a,_bp");
3044                         pic14_emitcode("movx","@r0,a");
3045                         pic14_emitcode("inc","%s",spname);
3046                 }
3047                 else
3048                 {
3049                         /* set up the stack */
3050                         pic14_emitcode ("push","_bp");   /* save the callers stack      */
3051                 }
3052                 pic14_emitcode ("mov","_bp,%s",spname);
3053         }
3054         
3055         /* adjust the stack for the function */
3056         if (sym->stack) {
3057                 
3058                 int i = sym->stack;
3059                 if (i > 256 ) 
3060                         werror(W_STACK_OVERFLOW,sym->name);
3061                 
3062                 if (i > 3 && sym->recvSize < 4) {                
3063                         
3064                         pic14_emitcode ("mov","a,sp");
3065                         pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3066                         pic14_emitcode ("mov","sp,a");
3067                         
3068                 }
3069                 else
3070                         while(i--)
3071                                 pic14_emitcode("inc","sp");
3072         }
3073         
3074         if (sym->xstack) {
3075                 
3076                 pic14_emitcode ("mov","a,_spx");
3077                 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3078                 pic14_emitcode ("mov","_spx,a");
3079         }
3080         
3081 }
3082
3083 /*-----------------------------------------------------------------*/
3084 /* genEndFunction - generates epilogue for functions                       */
3085 /*-----------------------------------------------------------------*/
3086 static void genEndFunction (iCode *ic)
3087 {
3088         symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3089         
3090         FENTRY;
3091
3092         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3093         
3094         if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3095         {
3096                 pic14_emitcode ("mov","%s,_bp",spname);
3097         }
3098         
3099         /* if use external stack but some variables were
3100         added to the local stack then decrement the
3101         local stack */
3102         if (options.useXstack && sym->stack) {    
3103                 pic14_emitcode("mov","a,sp");
3104                 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3105                 pic14_emitcode("mov","sp,a");
3106         }
3107         
3108         
3109         if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3110                 if (options.useXstack) {
3111                         pic14_emitcode("mov","r0,%s",spname);
3112                         pic14_emitcode("movx","a,@r0");
3113                         pic14_emitcode("mov","_bp,a");
3114                         pic14_emitcode("dec","%s",spname);
3115                 }
3116                 else
3117                 {
3118                         pic14_emitcode ("pop","_bp");
3119                 }
3120         }
3121         
3122         /* restore the register bank    */        
3123         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3124                 pic14_emitcode ("pop","psw");
3125         
3126         if (IFFUNC_ISISR(sym->type)) {
3127                 
3128                 /* now we need to restore the registers */
3129                 /* if this isr has no bank i.e. is going to
3130                 run with bank 0 , then we need to save more
3131 registers :-) */
3132                 if (!FUNC_REGBANK(sym->type)) {
3133                         
3134                 /* if this function does not call any other
3135                 function then we can be economical and
3136                         save only those registers that are used */
3137                         if (! IFFUNC_HASFCALL(sym->type)) {
3138                                 int i;
3139                                 
3140                                 /* if any registers used */
3141                                 if (sym->regsUsed) {
3142                                         /* save the registers used */
3143                                         for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3144                                                 if (bitVectBitValue(sym->regsUsed,i) ||
3145                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3146                                                         pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3147                                         }
3148                                 }
3149                                 
3150                         } else {
3151                         /* this function has    a function call cannot
3152                         determines register usage so we will have the
3153                                 entire bank */
3154                                 unsaverbank(0,ic,FALSE);
3155                         }       
3156                 }
3157 #if 0
3158                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3159                 {
3160                         if (options.stack10bit)
3161                         {
3162                                 pic14_emitcode ("pop", "dpx1");
3163                                 pic14_emitcode ("pop", "dph1");
3164                                 pic14_emitcode ("pop", "dpl1");
3165                         } 
3166                         pic14_emitcode ("pop", "dps");
3167                         pic14_emitcode ("pop", "dpx");
3168                 }
3169                 if (!inExcludeList("dph"))
3170                         pic14_emitcode ("pop","dph");
3171                 if (!inExcludeList("dpl"))
3172                         pic14_emitcode ("pop","dpl");
3173                 if (!inExcludeList("b"))
3174                         pic14_emitcode ("pop","b");
3175                 if (!inExcludeList("acc"))
3176                         pic14_emitcode ("pop","acc");
3177                 
3178                 if (IFFUNC_ISCRITICAL(sym->type))
3179                         pic14_emitcode("setb","ea");
3180 #endif
3181                 
3182                 /* if debug then send end of function */
3183                 /*      if (options.debug && currFunc) { */
3184                 if (currFunc) {
3185                         debugFile->writeEndFunction (currFunc, ic, 1);
3186                 }
3187                 
3188                 pic14_emitcode ("reti","");
3189                 emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
3190                 emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
3191                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
3192                 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3193                 emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
3194                 emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
3195                 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3196                 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3197                 emitpcodeNULLop(POC_RETFIE);
3198         }
3199         else {
3200                 if (IFFUNC_ISCRITICAL(sym->type))
3201                         pic14_emitcode("setb","ea");
3202                 
3203                 if (IFFUNC_CALLEESAVES(sym->type)) {
3204                         int i;
3205                         
3206                         /* if any registers used */
3207                         if (sym->regsUsed) {
3208                                 /* save the registers used */
3209                                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3210                                         if (bitVectBitValue(sym->regsUsed,i) ||
3211                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3212                                                 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3213                                 }
3214                         }
3215                         
3216                 }
3217                 
3218                 /* if debug then send end of function */
3219                 if (currFunc) {
3220                         debugFile->writeEndFunction (currFunc, ic, 1);
3221                 }
3222                 
3223                 pic14_emitcode ("return","");
3224                 emitpcodeNULLop(POC_RETURN);
3225                 
3226                 /* Mark the end of a function */
3227                 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3228         }
3229         
3230 }
3231
3232 /*-----------------------------------------------------------------*/
3233 /* genRet - generate code for return statement                                     */
3234 /*-----------------------------------------------------------------*/
3235 static void genRet (iCode *ic)
3236 {
3237         int size,offset = 0;
3238         
3239         FENTRY;
3240
3241         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3242         /* if we have no return value then
3243         just generate the "ret" */
3244         if (!IC_LEFT(ic)) 
3245                 goto jumpret;           
3246         
3247                 /* we have something to return then
3248         move the return value into place */
3249         aopOp(IC_LEFT(ic),ic,FALSE);
3250         size = AOP_SIZE(IC_LEFT(ic));
3251
3252         for (offset = 0; offset < size; offset++)
3253         {
3254                 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3255         }
3256         
3257         freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3258         
3259 jumpret:
3260         /* generate a jump to the return label
3261         if the next is not the return statement */
3262         if (!(ic->next && ic->next->op == LABEL &&
3263                 IC_LABEL(ic->next) == returnLabel)) {
3264                 
3265                 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3266         }
3267         
3268 }
3269
3270 /*-----------------------------------------------------------------*/
3271 /* genLabel - generates a label                                                                    */
3272 /*-----------------------------------------------------------------*/
3273 static void genLabel (iCode *ic)
3274 {
3275         FENTRY;
3276
3277         /* special case never generate */
3278         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3279         if (IC_LABEL(ic) == entryLabel)
3280                 return ;
3281         
3282         emitpLabel(IC_LABEL(ic)->key);
3283         pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3284 }
3285
3286 /*-----------------------------------------------------------------*/
3287 /* genGoto - generates a goto                                                                      */
3288 /*-----------------------------------------------------------------*/
3289 //tsd
3290 static void genGoto (iCode *ic)
3291 {
3292         FENTRY;
3293
3294         emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3295         pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3296 }
3297
3298
3299 /*-----------------------------------------------------------------*/
3300 /* genMultbits :- multiplication of bits                                                   */
3301 /*-----------------------------------------------------------------*/
3302 static void genMultbits (operand *left, 
3303                                                  operand *right, 
3304                                                  operand *result)
3305 {
3306         FENTRY;
3307         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3308         
3309         if(!pic14_sameRegs(AOP(result),AOP(right)))
3310                 emitpcode(POC_BSF,      popGet(AOP(result),0));
3311         
3312         emitpcode(POC_BTFSC,popGet(AOP(right),0));
3313         emitpcode(POC_BTFSS,popGet(AOP(left),0));
3314         emitpcode(POC_BCF,  popGet(AOP(result),0));
3315         
3316 }
3317
3318
3319 /*-----------------------------------------------------------------*/
3320 /* genMultOneByte : 8 bit multiplication & division                        */
3321 /*-----------------------------------------------------------------*/
3322 static void genMultOneByte (operand *left,
3323                                                         operand *right,
3324                                                         operand *result)
3325 {
3326         char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3327         
3328         // symbol *lbl ;
3329         int size,offset,i;
3330         
3331         
3332         FENTRY;
3333         
3334         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3335         DEBUGpic14_AopType(__LINE__,left,right,result);
3336         DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3337         
3338         /* (if two literals, the value is computed before) */
3339         /* if one literal, literal on the right */
3340         if (AOP_TYPE(left) == AOP_LIT){
3341                 operand *t = right;
3342                 right = left;
3343                 left = t;
3344         }
3345
3346         assert (AOP_SIZE(left) == AOP_SIZE(right));
3347         
3348         size = min(AOP_SIZE(result),AOP_SIZE(left));
3349         offset = Gstack_base_addr - (2*size - 1);
3350
3351         /* pass right operand as argument */
3352         for (i=0; i < size; i++)
3353         {
3354                 mov2w (AOP(right), i);
3355                 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3356         } // for
3357         
3358         /* pass left operand as argument */
3359         for (i=0; i < size; i++)
3360         {
3361                 mov2w (AOP(left), i);
3362                 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3363         } // for
3364         assert (offset == Gstack_base_addr);
3365         
3366         /* call library routine */
3367         assert (size > 0 && size <= 4);
3368         call_libraryfunc (func[size]);
3369         
3370         /* assign result */
3371         movwf (AOP(result), size-1);
3372         for (i=0; i < size - 1; i++)
3373         {
3374                 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3375                 movwf (AOP(result), size - 2 - i);
3376         } // for
3377
3378         /* now (zero-/sign) extend the result to its size */
3379         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3380 }
3381
3382 /*-----------------------------------------------------------------*/
3383 /* genMult - generates code for multiplication                                     */
3384 /*-----------------------------------------------------------------*/
3385 static void genMult (iCode *ic)
3386 {
3387         operand *left = IC_LEFT(ic);
3388         operand *right = IC_RIGHT(ic);
3389         operand *result= IC_RESULT(ic); 
3390         
3391         FENTRY;
3392
3393         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3394         /* assign the amsops */
3395         aopOp (left,ic,FALSE);
3396         aopOp (right,ic,FALSE);
3397         aopOp (result,ic,TRUE);
3398         
3399         DEBUGpic14_AopType(__LINE__,left,right,result);
3400         
3401         /* special cases first */
3402         /* both are bits */
3403         if (AOP_TYPE(left) == AOP_CRY &&
3404                 AOP_TYPE(right)== AOP_CRY) {
3405                 genMultbits(left,right,result);
3406                 goto release ;
3407         }
3408         
3409         /* if both are of size == 1 */
3410         if (AOP_SIZE(left) == 1 &&
3411                 AOP_SIZE(right) == 1 ) {
3412                 genMultOneByte(left,right,result);
3413                 goto release ;
3414         }
3415         
3416         /* should have been converted to function call */
3417         assert(0) ;
3418         
3419 release :
3420         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3421         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3422         freeAsmop(result,NULL,ic,TRUE); 
3423 }
3424
3425 /*-----------------------------------------------------------------*/
3426 /* genDivbits :- division of bits                                                                  */
3427 /*-----------------------------------------------------------------*/
3428 static void genDivbits (operand *left, 
3429                                                 operand *right, 
3430                                                 operand *result)
3431 {
3432         
3433         char *l;
3434         
3435         FENTRY;
3436
3437         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3438         /* the result must be bit */      
3439         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3440         l = aopGet(AOP(left),0,FALSE,FALSE);
3441         
3442         MOVA(l);          
3443         
3444         pic14_emitcode("div","ab");
3445         pic14_emitcode("rrc","a");
3446         aopPut(AOP(result),"c",0);
3447 }
3448
3449 /*-----------------------------------------------------------------*/
3450 /* genDivOneByte : 8 bit division                                                                  */
3451 /*-----------------------------------------------------------------*/
3452 static void genDivOneByte (operand *left,
3453                                                    operand *right,
3454                                                    operand *result)
3455 {
3456         int size;
3457         
3458         FENTRY;
3459         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3460         
3461         assert (AOP_SIZE(result) == 1);
3462         assert (AOP_SIZE(right) == 1);
3463         assert (AOP_SIZE(left) == 1);
3464
3465         size = min(AOP_SIZE(result),AOP_SIZE(left));
3466
3467         if (AOP_TYPE(right) == AOP_LIT)
3468         {
3469                 /* XXX: might add specialized code */
3470         }
3471
3472         if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3473         {
3474                 /* unsigned division */
3475         #if 1
3476                 mov2w(AOP(right),0);
3477                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3478                 mov2w(AOP(left),0);
3479                 call_libraryfunc("__divuchar");
3480                 movwf(AOP(result),0);
3481         #else
3482                 pCodeOp *temp;
3483                 symbol *lbl;
3484
3485                 temp = popGetTempReg();
3486                 lbl = newiTempLabel(NULL);
3487                 
3488                 /* XXX: improve this naive approach:
3489                    [result] = [a] / [b]
3490                         ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3491
3492                    In PIC assembler:
3493                    movf  left,W
3494                    movwf temp           // temp <-- left
3495                    movf  right,W        // W <-- right
3496                    clrf  result
3497                    label1:
3498                    incf  result
3499                    subwf temp,F         // temp <-- temp - W
3500                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if temp < W
3501                    goto  label1
3502                    decf result          // we just subtract once too often
3503                  */
3504
3505                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3506                 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3507                 
3508                 mov2w(AOP(left),0);
3509                 emitpcode(POC_MOVWF, temp);
3510                 mov2w(AOP(right),0);
3511                 emitpcode(POC_CLRF, popGet(AOP(result),0));
3512
3513                 emitpLabel(lbl->key);
3514                 emitpcode(POC_INCF, popGet(AOP(result),0));
3515                 emitpcode(POC_SUBWF, temp);
3516                 emitSKPNC;
3517                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3518                 emitpcode(POC_DECF, popGet(AOP(result),0));
3519         #endif
3520         }
3521         else
3522         {
3523                 /* signed division */
3524                 mov2w(AOP(right),0);
3525                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3526                 mov2w(AOP(left),0);
3527                 call_libraryfunc("__divschar");
3528                 movwf(AOP(result),0);
3529         }
3530
3531         /* now performed the signed/unsigned division -- extend result */
3532         addSign(result, 1, !SPEC_USIGN(operandType(result)));
3533 }
3534
3535 /*-----------------------------------------------------------------*/
3536 /* genDiv - generates code for division                            */
3537 /*-----------------------------------------------------------------*/
3538 static void genDiv (iCode *ic)
3539 {
3540         operand *left = IC_LEFT(ic);
3541         operand *right = IC_RIGHT(ic);
3542         operand *result= IC_RESULT(ic); 
3543         
3544         FENTRY;
3545         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3546         /* assign the amsops */
3547         aopOp (left,ic,FALSE);
3548         aopOp (right,ic,FALSE);
3549         aopOp (result,ic,TRUE);
3550         
3551         /* special cases first */
3552         /* both are bits */
3553         if (AOP_TYPE(left) == AOP_CRY &&
3554                 AOP_TYPE(right)== AOP_CRY) {
3555                 genDivbits(left,right,result);
3556                 goto release ;
3557         }
3558         
3559         /* if both are of size == 1 */
3560         if (AOP_SIZE(left) == 1 &&
3561                 AOP_SIZE(right) == 1 ) {
3562                 genDivOneByte(left,right,result);
3563                 goto release ;
3564         }
3565         
3566         /* should have been converted to function call */
3567         assert(0);
3568 release :
3569         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3570         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3571         freeAsmop(result,NULL,ic,TRUE); 
3572 }
3573
3574 /*-----------------------------------------------------------------*/
3575 /* genModbits :- modulus of bits                                                                   */
3576 /*-----------------------------------------------------------------*/
3577 static void genModbits (operand *left, 
3578                                                 operand *right, 
3579                                                 operand *result)
3580 {
3581         
3582         char *l;
3583         
3584         FENTRY;
3585         /* the result must be bit */      
3586         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3587         l = aopGet(AOP(left),0,FALSE,FALSE);
3588         
3589         MOVA(l);
3590         
3591         pic14_emitcode("div","ab");
3592         pic14_emitcode("mov","a,b");
3593         pic14_emitcode("rrc","a");
3594         aopPut(AOP(result),"c",0);
3595 }
3596
3597 /*-----------------------------------------------------------------*/
3598 /* genModOneByte : 8 bit modulus                                                                   */
3599 /*-----------------------------------------------------------------*/
3600 static void genModOneByte (operand *left,
3601                                                    operand *right,
3602                                                    operand *result)
3603 {
3604         int size;
3605         
3606         FENTRY;
3607         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3608         
3609         assert (AOP_SIZE(result) == 1);
3610         assert (AOP_SIZE(right) == 1);
3611         assert (AOP_SIZE(left) == 1);
3612
3613         size = min(AOP_SIZE(result),AOP_SIZE(left));
3614
3615         if (AOP_TYPE(right) == AOP_LIT)
3616         {
3617                 /* XXX: might add specialized code */
3618         }
3619
3620         if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3621         {
3622                 /* unsigned division */
3623         #if 1
3624                 mov2w(AOP(right),0);
3625                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3626                 mov2w(AOP(left),0);
3627                 call_libraryfunc("__moduchar");
3628                 movwf(AOP(result),0);
3629         #else
3630                 pCodeOp *temp;
3631                 symbol *lbl;
3632
3633                 lbl = newiTempLabel(NULL);
3634                 
3635                 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3636
3637                 /* XXX: improve this naive approach:
3638                    [result] = [a] % [b]
3639                         ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3640
3641                    In PIC assembler:
3642                    movf  left,W
3643                    movwf result         // result <-- left
3644                    movf  right,W        // W <-- right
3645                    label1:
3646                    subwf result,F       // result <-- result - W
3647                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if result < W
3648                    goto  label1
3649                    addwf result, F      // we just subtract once too often
3650                  */
3651
3652                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3653                 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3654                 
3655                 if (!pic14_sameRegs(AOP(left), AOP(result)))
3656                 {
3657                         mov2w(AOP(left),0);
3658                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
3659                 }
3660                 mov2w(AOP(right),0);
3661
3662                 emitpLabel(lbl->key);
3663                 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3664                 emitSKPNC;
3665                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3666                 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3667         #endif
3668         }
3669         else
3670         {
3671                 /* signed division */
3672                 mov2w(AOP(right),0);
3673                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3674                 mov2w(AOP(left),0);
3675                 call_libraryfunc("__modschar");
3676                 movwf(AOP(result),0);
3677         }
3678
3679         /* now we performed the signed/unsigned modulus -- extend result */
3680         addSign(result, 1, !SPEC_USIGN(operandType(result)));
3681 }
3682
3683 /*-----------------------------------------------------------------*/
3684 /* genMod - generates code for division                                                    */
3685 /*-----------------------------------------------------------------*/
3686 static void genMod (iCode *ic)
3687 {
3688         operand *left = IC_LEFT(ic);
3689         operand *right = IC_RIGHT(ic);
3690         operand *result= IC_RESULT(ic);  
3691         
3692         FENTRY;
3693         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3694         /* assign the amsops */
3695         aopOp (left,ic,FALSE);
3696         aopOp (right,ic,FALSE);
3697         aopOp (result,ic,TRUE);
3698         
3699         /* special cases first */
3700         /* both are bits */
3701         if (AOP_TYPE(left) == AOP_CRY &&
3702                 AOP_TYPE(right)== AOP_CRY) {
3703                 genModbits(left,right,result);
3704                 goto release ;
3705         }
3706         
3707         /* if both are of size == 1 */
3708         if (AOP_SIZE(left) == 1 &&
3709                 AOP_SIZE(right) == 1 ) {
3710                 genModOneByte(left,right,result);
3711                 goto release ;
3712         }
3713         
3714         /* should have been converted to function call */
3715         assert(0);
3716         
3717 release :
3718         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3719         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3720         freeAsmop(result,NULL,ic,TRUE); 
3721 }
3722
3723 /*-----------------------------------------------------------------*/
3724 /* genIfxJump :- will create a jump depending on the ifx                   */
3725 /*-----------------------------------------------------------------*/
3726 /*
3727 note: May need to add parameter to indicate when a variable is in bit space.
3728 */
3729 static void genIfxJump (iCode *ic, char *jval)
3730 {
3731         
3732         FENTRY;
3733         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3734         /* if true label then we jump if condition
3735         supplied is true */
3736         if ( IC_TRUE(ic) ) {
3737                 
3738                 if(strcmp(jval,"a") == 0)
3739                         emitSKPZ;
3740                 else if (strcmp(jval,"c") == 0)
3741                         emitSKPC;
3742                 else {
3743                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3744                         emitpcode(POC_BTFSC,    newpCodeOpBit(jval,-1,1));
3745                 }
3746                 
3747                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3748                 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3749                 
3750         }
3751         else {
3752                 /* false label is present */
3753                 if(strcmp(jval,"a") == 0)
3754                         emitSKPNZ;
3755                 else if (strcmp(jval,"c") == 0)
3756                         emitSKPNC;
3757                 else {
3758                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3759                         emitpcode(POC_BTFSS,    newpCodeOpBit(jval,-1,1));
3760                 }
3761                 
3762                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3763                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3764                 
3765         }
3766         
3767         
3768         /* mark the icode as generated */
3769         ic->generated = 1;
3770 }
3771
3772 #if 0
3773 /*-----------------------------------------------------------------*/
3774 /* genSkip                                                                                                                 */
3775 /*-----------------------------------------------------------------*/
3776 static void genSkip(iCode *ifx,int status_bit)
3777 {
3778         FENTRY;
3779         if(!ifx)
3780                 return;
3781         
3782         if ( IC_TRUE(ifx) ) {
3783                 switch(status_bit) {
3784                 case 'z':
3785                         emitSKPNZ;
3786                         break;
3787                         
3788                 case 'c':
3789                         emitSKPNC;
3790                         break;
3791                         
3792                 case 'd':
3793                         emitSKPDC;
3794                         break;
3795                         
3796                 }
3797                 
3798                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3799                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3800                 
3801         } else {
3802                 
3803                 switch(status_bit) {
3804                         
3805                 case 'z':
3806                         emitSKPZ;
3807                         break;
3808                         
3809                 case 'c':
3810                         emitSKPC;
3811                         break;
3812                         
3813                 case 'd':
3814                         emitSKPDC;
3815                         break;
3816                 }
3817                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3818                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3819                 
3820         }
3821         
3822 }
3823 #endif
3824
3825 /*-----------------------------------------------------------------*/
3826 /* genSkipc                                                                                                        */
3827 /*-----------------------------------------------------------------*/
3828 static void genSkipc(resolvedIfx *rifx)
3829 {
3830         FENTRY;
3831         if(!rifx)
3832                 return;
3833         
3834         if(rifx->condition)
3835                 emitSKPNC;
3836         else
3837                 emitSKPC;
3838         
3839         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3840         emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3841         rifx->generated = 1;
3842 }
3843
3844 #if 0
3845 /*-----------------------------------------------------------------*/
3846 /* genSkipz2                                                                                                       */
3847 /*-----------------------------------------------------------------*/
3848 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3849 {
3850         FENTRY;
3851         if(!rifx)
3852                 return;
3853         
3854         if( (rifx->condition ^ invert_condition) & 1)
3855                 emitSKPZ;
3856         else
3857                 emitSKPNZ;
3858         
3859         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3860         rifx->generated = 1;
3861 }
3862 #endif
3863
3864 #if 0
3865 /*-----------------------------------------------------------------*/
3866 /* genSkipz                                                        */
3867 /*-----------------------------------------------------------------*/
3868 static void genSkipz(iCode *ifx, int condition)
3869 {
3870         FENTRY;
3871         assert (ifx != NULL);
3872         
3873         if(condition)
3874                 emitSKPNZ;
3875         else
3876                 emitSKPZ;
3877         
3878         if ( IC_TRUE(ifx) )
3879                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3880         else
3881                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3882         
3883         if ( IC_TRUE(ifx) )
3884                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3885         else
3886                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3887         
3888 }
3889 #endif
3890
3891 #if 0
3892 /*-----------------------------------------------------------------*/
3893 /* genSkipCond                                                     */
3894 /*-----------------------------------------------------------------*/
3895 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3896 {
3897         FENTRY;
3898         if(!rifx)
3899                 return;
3900         
3901         if(rifx->condition)
3902                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3903         else
3904                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3905         
3906         
3907         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3908         rifx->generated = 1;
3909 }
3910 #endif
3911
3912 #if 0
3913 /*-----------------------------------------------------------------*/
3914 /* genChkZeroes :- greater or less than comparison                 */
3915 /*     For each byte in a literal that is zero, inclusive or the   */
3916 /*     the corresponding byte in the operand with W                */
3917 /*     returns true if any of the bytes are zero                   */
3918 /*-----------------------------------------------------------------*/
3919 static int genChkZeroes(operand *op, int lit,  int size)
3920 {
3921         
3922         int i;
3923         int flag =1;
3924         
3925         while(size--) {
3926                 i = (lit >> (size*8)) & 0xff;
3927                 
3928                 if(i==0) {
3929                         if(flag) 
3930                                 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3931                         else
3932                                 emitpcode(POC_IORFW, popGet(AOP(op),size));
3933                         flag = 0;
3934                 }
3935         }
3936         
3937         return (flag==0);
3938 }
3939 #endif
3940
3941
3942 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3943 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
3944 #define DEBUGpc           emitpComment
3945
3946 /*-----------------------------------------------------------------*/
3947 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
3948 /*                  aop (if it's NOT a literal) or from lit (if    */
3949 /*                  aop is a literal)                              */
3950 /*-----------------------------------------------------------------*/
3951 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3952   if (aop->type == AOP_LIT) {
3953     emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3954   } else {
3955     emitpcode (POC_MOVFW, popGet (aop, offset));
3956   }
3957 }
3958
3959 /* genCmp performs a left < right comparison, stores
3960  * the outcome in result (if != NULL) and generates
3961  * control flow code for the ifx (if != NULL).
3962  *
3963  * This version leaves in sequences like
3964  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3965  * which should be optmized by the peephole
3966  * optimizer - RN 2005-01-01 */
3967 static void genCmp (operand *left,operand *right,
3968                     operand *result, iCode *ifx, int sign)
3969 {
3970   resolvedIfx rIfx;
3971   int size;
3972   int offs;
3973   symbol *templbl;
3974   operand *dummy;
3975   unsigned long lit;
3976   unsigned long mask;
3977   int performedLt;
3978   int invert_result = 0;
3979
3980   FENTRY;
3981   
3982   assert (AOP_SIZE(left) == AOP_SIZE(right));
3983   assert (left && right);
3984
3985   size = AOP_SIZE(right) - 1;
3986   mask = (0x100UL << (size*8)) - 1;
3987   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3988   performedLt = 1;
3989   templbl = NULL;
3990   lit = 0;
3991   
3992   resolveIfx (&rIfx, ifx);
3993
3994   /**********************************************************************
3995    * handle bits - bit compares are promoted to int compares seemingly! *
3996    **********************************************************************/
3997 #if 0
3998   // THIS IS COMPLETELY UNTESTED!
3999   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4000     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4001     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4002     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4003
4004     emitSETC;
4005     // 1 < {0,1} is false --> clear C by skipping the next instruction
4006     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4007     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4008     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4009     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4010     emitCLRC; // only skipped for left=0 && right=1
4011
4012     goto correct_result_in_carry;
4013   } // if
4014 #endif
4015
4016   /*************************************************
4017    * make sure that left is register (or the like) *
4018    *************************************************/
4019   if (!isAOP_REGlike(left)) {
4020     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4021     assert (isAOP_LIT(left));
4022     assert (isAOP_REGlike(right));
4023     // swap left and right
4024     // left < right <==> right > left <==> (right >= left + 1)
4025     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4026
4027     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4028       // MAXVALUE < right? always false
4029       if (performedLt) emitCLRC; else emitSETC;
4030       goto correct_result_in_carry;
4031     } // if
4032
4033     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4034     // that's why we handled it above.
4035     lit++;
4036
4037     dummy = left;
4038     left = right;
4039     right = dummy;
4040
4041     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4042   } else if (isAOP_LIT(right)) {
4043     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4044   } // if
4045
4046   assert (isAOP_REGlike(left)); // left must be register or the like
4047   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4048
4049   /*************************************************
4050    * special cases go here                         *
4051    *************************************************/
4052
4053   if (isAOP_LIT(right)) {
4054     if (!sign) {
4055       // unsigned comparison to a literal
4056       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4057       if (lit == 0) {
4058         // unsigned left < 0? always false
4059         if (performedLt) emitCLRC; else emitSETC;
4060         goto correct_result_in_carry;
4061       }
4062     } else {
4063       // signed comparison to a literal
4064       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4065       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4066         // signed left < 0x80000000? always false
4067         if (performedLt) emitCLRC; else emitSETC;
4068         goto correct_result_in_carry;
4069       } else if (lit == 0) {
4070         // compare left < 0; set CARRY if SIGNBIT(left) is set
4071         if (performedLt) emitSETC; else emitCLRC;
4072         emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
4073         if (performedLt) emitCLRC; else emitSETC;
4074         goto correct_result_in_carry;
4075       }
4076     } // if (!sign)
4077   } // right is literal
4078
4079   /*************************************************
4080    * perform a general case comparison             *
4081    * make sure we get CARRY==1 <==> left >= right  *
4082    *************************************************/
4083   // compare most significant bytes
4084   //DEBUGpc ("comparing bytes at offset %d", size);
4085   if (!sign) {
4086     // unsigned comparison
4087     pic14_mov2w_regOrLit (AOP(right), lit, size);
4088     emitpcode (POC_SUBFW, popGet (AOP(left), size));
4089   } else {
4090     // signed comparison
4091     // (add 2^n to both operands then perform an unsigned comparison)
4092     if (isAOP_LIT(right)) {
4093       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4094       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4095
4096       if (litbyte == 0x80) {
4097         // left >= 0x80 -- always true, but more bytes to come
4098         mov2w (AOP(left), size);
4099         emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
4100         emitSETC;
4101       } else {
4102         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4103         mov2w (AOP(left), size);
4104         emitpcode (POC_ADDLW, popGetLit (0x80));
4105         emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4106       } // if
4107     } else {
4108       pCodeOp *pctemp = popGetTempReg();
4109       mov2w (AOP(left), size);
4110       emitpcode (POC_ADDLW, popGetLit (0x80));
4111       emitpcode (POC_MOVWF, pctemp);
4112       mov2w (AOP(right), size);
4113       emitpcode (POC_ADDLW, popGetLit (0x80));
4114       emitpcode (POC_SUBFW, pctemp);
4115       popReleaseTempReg(pctemp);
4116     }
4117   } // if (!sign)
4118
4119   // compare remaining bytes (treat as unsigned case from above)
4120   templbl = newiTempLabel ( NULL );
4121   offs = size;
4122   while (offs--) {
4123     //DEBUGpc ("comparing bytes at offset %d", offs);
4124     emitSKPZ;
4125     emitpcode (POC_GOTO, popGetLabel (templbl->key));
4126     pic14_mov2w_regOrLit (AOP(right), lit, offs);
4127     emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4128   } // while (offs)
4129   emitpLabel (templbl->key);
4130   goto result_in_carry;
4131
4132 result_in_carry:
4133   
4134   /****************************************************
4135    * now CARRY contains the result of the comparison: *
4136    * SUBWF sets CARRY iff                             *
4137    * F-W >= 0 <==> F >= W <==> !(F < W)               *
4138    * (F=left, W=right)                                *
4139    ****************************************************/
4140
4141   if (performedLt) {
4142     invert_result = 1;
4143     // value will be used in the following genSkipc()
4144     rIfx.condition ^= 1;
4145   } // if
4146
4147 correct_result_in_carry:
4148
4149   // assign result to variable (if neccessary)
4150   if (result && AOP_TYPE(result) != AOP_CRY) {
4151     //DEBUGpc ("assign result");
4152     size = AOP_SIZE(result);
4153     while (size--) {
4154       emitpcode (POC_CLRF, popGet (AOP(result), size));
4155     } // while
4156     if (invert_result) {
4157       emitSKPC;
4158       emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4159     } else {
4160       emitpcode (POC_RLF, popGet (AOP(result), 0));
4161     }
4162   } // if (result)
4163
4164   // perform conditional jump
4165   if (ifx) {
4166     //DEBUGpc ("generate control flow");
4167     genSkipc (&rIfx);
4168     ifx->generated = 1;
4169   } // if
4170 }
4171
4172
4173 #if 0
4174 /* OLD VERSION -- BUGGY, DO NOT USE */
4175
4176 /*-----------------------------------------------------------------*/
4177 /* genCmp :- greater or less than comparison                       */
4178 /*-----------------------------------------------------------------*/
4179 static void genCmp (operand *left,operand *right,
4180                                         operand *result, iCode *ifx, int sign)
4181 {
4182         int size; //, offset = 0 ;
4183         unsigned long lit = 0L,i = 0;
4184         resolvedIfx rFalseIfx;
4185         //  resolvedIfx rTrueIfx;
4186         symbol *truelbl;
4187
4188         FENTRY;
4189         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4190         /*
4191         if(ifx) {
4192         DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4193         DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4194         }
4195         */
4196         
4197         resolveIfx(&rFalseIfx,ifx);
4198         truelbl  = newiTempLabel(NULL);
4199         size = max(AOP_SIZE(left),AOP_SIZE(right));
4200         
4201         DEBUGpic14_AopType(__LINE__,left,right,result);
4202         
4203 #define _swapp
4204         
4205         /* if literal is on the right then swap with left */
4206         if ((AOP_TYPE(right) == AOP_LIT)) {
4207                 operand *tmp = right ;
4208                 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4209                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4210 #ifdef _swapp
4211                 
4212                 lit = (lit - 1) & mask;
4213                 right = left;
4214                 left = tmp;
4215                 rFalseIfx.condition ^= 1;
4216 #endif
4217                 
4218         } else if ((AOP_TYPE(left) == AOP_LIT)) {
4219                 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4220         }
4221         
4222         
4223         //if(IC_TRUE(ifx) == NULL)
4224         /* if left & right are bit variables */
4225         if (AOP_TYPE(left) == AOP_CRY &&
4226                 AOP_TYPE(right) == AOP_CRY ) {
4227                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4228                 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4229         } else {
4230         /* subtract right from left if at the
4231         end the carry flag is set then we know that
4232                 left is greater than right */
4233                 
4234                 symbol *lbl  = newiTempLabel(NULL);
4235                 
4236 #ifndef _swapp
4237                 if(AOP_TYPE(right) == AOP_LIT) {
4238                         
4239                         //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4240                         
4241                         DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4242                         
4243                         /* special cases */
4244                         
4245                         if(lit == 0) {
4246                                 
4247                                 if(sign != 0) 
4248                                         genSkipCond(&rFalseIfx,left,size-1,7);
4249                                 else 
4250                                         /* no need to compare to 0...*/
4251                                         /* NOTE: this is a de-generate compare that most certainly 
4252                                         *       creates some dead code. */
4253                                         emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4254                                 
4255                                 if(ifx) ifx->generated = 1;
4256                                 return;
4257                                 
4258                         }
4259                         size--;
4260                         
4261                         if(size == 0) {
4262                                 //i = (lit >> (size*8)) & 0xff;
4263                                 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4264                                 
4265                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4266                                 
4267                                 i = ((0-lit) & 0xff);
4268                                 if(sign) {
4269                                         if( i == 0x81) { 
4270                                         /* lit is 0x7f, all signed chars are less than
4271                                                 * this except for 0x7f itself */
4272                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4273                                                 genSkipz2(&rFalseIfx,0);
4274                                         } else {
4275                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4276                                                 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4277                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4278                                         }
4279                                         
4280                                 } else {
4281                                         if(lit == 1) {
4282                                                 genSkipz2(&rFalseIfx,1);
4283                                         } else {
4284                                                 emitpcode(POC_ADDLW, popGetLit(i));
4285                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4286                                         }
4287                                 }
4288                                 
4289                                 if(ifx) ifx->generated = 1;
4290                                 return;
4291                         }
4292                         
4293                         /* chars are out of the way. now do ints and longs */
4294                         
4295                         
4296                         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4297                         
4298                         /* special cases */
4299                         
4300                         if(sign) {
4301                                 
4302                                 if(lit == 0) {
4303                                         genSkipCond(&rFalseIfx,left,size,7);
4304                                         if(ifx) ifx->generated = 1;
4305                                         return;
4306                                 }
4307                                 
4308                                 if(lit <0x100) {
4309                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4310                                         
4311                                         //rFalseIfx.condition ^= 1;
4312                                         //genSkipCond(&rFalseIfx,left,size,7);
4313                                         //rFalseIfx.condition ^= 1;
4314                                         
4315                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4316                                         if(rFalseIfx.condition)
4317                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4318                                         else
4319                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4320                                         
4321                                         emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4322                                         emitpcode(POC_ADDFW, popGet(AOP(left),0));
4323                                         emitpcode(POC_MOVFW, popGet(AOP(left),1));
4324                                         
4325                                         while(size > 1)
4326                                                 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4327                                         
4328                                         if(rFalseIfx.condition) {
4329                                                 emitSKPZ;
4330                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4331                                                 
4332                                         } else {
4333                                                 emitSKPNZ;
4334                                         }
4335                                         
4336                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4337                                         emitpLabel(truelbl->key);
4338                                         if(ifx) ifx->generated = 1;
4339                                         return;
4340                                         
4341                                 }
4342                                 
4343                                 if(size == 1) {
4344                                         
4345                                         if( (lit & 0xff) == 0) {
4346                                                 /* lower byte is zero */
4347                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4348                                                 i = ((lit >> 8) & 0xff) ^0x80;
4349                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4350                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4351                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4352                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4353                                                 
4354                                                 
4355                                                 if(ifx) ifx->generated = 1;
4356                                                 return;
4357                                                 
4358                                         }
4359                                 } else {
4360                                         /* Special cases for signed longs */
4361                                         if( (lit & 0xffffff) == 0) {
4362                                                 /* lower byte is zero */
4363                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4364                                                 i = ((lit >> 8*3) & 0xff) ^0x80;
4365                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4366                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4367                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4368                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4369                                                 
4370                                                 
4371                                                 if(ifx) ifx->generated = 1;
4372                                                 return;
4373                                                 
4374                                         }
4375                                         
4376                                 }
4377                                 
4378                                 
4379                                 if(lit & (0x80 << (size*8))) {
4380                                         /* lit is negative */
4381                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4382                                         
4383                                         //genSkipCond(&rFalseIfx,left,size,7);
4384                                         
4385                                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4386                                         
4387                                         if(rFalseIfx.condition)
4388                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4389                                         else
4390                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4391                                         
4392                                         
4393                                 } else {
4394                                         /* lit is positive */
4395                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4396                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4397                                         if(rFalseIfx.condition)
4398                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4399                                         else
4400                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4401                                         
4402                                 }
4403                                 
4404                                 /* There are no more special cases, so perform a general compare */
4405                                 
4406                                 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4407                                 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4408                                 
4409                                 while(size--) {
4410                                         
4411                                         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4412                                         emitSKPNZ;
4413                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4414                                 }
4415                                 //rFalseIfx.condition ^= 1;
4416                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4417                                 
4418                                 emitpLabel(truelbl->key);
4419                                 
4420                                 if(ifx) ifx->generated = 1;
4421                                 return;
4422                                 
4423                                 
4424                         }
4425
4426
4427                         /* sign is out of the way. So now do an unsigned compare */
4428                         DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4429
4430
4431                         /* General case - compare to an unsigned literal on the right.*/
4432
4433                         i = (lit >> (size*8)) & 0xff;
4434                         emitpcode(POC_MOVLW, popGetLit(i));
4435                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4436                         while(size--) {
4437                                 i = (lit >> (size*8)) & 0xff;
4438                                 
4439                                 if(i) {
4440                                         emitpcode(POC_MOVLW, popGetLit(i));
4441                                         emitSKPNZ;
4442                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4443                                 } else {
4444                                 /* this byte of the lit is zero, 
4445                                         *if it's not the last then OR in the variable */
4446                                         if(size)
4447                                                 emitpcode(POC_IORFW, popGet(AOP(left),size));
4448                                 }
4449                         }
4450
4451
4452                 emitpLabel(lbl->key);
4453                 //if(emitFinalCheck)
4454                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4455                 if(sign)
4456                         emitpLabel(truelbl->key);
4457
4458                 if(ifx) ifx->generated = 1;
4459                 return;
4460
4461
4462                 }
4463 #endif  // _swapp
4464
4465                 if(AOP_TYPE(left) == AOP_LIT) {
4466                         //symbol *lbl = newiTempLabel(NULL);
4467                         
4468                         //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4469                         
4470                         
4471                         DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4472                         
4473                         /* Special cases */
4474                         if((lit == 0) && (sign == 0)){
4475                                 
4476                                 size--;
4477                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4478                                 while(size) 
4479                                         emitpcode(POC_IORFW, popGet(AOP(right),--size));
4480                                 
4481                                 genSkipz2(&rFalseIfx,0);
4482                                 if(ifx) ifx->generated = 1;
4483                                 return;
4484                         }
4485                         
4486                         if(size==1) {
4487                                 /* Special cases */
4488                                 lit &= 0xff;
4489                                 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4490                                         /* degenerate compare can never be true */
4491                                         if(rFalseIfx.condition == 0)
4492                                                 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4493                                         
4494                                         if(ifx) ifx->generated = 1;
4495                                         return;
4496                                 }
4497                                 
4498                                 if(sign) {
4499                                         /* signed comparisons to a literal byte */
4500                                         
4501                                         int lp1 = (lit+1) & 0xff;
4502                                         
4503                                         DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4504                                         switch (lp1) {
4505                                         case 0:
4506                                                 rFalseIfx.condition ^= 1;
4507                                                 genSkipCond(&rFalseIfx,right,0,7);
4508                                                 break;
4509                                         case 0x7f:
4510                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4511                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4512                                                 genSkipz2(&rFalseIfx,1);
4513                                                 break;
4514                                         default:
4515                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4516                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4517                                                 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4518                                                 rFalseIfx.condition ^= 1;
4519                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4520                                                 break;
4521                                         }
4522                                         if(ifx) ifx->generated = 1;
4523                                 } else {
4524                                         /* unsigned comparisons to a literal byte */
4525                                         
4526                                         switch(lit & 0xff ) {
4527                                         case 0:
4528                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4529                                                 genSkipz2(&rFalseIfx,0);
4530                                                 if(ifx) ifx->generated = 1;
4531                                                 break;
4532                                         case 0x7f:
4533                                                 genSkipCond(&rFalseIfx,right,0,7);
4534                                                 if(ifx) ifx->generated = 1;
4535                                                 break;
4536                                                 
4537                                         default:
4538                                                 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4539                                                 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4540                                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4541                                                 rFalseIfx.condition ^= 1;
4542                                                 if (AOP_TYPE(result) == AOP_CRY) {
4543                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4544                                                         if(ifx) ifx->generated = 1;
4545                                                 } else {
4546                                                         DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4547                                                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4548                                                         emitpcode(POC_RLF, popGet(AOP(result),0));
4549                                                         emitpcode(POC_MOVLW, popGetLit(0x01));
4550                                                         emitpcode(POC_XORWF, popGet(AOP(result),0));
4551                                                 }       
4552                                                 break;
4553                                         }
4554                                 }
4555                                 
4556                                 //goto check_carry;
4557                                 return;
4558                                 
4559                         } else {
4560                                 
4561                                 /* Size is greater than 1 */
4562                                 
4563                                 if(sign) {
4564                                         int lp1 = lit+1;
4565                                         
4566                                         size--;
4567                                         
4568                                         if(lp1 == 0) {
4569                                                 /* this means lit = 0xffffffff, or -1 */
4570                                                 
4571                                                 
4572                                                 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4573                                                 rFalseIfx.condition ^= 1;
4574                                                 genSkipCond(&rFalseIfx,right,size,7);
4575                                                 if(ifx) ifx->generated = 1;
4576                                                 return;
4577                                         }
4578                                         
4579                                         if(lit == 0) {
4580                                                 int s = size;
4581                                                 
4582                                                 if(rFalseIfx.condition) {
4583                                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4584                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4585                                                 }
4586                                                 
4587                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4588                                                 while(size--)
4589                                                         emitpcode(POC_IORFW, popGet(AOP(right),size));
4590                                                 
4591                                                 
4592                                                 emitSKPZ;
4593                                                 if(rFalseIfx.condition) {
4594                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4595                                                         emitpLabel(truelbl->key);
4596                                                 }else {
4597                                                         rFalseIfx.condition ^= 1;
4598                                                         genSkipCond(&rFalseIfx,right,s,7);
4599                                                 }
4600                                                 
4601                                                 if(ifx) ifx->generated = 1;
4602                                                 return;
4603                                         }
4604                                         
4605                                         if((size == 1) &&  (0 == (lp1&0xff))) {
4606                                                 /* lower byte of signed word is zero */
4607                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4608                                                 i = ((lp1 >> 8) & 0xff) ^0x80;
4609                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4610                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4611                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4612                                                 rFalseIfx.condition ^= 1;
4613                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4614                                                 
4615                                                 
4616                                                 if(ifx) ifx->generated = 1;
4617                                                 return;
4618                                         }
4619                                         
4620                                         if(lit & (0x80 << (size*8))) {
4621                                                 /* Lit is less than zero */
4622                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4623                                                 //rFalseIfx.condition ^= 1;
4624                                                 //genSkipCond(&rFalseIfx,left,size,7);
4625                                                 //rFalseIfx.condition ^= 1;
4626                                                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4627                                                 //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4628                                                 
4629                                                 if(rFalseIfx.condition)
4630                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4631                                                 else
4632                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4633                                                 
4634                                                 
4635                                         } else {
4636                                                 /* Lit is greater than or equal to zero */
4637                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4638                                                 //rFalseIfx.condition ^= 1;
4639                                                 //genSkipCond(&rFalseIfx,right,size,7);
4640                                                 //rFalseIfx.condition ^= 1;
4641                                                 
4642                                                 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4643                                                 //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4644                                                 
4645                                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4646                                                 if(rFalseIfx.condition)
4647                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4648                                                 else
4649                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4650                                                 
4651                                         }
4652                                         
4653                                         
4654                                         emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4655                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4656                                         
4657                                         while(size--) {
4658                                                 
4659                                                 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4660                                                 emitSKPNZ;
4661                                                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4662                                         }
4663                                         rFalseIfx.condition ^= 1;
4664                                         //rFalseIfx.condition = 1;
4665                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4666                                         
4667                                         emitpLabel(truelbl->key);
4668                                         
4669                                         if(ifx) ifx->generated = 1;
4670                                         return;
4671                                         // end of if (sign)
4672                                 } else {
4673                                         
4674                                         /* compare word or long to an unsigned literal on the right.*/
4675                                         
4676                                         
4677                                         size--;
4678                                         if(lit < 0xff) {
4679                                                 DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4680                                                 switch (lit) {
4681                                                 case 0:
4682                                                         break; /* handled above */
4683                                                 /*
4684                                                 case 0xff:
4685                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4686                                                         while(size--)
4687                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4688                                                         genSkipz2(&rFalseIfx,0);
4689                                                         break;
4690                                                 */
4691                                                 default:
4692                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4693                                                         while(--size)
4694                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4695                                                         
4696                                                         emitSKPZ;
4697                                                         if(rFalseIfx.condition)
4698                                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4699                                                         else
4700                                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4701                                                         
4702                                                         
4703                                                         emitpcode(POC_MOVLW, popGetLit(lit+1));
4704                                                         emitpcode(POC_SUBFW, popGet(AOP(right),0));
4705                                                         
4706                                                         rFalseIfx.condition ^= 1;
4707                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4708                                                 }
4709                                                 
4710                                                 emitpLabel(truelbl->key);
4711                                                 
4712                                                 if(ifx) ifx->generated = 1;
4713                                                 return;
4714                                         }
4715                                         
4716                                         
4717                                         lit++;
4718                                         DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4719                                         i = (lit >> (size*8)) & 0xff;
4720                                         
4721                                         emitpcode(POC_MOVLW, popGetLit(i));
4722                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4723                                         
4724                                         while(size--) {
4725                                                 i = (lit >> (size*8)) & 0xff;
4726                                                 
4727                                                 if(i) {
4728                                                         emitpcode(POC_MOVLW, popGetLit(i));
4729                                                         emitSKPNZ;
4730                                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4731                                                 } else {
4732                                                 /* this byte of the lit is zero, 
4733                                                         *if it's not the last then OR in the variable */
4734                                                         if(size)
4735                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4736                                                 }
4737                                         }
4738                                         
4739                                         
4740                                         emitpLabel(lbl->key);
4741                                         
4742                                         rFalseIfx.condition ^= 1;
4743                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4744                                 }
4745                                 
4746                                 if(sign)
4747                                         emitpLabel(truelbl->key);
4748                                 if(ifx) ifx->generated = 1;
4749                                 return;
4750                         }
4751                 }
4752                 /* Compare two variables */
4753                 
4754                 DEBUGpic14_emitcode(";sign","%d",sign);
4755                 
4756                 size--;
4757                 if(sign) {
4758                         /* Sigh. thus sucks... */
4759                         if(size) {
4760                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4761                                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4762                                 emitpcode(POC_MOVLW, popGetLit(0x80));
4763                                 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4764                                 emitpcode(POC_XORFW, popGet(AOP(right),size));
4765                                 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4766                         } else {
4767                                 /* Signed char comparison */
4768                                 /* Special thanks to Nikolai Golovchenko for this snippet */
4769                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4770                                 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4771                                 emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4772                                 emitpcode(POC_XORFW, popGet(AOP(left),0));
4773                                 emitpcode(POC_XORFW, popGet(AOP(right),0));
4774                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4775                                 
4776                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4777                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4778                                 
4779                                 if(ifx) ifx->generated = 1;
4780                                 return;
4781                         }
4782                         
4783                 } else {
4784                         
4785                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4786                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4787                 }
4788                 
4789                 
4790                 /* The rest of the bytes of a multi-byte compare */
4791                 while (size) {
4792                         
4793                         emitSKPZ;
4794                         emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4795                         size--;
4796                         
4797                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4798                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4799                         
4800                         
4801                 }
4802                 
4803                 emitpLabel(lbl->key);
4804                 
4805                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4806                 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4807                         (AOP_TYPE(result) == AOP_REG)) {
4808                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4809                         emitpcode(POC_RLF, popGet(AOP(result),0));
4810                 } else {
4811                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4812                 }       
4813                 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4814                 if(ifx) ifx->generated = 1;
4815                 
4816                 return;
4817                 
4818         }
4819         
4820         // check_carry:
4821         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4822                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4823                 pic14_outBitC(result);
4824         } else {
4825                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4826                 /* if the result is used in the next
4827                 ifx conditional branch then generate
4828                 code a little differently */
4829                 if (ifx )
4830                         genIfxJump (ifx,"c");
4831                 else
4832                         pic14_outBitC(result);
4833                 /* leave the result in acc */
4834         }
4835         
4836 }
4837 #endif
4838
4839 /*-----------------------------------------------------------------*/
4840 /* genCmpGt :- greater than comparison                             */
4841 /*-----------------------------------------------------------------*/
4842 static void genCmpGt (iCode *ic, iCode *ifx)
4843 {
4844         operand *left, *right, *result;
4845         sym_link *letype , *retype;
4846         int sign ;
4847         
4848         FENTRY;
4849         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4850         left = IC_LEFT(ic);
4851         right= IC_RIGHT(ic);
4852         result = IC_RESULT(ic);
4853         
4854         letype = getSpec(operandType(left));
4855         retype =getSpec(operandType(right));
4856         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4857         /* assign the amsops */
4858         aopOp (left,ic,FALSE);
4859         aopOp (right,ic,FALSE);
4860         aopOp (result,ic,TRUE);
4861         
4862         genCmp(right, left, result, ifx, sign);
4863         
4864         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4865         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4866         freeAsmop(result,NULL,ic,TRUE); 
4867 }
4868
4869 /*-----------------------------------------------------------------*/
4870 /* genCmpLt - less than comparisons                                */
4871 /*-----------------------------------------------------------------*/
4872 static void genCmpLt (iCode *ic, iCode *ifx)
4873 {
4874         operand *left, *right, *result;
4875         sym_link *letype , *retype;
4876         int sign ;
4877         
4878         FENTRY;
4879         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4880         left = IC_LEFT(ic);
4881         right= IC_RIGHT(ic);
4882         result = IC_RESULT(ic);
4883         
4884         letype = getSpec(operandType(left));
4885         retype =getSpec(operandType(right));
4886         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4887         
4888         /* assign the amsops */
4889         aopOp (left,ic,FALSE);
4890         aopOp (right,ic,FALSE);
4891         aopOp (result,ic,TRUE);
4892         
4893         genCmp(left, right, result, ifx, sign);
4894         
4895         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4896         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4897         freeAsmop(result,NULL,ic,TRUE); 
4898 }
4899
4900 #if 0
4901 /*-----------------------------------------------------------------*/
4902 /* genc16bit2lit - compare a 16 bit value to a literal             */
4903 /*-----------------------------------------------------------------*/
4904 static void genc16bit2lit(operand *op, int lit, int offset)
4905 {
4906         int i;
4907         
4908         FENTRY;
4909         DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4910         if( (lit&0xff) == 0) 
4911                 i=1;
4912         else
4913                 i=0;
4914         
4915         switch( BYTEofLONG(lit,i)) { 
4916         case 0:
4917                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4918                 break;
4919         case 1:
4920                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4921                 break;
4922         case 0xff:
4923                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4924                 break;
4925         default:
4926                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4927                 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4928         }
4929         
4930         i ^= 1;
4931         
4932         switch( BYTEofLONG(lit,i)) { 
4933         case 0:
4934                 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4935                 break;
4936         case 1:
4937                 emitSKPNZ;
4938                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4939                 break;
4940         case 0xff:
4941                 emitSKPNZ;
4942                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4943                 break;
4944         default:
4945                 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4946                 emitSKPNZ;
4947                 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4948                 
4949         }
4950         
4951 }
4952 #endif
4953
4954 #if 0
4955 /*-----------------------------------------------------------------*/
4956 /* gencjneshort - compare and jump if not equal                    */
4957 /*-----------------------------------------------------------------*/
4958 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4959 {
4960         int size = min(AOP_SIZE(left),AOP_SIZE(right));
4961         int offset = 0;
4962         //resolvedIfx rIfx;
4963         symbol *lbl;
4964         
4965         //unsigned long lit = 0L;
4966         FENTRY;
4967         if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4968           emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4969           return;
4970         }
4971         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4972         DEBUGpic14_AopType(__LINE__,left,right,result);
4973         
4974         assert (!pic14_sameRegs (AOP(left), AOP(result)));
4975         assert (!pic14_sameRegs (AOP(right), AOP(result)));
4976         if (AOP_SIZE(result)) {
4977           for (offset = 0; offset < AOP_SIZE(result); offset++)
4978             emitpcode (POC_CLRF, popGet (AOP(result), offset));
4979         }
4980         
4981         assert (AOP_SIZE(left) == AOP_SIZE(right));
4982         //resolveIfx(&rIfx,ifx);
4983         lbl = newiTempLabel (NULL);
4984         while (size--)
4985         {
4986           mov2w (AOP(right),size);
4987           emitpcode (POC_XORFW, popGet (AOP(left), size));
4988           if (size)
4989           {
4990             emitSKPZ;
4991             emitpcode (POC_GOTO, popGetLabel (lbl->key));
4992           }
4993         } // while
4994         emitpLabel (lbl->key);
4995         if (AOP_SIZE(result)) {
4996           emitSKPNZ;
4997           emitpcode (POC_INCF, popGet (AOP(result), 0));
4998         } else {
4999           assert (ifx);
5000           genSkipz (ifx, NULL != IC_TRUE(ifx));
5001           ifx->generated = 1;
5002         }
5003         return;
5004 #if 0   
5005         if(result)
5006         {
5007                 DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
5008                 assert (!pic14_sameRegs (AOP(result), AOP(left)));
5009                 assert (!pic14_sameRegs (AOP(result), AOP(right)));
5010                 for (offset=0; offset < AOP_SIZE(result); offset++)
5011                 {
5012                         emitpcode (POC_CLRF, popGet (AOP(result), offset));
5013                 } // for offset
5014         }
5015         
5016         
5017         /* if the left side is a literal or 
5018         if the right is in a pointer register and left 
5019         is not */
5020         if ((AOP_TYPE(left) == AOP_LIT) || 
5021                 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5022                 operand *t = right;
5023                 right = left;
5024                 left = t;
5025         }
5026         if(AOP_TYPE(right) == AOP_LIT)
5027                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5028         
5029         /* if the right side is a literal then anything goes */
5030         if (AOP_TYPE(right) == AOP_LIT &&
5031                 AOP_TYPE(left) != AOP_DIR ) {
5032                 switch(size) {
5033                 case 2:
5034                         genc16bit2lit(left, lit, 0);
5035                         emitSKPNZ;
5036                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
5037                         break;
5038                 default:
5039                         offset = 0;
5040                         while (size--) {
5041                                 if(lit & 0xff) {
5042                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5043                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5044                                 } else {
5045                                         emitpcode(POC_MOVF,popGet(AOP(left),offset));
5046                                 }
5047                                 
5048                                 emitSKPNZ;
5049                                 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5050                                 offset++;
5051                                 lit >>= 8;
5052                         }
5053                         break;
5054                 }
5055         }
5056         
5057         /* if the right side is in a register or in direct space or
5058         if the left is a pointer register & right is not */    
5059         else if (AOP_TYPE(right) == AOP_REG ||
5060                 AOP_TYPE(right) == AOP_DIR || 
5061                 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5062                 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5063                 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5064                 int lbl_key = lbl->key;
5065                 
5066                 if(!result) {
5067                         DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5068                         fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5069                                 __FUNCTION__,__LINE__);
5070                         return;
5071                 }
5072                 
5073                 /*     switch(size) { */
5074                 /*     case 2: */
5075                 /*       genc16bit2lit(left, lit, 0); */
5076                 /*       emitSKPNZ; */
5077                 /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
5078                 /*       break; */
5079                 /*     default: */
5080                 offset = 0;
5081                 while (size--) {
5082                         int emit_skip=1;
5083                         if((AOP_TYPE(left) == AOP_DIR) && 
5084                                 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5085                                 
5086                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5087                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5088                                 
5089                         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5090                                 
5091                                 switch (lit & 0xff) {
5092                                 case 0:
5093                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5094                                         break;
5095                                 case 1:
5096                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5097                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5098                                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
5099                                         emit_skip=0;
5100                                         break;
5101                                 case 0xff:
5102                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5103                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5104                                         //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5105                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5106                                         emit_skip=0;
5107                                         break;
5108                                 default:
5109                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5110                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5111                                 }
5112                                 lit >>= 8;
5113                                 
5114                         } else {
5115                                 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5116                         }
5117                         if(emit_skip) {
5118                                 if(AOP_TYPE(result) == AOP_CRY) {
5119                                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5120                                         if(rIfx.condition)
5121                                                 emitSKPNZ;
5122                                         else
5123                                                 emitSKPZ;
5124                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5125                                 } else {
5126                                         /* fix me. probably need to check result size too */
5127                                         //emitpcode(POC_CLRF,popGet(AOP(result),0));
5128                                         if(rIfx.condition)
5129                                                 emitSKPZ;
5130                                         else
5131                                                 emitSKPNZ;
5132                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5133                                 }
5134                                 if(ifx)
5135                                         ifx->generated=1;
5136                         }
5137                         emit_skip++;
5138                         offset++;
5139                 }
5140                 /*       break; */
5141                 /*     } */
5142         } else if(AOP_TYPE(right) == AOP_REG &&
5143                 AOP_TYPE(left) != AOP_DIR){
5144
5145                 offset = 0;
5146                 while(size--) {
5147                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5148                         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5149                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5150                         if(rIfx.condition)
5151                                 emitSKPNZ;
5152                         else
5153                                 emitSKPZ;
5154                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5155                         offset++;
5156                 }
5157                 
5158         }else{
5159                 /* right is a pointer reg need both a & b */
5160                 offset = 0;
5161                 while(size--) {
5162                         char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5163                         if(strcmp(l,"b"))
5164                                 pic14_emitcode("mov","b,%s",l);
5165                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5166                         pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5167                         offset++;
5168                 }
5169         }
5170         
5171         emitpcode(POC_INCF,popGet(AOP(result),0));
5172         if(!rIfx.condition)
5173                 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5174         
5175         emitpLabel(lbl->key);
5176         
5177         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5178         
5179         if(ifx)
5180                 ifx->generated = 1;
5181 #endif
5182 }
5183 #endif
5184
5185 #if 0
5186 /*-----------------------------------------------------------------*/
5187 /* gencjne - compare and jump if not equal                         */
5188 /*-----------------------------------------------------------------*/
5189 static void gencjne(operand *left, operand *right, iCode *ifx)
5190 {
5191         symbol *tlbl  = newiTempLabel(NULL);
5192         
5193         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5194         gencjneshort(left, right, lbl);
5195         
5196         pic14_emitcode("mov","a,%s",one);
5197         pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5198         pic14_emitcode("","%05d_DS_:",lbl->key+100);
5199         pic14_emitcode("clr","a");
5200         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5201         
5202         emitpLabel(lbl->key);
5203         emitpLabel(tlbl->key);
5204         
5205 }
5206 #endif
5207
5208 /*-----------------------------------------------------------------*/
5209 /* genCmpEq - generates code for equal to                          */
5210 /*-----------------------------------------------------------------*/
5211 static void genCmpEq (iCode *ic, iCode *ifx)
5212 {
5213   operand *left, *right, *result;
5214   int size;
5215   symbol *false_label;
5216
5217   FENTRY;
5218   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5219
5220   if(ifx)
5221     DEBUGpic14_emitcode ("; ifx is non-null","");
5222   else
5223     DEBUGpic14_emitcode ("; ifx is null","");
5224
5225   aopOp((left=IC_LEFT(ic)),ic,FALSE);
5226   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5227   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5228
5229   DEBUGpic14_AopType(__LINE__,left,right,result);
5230
5231   /* if literal, move literal to right */ 
5232   if (op_isLitLike (IC_LEFT(ic))) {
5233     operand *tmp = right ;
5234     right = left;
5235     left = tmp;
5236   }
5237
5238   false_label = NULL;
5239   if (ifx && !IC_TRUE(ifx))
5240   {
5241     assert (IC_FALSE(ifx));
5242     false_label = IC_FALSE(ifx);
5243   }
5244
5245   size = min(AOP_SIZE(left),AOP_SIZE(right));
5246   assert(!pic14_sameRegs(AOP(result),AOP(left)));
5247   assert(!pic14_sameRegs(AOP(result),AOP(right)));
5248
5249   /* assume left != right */
5250   {
5251     int i;
5252     for (i=0; i < AOP_SIZE(result); i++)
5253     {
5254       emitpcode(POC_CLRF, popGet(AOP(result),i));
5255     }
5256   }
5257
5258   if (AOP_TYPE(right) == AOP_LIT)
5259   {
5260     unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5261     int i;
5262     size = AOP_SIZE(left);
5263     assert(!op_isLitLike(left));
5264
5265     switch (lit)
5266     {
5267       case 0:
5268         mov2w(AOP(left), 0);
5269         for (i=1; i < size; i++)
5270           emitpcode(POC_IORFW,popGet(AOP(left),i));
5271         /* now Z is set iff `left == right' */
5272         emitSKPZ;
5273         if (!false_label) false_label = newiTempLabel(NULL);
5274         emitpcode(POC_GOTO, popGetLabel(false_label->key));
5275         break;
5276
5277       default:
5278         for (i=0; i < size; i++)
5279         {
5280           mov2w(AOP(left),i);
5281           emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5282           /* now Z is cleared if `left != right' */
5283           emitSKPZ;
5284           if (!false_label) false_label = newiTempLabel(NULL);
5285           emitpcode(POC_GOTO, popGetLabel(false_label->key));
5286         } // for i
5287         break;
5288     } // switch (lit)
5289   }
5290   else
5291   {
5292     /* right is no literal */
5293     int i;
5294
5295     for (i=0; i < size; i++)
5296     {
5297       mov2w(AOP(right),i);
5298       emitpcode(POC_XORFW,popGet(AOP(left),i));
5299       /* now Z is cleared if `left != right' */
5300       emitSKPZ;
5301       if (!false_label) false_label = newiTempLabel(NULL);
5302       emitpcode(POC_GOTO, popGetLabel(false_label->key));
5303     } // for i
5304   }
5305
5306   /* if we reach here, left == right */
5307
5308   if (AOP_SIZE(result) > 0)
5309   {
5310     emitpcode(POC_INCF, popGet(AOP(result),0));
5311   }
5312
5313   if (ifx && IC_TRUE(ifx))
5314   {
5315     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5316   }
5317
5318   if (false_label && (!ifx || IC_TRUE(ifx)))
5319     emitpLabel(false_label->key);
5320
5321   if (ifx) ifx->generated = 1;
5322
5323   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5324   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5325   freeAsmop(result,NULL,ic,TRUE);
5326 }
5327
5328 /*-----------------------------------------------------------------*/
5329 /* ifxForOp - returns the icode containing the ifx for operand     */
5330 /*-----------------------------------------------------------------*/
5331 static iCode *ifxForOp ( operand *op, iCode *ic )
5332 {
5333         FENTRY;
5334         /* if true symbol then needs to be assigned */
5335         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5336         if (IS_TRUE_SYMOP(op))
5337                 return NULL ;
5338         
5339         /* if this has register type condition and
5340         the next instruction is ifx with the same operand
5341         and live to of the operand is upto the ifx only then */
5342         if (ic->next &&
5343                 ic->next->op == IFX &&
5344                 IC_COND(ic->next)->key == op->key &&
5345                 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5346                 return ic->next;
5347         
5348         if (ic->next &&
5349                 ic->next->op == IFX &&
5350                 IC_COND(ic->next)->key == op->key) {
5351                 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5352                 return ic->next;
5353         }
5354         
5355         DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5356         if (ic->next &&
5357                 ic->next->op == IFX)
5358                 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5359         
5360         if (ic->next &&
5361                 ic->next->op == IFX &&
5362                 IC_COND(ic->next)->key == op->key) {
5363                 DEBUGpic14_emitcode ("; "," key is okay");
5364                 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5365                         OP_SYMBOL(op)->liveTo,
5366                         ic->next->seq);
5367         }
5368         
5369         
5370         return NULL;
5371 }
5372 /*-----------------------------------------------------------------*/
5373 /* genAndOp - for && operation                                     */
5374 /*-----------------------------------------------------------------*/
5375 static void genAndOp (iCode *ic)
5376 {
5377         operand *left,*right, *result;
5378         /*     symbol *tlbl; */
5379         
5380         FENTRY;
5381         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5382         /* note here that && operations that are in an
5383         if statement are taken away by backPatchLabels
5384         only those used in arthmetic operations remain */
5385         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5386         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5387         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5388         
5389         DEBUGpic14_AopType(__LINE__,left,right,result);
5390         
5391         emitpcode(POC_MOVFW,popGet(AOP(left),0));
5392         emitpcode(POC_ANDFW,popGet(AOP(right),0));
5393         emitpcode(POC_MOVWF,popGet(AOP(result),0));
5394         
5395         /* if both are bit variables */
5396         /*     if (AOP_TYPE(left) == AOP_CRY && */
5397         /*         AOP_TYPE(right) == AOP_CRY ) { */
5398         /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5399         /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5400         /*         pic14_outBitC(result); */
5401         /*     } else { */
5402         /*         tlbl = newiTempLabel(NULL); */
5403         /*         pic14_toBoolean(left);     */
5404         /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5405         /*         pic14_toBoolean(right); */
5406         /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5407         /*         pic14_outBitAcc(result); */
5408         /*     } */
5409         
5410         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5411         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5412         freeAsmop(result,NULL,ic,TRUE);
5413 }
5414
5415
5416 /*-----------------------------------------------------------------*/
5417 /* genOrOp - for || operation                                      */
5418 /*-----------------------------------------------------------------*/
5419 /*
5420 tsd pic port -
5421 modified this code, but it doesn't appear to ever get called
5422 */
5423
5424 static void genOrOp (iCode *ic)
5425 {
5426         operand *left,*right, *result;
5427         symbol *tlbl;
5428         int i;
5429         
5430         /* note here that || operations that are in an
5431         if statement are taken away by backPatchLabels
5432         only those used in arthmetic operations remain */
5433         FENTRY;
5434         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5435         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5436         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5437         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5438         
5439         DEBUGpic14_AopType(__LINE__,left,right,result);
5440
5441         for (i=0; i < AOP_SIZE(result); i++)
5442         {
5443                 emitpcode(POC_CLRF, popGet(AOP(result), i));
5444         } // for i
5445
5446         tlbl = newiTempLabel(NULL);
5447         pic14_toBoolean(left);
5448         emitSKPZ;
5449         emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5450         pic14_toBoolean(right);
5451         emitpLabel(tlbl->key);
5452         /* here Z is clear IFF `left || right' */
5453         emitSKPZ;
5454         emitpcode(POC_INCF, popGet(AOP(result), 0));
5455         
5456         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5457         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5458         freeAsmop(result,NULL,ic,TRUE);            
5459 }
5460
5461 /*-----------------------------------------------------------------*/
5462 /* isLiteralBit - test if lit == 2^n                               */
5463 /*-----------------------------------------------------------------*/
5464 static int isLiteralBit(unsigned long lit)
5465 {
5466         unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5467                 0x100L,0x200L,0x400L,0x800L,
5468                 0x1000L,0x2000L,0x4000L,0x8000L,
5469                 0x10000L,0x20000L,0x40000L,0x80000L,
5470                 0x100000L,0x200000L,0x400000L,0x800000L,
5471                 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5472                 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5473         int idx;
5474         
5475         FENTRY;
5476         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5477         for(idx = 0; idx < 32; idx++)
5478                 if(lit == pw[idx])
5479                         return idx+1;
5480                 return 0;
5481 }
5482
5483 /*-----------------------------------------------------------------*/
5484 /* continueIfTrue -                                                */
5485 /*-----------------------------------------------------------------*/
5486 static void continueIfTrue (iCode *ic)
5487 {
5488         FENTRY;
5489         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5490         if(IC_TRUE(ic))
5491         {
5492                 // Why +100?!?
5493                 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5494                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5495         }
5496         ic->generated = 1;
5497 }
5498
5499 /*-----------------------------------------------------------------*/
5500 /* jmpIfTrue -                                                     */
5501 /*-----------------------------------------------------------------*/
5502 static void jumpIfTrue (iCode *ic)
5503 {
5504         FENTRY;
5505         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5506         if(!IC_TRUE(ic))
5507         {
5508                 // Why +100?!?
5509                 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5510                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5511         }
5512         ic->generated = 1;
5513 }
5514
5515 /*-----------------------------------------------------------------*/
5516 /* jmpTrueOrFalse -                                                */
5517 /*-----------------------------------------------------------------*/
5518 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5519 {
5520         FENTRY;
5521         // ugly but optimized by peephole
5522         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5523         if(IC_TRUE(ic)){
5524                 symbol *nlbl = newiTempLabel(NULL);
5525                 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5526                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5527                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5528                 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5529         }
5530         else{
5531                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5532                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5533         }
5534         ic->generated = 1;
5535 }
5536
5537 /*-----------------------------------------------------------------*/
5538 /* genAnd  - code for and                                          */
5539 /*-----------------------------------------------------------------*/
5540 static void genAnd (iCode *ic, iCode *ifx)
5541 {
5542         operand *left, *right, *result;
5543         int size, offset=0;  
5544         unsigned long lit = 0L;
5545         int bytelit = 0;
5546         resolvedIfx rIfx;
5547         
5548         FENTRY;
5549         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5550         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5551         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5552         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5553         
5554         resolveIfx(&rIfx,ifx);
5555         
5556         /* if left is a literal & right is not then exchange them */
5557         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5558                 AOP_NEEDSACC(left)) {
5559                 operand *tmp = right ;
5560                 right = left;
5561                 left = tmp;
5562         }
5563         
5564         /* if result = right then exchange them */
5565         if(pic14_sameRegs(AOP(result),AOP(right))){
5566                 operand *tmp = right ;
5567                 right = left;
5568                 left = tmp;
5569         }
5570         
5571         /* if right is bit then exchange them */
5572         if (AOP_TYPE(right) == AOP_CRY &&
5573                 AOP_TYPE(left) != AOP_CRY){
5574                 operand *tmp = right ;
5575                 right = left;
5576                 left = tmp;
5577         }
5578         if(AOP_TYPE(right) == AOP_LIT)
5579                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5580         
5581         size = AOP_SIZE(result);
5582         
5583         DEBUGpic14_AopType(__LINE__,left,right,result);
5584         
5585         // if(bit & yy)
5586         // result = bit & yy;
5587         if (AOP_TYPE(left) == AOP_CRY){
5588                 // c = bit & literal;
5589                 if(AOP_TYPE(right) == AOP_LIT){
5590                         if(lit & 1) {
5591                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5592                                         // no change
5593                                         goto release;
5594                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5595                         } else {
5596                                 // bit(result) = 0;
5597                                 if(size && (AOP_TYPE(result) == AOP_CRY)){
5598                                         pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5599                                         goto release;
5600                                 }
5601                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5602                                         jumpIfTrue(ifx);
5603                                         goto release;
5604                                 }
5605                                 pic14_emitcode("clr","c");
5606                         }
5607                 } else {
5608                         if (AOP_TYPE(right) == AOP_CRY){
5609                                 // c = bit & bit;
5610                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5611                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5612                         } else {
5613                                 // c = bit & val;
5614                                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5615                                 // c = lsb
5616                                 pic14_emitcode("rrc","a");
5617                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5618                         }
5619                 }
5620                 // bit = c
5621                 // val = c
5622                 if(size)
5623                         pic14_outBitC(result);
5624                 // if(bit & ...)
5625                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5626                         genIfxJump(ifx, "c");           
5627                 goto release ;
5628         }
5629         
5630         // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5631         // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5632         if((AOP_TYPE(right) == AOP_LIT) &&
5633                 (AOP_TYPE(result) == AOP_CRY) &&
5634                 (AOP_TYPE(left) != AOP_CRY)){
5635                 int posbit = isLiteralBit(lit);
5636                 /* left &  2^n */
5637                 if(posbit){
5638                         posbit--;
5639                         //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5640                         // bit = left & 2^n
5641                         if(size)
5642                                 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5643                         // if(left &  2^n)
5644                         else{
5645                                 if(ifx){
5646                                         int offset = 0;
5647                                         while (posbit > 7) {
5648                                                 posbit -= 8;
5649                                                 offset++;
5650                                         }
5651                                         emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5652                                                 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5653                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5654                                         
5655                                         ifx->generated = 1;
5656                                 }
5657                                 goto release;
5658                         }
5659                 } else {
5660                         symbol *tlbl = newiTempLabel(NULL);
5661                         int sizel = AOP_SIZE(left);
5662                         if(size)
5663                                 pic14_emitcode("setb","c");
5664                         while(sizel--){
5665                                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5666                                         mov2w( AOP(left), offset);
5667                                         // byte ==  2^n ?
5668                                         if((posbit = isLiteralBit(bytelit)) != 0) {
5669                                                 emitpcode(rIfx.condition ? POC_BTFSC : POC_BTFSS, // XXX: or the other way round?
5670                                                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit - 1, 0));
5671                                                 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5672                                         }
5673                                         else{
5674                                                 emitpcode(POC_ANDLW, newpCodeOpLit(bytelit & 0x0ff));
5675                                                 if (rIfx.condition) emitSKPZ;
5676                                                 else emitSKPNZ;
5677                                                 
5678                                                 if(bytelit != 0x0FFL)
5679                                                 {
5680                                                         pic14_emitcode("anl","a,%s",
5681                                                         aopGet(AOP(right),offset,FALSE,TRUE));
5682                                                 }
5683                                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5684                                         }
5685
5686                                         emitpcode(POC_GOTO, popGetLabel(rIfx.lbl->key));
5687                                         ifx->generated = 1;
5688                                                 
5689                                 }
5690                                 offset++;
5691                         }
5692                         // bit = left & literal
5693                         if(size){
5694                                 pic14_emitcode("clr","c");
5695                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5696                         }
5697                         // if(left & literal)
5698                         else{
5699                                 if(ifx)
5700                                         jmpTrueOrFalse(ifx, tlbl);
5701                                 goto release ;
5702                         }
5703                 }
5704                 pic14_outBitC(result);
5705                 goto release ;
5706         }
5707         
5708         /* if left is same as result */
5709         if(pic14_sameRegs(AOP(result),AOP(left))){
5710                 int know_W = -1;
5711                 for(;size--; offset++,lit>>=8) {
5712                         if(AOP_TYPE(right) == AOP_LIT){
5713                                 switch(lit & 0xff) {
5714                                 case 0x00:
5715                                         /*  and'ing with 0 has clears the result */
5716                                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
5717                                         break;
5718                                 case 0xff:
5719                                         /* and'ing with 0xff is a nop when the result and left are the same */
5720                                         break;
5721                                         
5722                                 default:
5723                                         {
5724                                                 int p = my_powof2( (~lit) & 0xff );
5725                                                 if(p>=0) {
5726                                                         /* only one bit is set in the literal, so use a bcf instruction */
5727                                                         emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5728                                                         
5729                                                 } else {
5730                                                         if(know_W != (int)(lit&0xff))
5731                                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5732                                                         know_W = lit &0xff;
5733                                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5734                                                 }
5735                                         }    
5736                                 }
5737                         } else {
5738                                 if (AOP_TYPE(left) == AOP_ACC) {
5739                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5740                                 } else {        
5741                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5742                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5743                                         
5744                                 }
5745                         }
5746                 }
5747                 
5748         } else {
5749                 // left & result in different registers
5750                 if(AOP_TYPE(result) == AOP_CRY){
5751                         // result = bit
5752                         // if(size), result in bit
5753                         // if(!size && ifx), conditional oper: if(left & right)
5754                         symbol *tlbl = newiTempLabel(NULL);
5755                         int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5756                         if(size)
5757                                 pic14_emitcode("setb","c");
5758                         while(sizer--){
5759                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5760                                 pic14_emitcode("anl","a,%s",
5761                                         aopGet(AOP(left),offset,FALSE,FALSE));
5762                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5763                                 offset++;
5764                         }
5765                         if(size){
5766                                 CLRC;
5767                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5768                                 pic14_outBitC(result);
5769                         } else if(ifx)
5770                                 jmpTrueOrFalse(ifx, tlbl);
5771                 } else {
5772                         for(;(size--);offset++) {
5773                                 // normal case
5774                                 // result = left & right
5775                                 if(AOP_TYPE(right) == AOP_LIT){
5776                                         int t = (lit >> (offset*8)) & 0x0FFL;
5777                                         switch(t) { 
5778                                         case 0x00:
5779                                                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5780                                                 break;
5781                                         case 0xff:
5782                                                 if(AOP_TYPE(left) != AOP_ACC) {
5783                                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5784                                                 }
5785                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5786                                                 break;
5787                                         default:
5788                                                 if(AOP_TYPE(left) == AOP_ACC) {
5789                                                         emitpcode(POC_ANDLW, popGetLit(t));
5790                                                 } else {
5791                                                         emitpcode(POC_MOVLW, popGetLit(t));
5792                                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5793                                                 }
5794                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5795                                         }
5796                                         continue;
5797                                 }
5798                                 
5799                                 if (AOP_TYPE(left) == AOP_ACC) {
5800                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5801                                 } else {
5802                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5803                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5804                                 }
5805                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5806                         }
5807                 }
5808         }
5809         
5810 release :
5811         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5812         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5813         freeAsmop(result,NULL,ic,TRUE);     
5814 }
5815
5816 /*-----------------------------------------------------------------*/
5817 /* genOr  - code for or                                            */
5818 /*-----------------------------------------------------------------*/
5819 static void genOr (iCode *ic, iCode *ifx)
5820 {
5821         operand *left, *right, *result;
5822         int size, offset=0;
5823         unsigned long lit = 0L;
5824         
5825         FENTRY;
5826         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5827         
5828         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5829         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5830         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5831         
5832         DEBUGpic14_AopType(__LINE__,left,right,result);
5833         
5834         /* if left is a literal & right is not then exchange them */
5835         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5836                 AOP_NEEDSACC(left)) {
5837                 operand *tmp = right ;
5838                 right = left;
5839                 left = tmp;
5840         }
5841         
5842         /* if result = right then exchange them */
5843         if(pic14_sameRegs(AOP(result),AOP(right))){
5844                 operand *tmp = right ;
5845                 right = left;
5846                 left = tmp;
5847         }
5848         
5849         /* if right is bit then exchange them */
5850         if (AOP_TYPE(right) == AOP_CRY &&
5851                 AOP_TYPE(left) != AOP_CRY){
5852                 operand *tmp = right ;
5853                 right = left;
5854                 left = tmp;
5855         }
5856         
5857         DEBUGpic14_AopType(__LINE__,left,right,result);
5858         
5859         if(AOP_TYPE(right) == AOP_LIT)
5860                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5861         
5862         size = AOP_SIZE(result);
5863         
5864         // if(bit | yy)
5865         // xx = bit | yy;
5866         if (AOP_TYPE(left) == AOP_CRY){
5867                 if(AOP_TYPE(right) == AOP_LIT){
5868                         // c = bit & literal;
5869                         if(lit){
5870                                 // lit != 0 => result = 1
5871                                 if(AOP_TYPE(result) == AOP_CRY){
5872                                         if(size)
5873                                                 emitpcode(POC_BSF, popGet(AOP(result),0));
5874                                         //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5875                                         //   AOP(result)->aopu.aop_dir,
5876                                         //   AOP(result)->aopu.aop_dir);
5877                                         else if(ifx)
5878                                                 continueIfTrue(ifx);
5879                                         goto release;
5880                                 }
5881                         } else {
5882                                 // lit == 0 => result = left
5883                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5884                                         goto release;
5885                                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5886                         }
5887                 } else {
5888                         if (AOP_TYPE(right) == AOP_CRY){
5889                                 if(pic14_sameRegs(AOP(result),AOP(left))){
5890                                         // c = bit | bit;
5891                                         emitpcode(POC_BCF,   popGet(AOP(result),0));
5892                                         emitpcode(POC_BTFSC, popGet(AOP(right),0));
5893                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5894                                         
5895                                         pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5896                                                 AOP(result)->aopu.aop_dir,
5897                                                 AOP(result)->aopu.aop_dir);
5898                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5899                                                 AOP(right)->aopu.aop_dir,
5900                                                 AOP(right)->aopu.aop_dir);
5901                                         pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5902                                                 AOP(result)->aopu.aop_dir,
5903                                                 AOP(result)->aopu.aop_dir);
5904                                 } else {
5905                                         if( AOP_TYPE(result) == AOP_ACC) {
5906                                                 emitpcode(POC_MOVLW, popGetLit(0));
5907                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5908                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5909                                                 emitpcode(POC_MOVLW, popGetLit(1));
5910                                                 
5911                                         } else {
5912                                                 
5913                                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5914                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5915                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5916                                                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5917                                                 
5918                                                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5919                                                         AOP(result)->aopu.aop_dir,
5920                                                         AOP(result)->aopu.aop_dir);
5921                                                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5922                                                         AOP(right)->aopu.aop_dir,
5923                                                         AOP(right)->aopu.aop_dir);
5924                                                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5925                                                         AOP(left)->aopu.aop_dir,
5926                                                         AOP(left)->aopu.aop_dir);
5927                                                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5928                                                         AOP(result)->aopu.aop_dir,
5929                                                         AOP(result)->aopu.aop_dir);
5930                                         }
5931                                 }
5932                         } else {
5933                                 // c = bit | val;
5934                                 symbol *tlbl = newiTempLabel(NULL);
5935                                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5936                                 
5937                                 
5938                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5939                                 if( AOP_TYPE(right) == AOP_ACC) {
5940                                         emitpcode(POC_IORLW, popGetLit(0));
5941                                         emitSKPNZ;
5942                                         emitpcode(POC_BTFSC, popGet(AOP(left),0));
5943                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5944                                 }
5945                                 
5946                                 
5947                                 
5948                                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5949                                         pic14_emitcode(";XXX setb","c");
5950                                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5951                                         AOP(left)->aopu.aop_dir,tlbl->key+100);
5952                                 pic14_toBoolean(right);
5953                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5954                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5955                                         jmpTrueOrFalse(ifx, tlbl);
5956                                         goto release;
5957                                 } else {
5958                                         CLRC;
5959                                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5960                                 }
5961                         }
5962                 }
5963                 // bit = c
5964                 // val = c
5965                 if(size)
5966                         pic14_outBitC(result);
5967                 // if(bit | ...)
5968                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5969                         genIfxJump(ifx, "c");           
5970                 goto release ;
5971         }
5972
5973         // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5974         // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5975         if((AOP_TYPE(right) == AOP_LIT) &&
5976           (AOP_TYPE(result) == AOP_CRY) &&
5977           (AOP_TYPE(left) != AOP_CRY)){
5978                 if(lit){
5979                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5980                         // result = 1
5981                         if(size)
5982                                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5983                         else 
5984                                 continueIfTrue(ifx);
5985                         goto release;
5986                 } else {
5987                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5988                         // lit = 0, result = boolean(left)
5989                         if(size)
5990                                 pic14_emitcode(";XXX setb","c");
5991                         pic14_toBoolean(right);
5992                         if(size){
5993                                 symbol *tlbl = newiTempLabel(NULL);
5994                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5995                                 CLRC;
5996                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5997                         } else {
5998                                 genIfxJump (ifx,"a");
5999                                 goto release;
6000                         }
6001                 }
6002                 pic14_outBitC(result);
6003                 goto release ;
6004         }
6005
6006         /* if left is same as result */
6007         if(pic14_sameRegs(AOP(result),AOP(left))){
6008                 int know_W = -1;
6009                 for(;size--; offset++,lit>>=8) {
6010                         if(AOP_TYPE(right) == AOP_LIT){
6011                                 if((lit & 0xff) == 0)
6012                                         /*  or'ing with 0 has no effect */
6013                                         continue;
6014                                 else {
6015                                         int p = my_powof2(lit & 0xff);
6016                                         if(p>=0) {
6017                                                 /* only one bit is set in the literal, so use a bsf instruction */
6018                                                 emitpcode(POC_BSF,
6019                                                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6020                                         } else {
6021                                                 if(know_W != (int)(lit & 0xff))
6022                                                         emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
6023                                                 know_W = lit & 0xff;
6024                                                 emitpcode(POC_IORWF, popGet(AOP(left),offset));
6025                                         }
6026                                         
6027                                 }
6028                         } else {
6029                                 if (AOP_TYPE(left) == AOP_ACC) {
6030                                         emitpcode(POC_IORFW,  popGet(AOP(right),offset));
6031                                         pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6032                                 } else {        
6033                                         emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
6034                                         emitpcode(POC_IORWF,  popGet(AOP(left),offset));
6035                                         
6036                                         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6037                                         pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
6038                                         
6039                                 }
6040                         }
6041                 }
6042         } else {
6043                 // left & result in different registers
6044                 if(AOP_TYPE(result) == AOP_CRY){
6045                         // result = bit
6046                         // if(size), result in bit
6047                         // if(!size && ifx), conditional oper: if(left | right)
6048                         symbol *tlbl = newiTempLabel(NULL);
6049                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6050                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6051                         
6052                         
6053                         if(size)
6054                                 pic14_emitcode(";XXX setb","c");
6055                         while(sizer--){
6056                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6057                                 pic14_emitcode(";XXX orl","a,%s",
6058                                         aopGet(AOP(left),offset,FALSE,FALSE));
6059                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6060                                 offset++;
6061                         }
6062                         if(size){
6063                                 CLRC;
6064                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6065                                 pic14_outBitC(result);
6066                         } else if(ifx)
6067                                 jmpTrueOrFalse(ifx, tlbl);
6068                 } else for(;(size--);offset++){
6069                         // normal case
6070                         // result = left | right
6071                         if(AOP_TYPE(right) == AOP_LIT){
6072                                 int t = (lit >> (offset*8)) & 0x0FFL;
6073                                 switch(t) { 
6074                                 case 0x00:
6075                                         if (AOP_TYPE(left) != AOP_ACC) {
6076                                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
6077                                         }
6078                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6079                                         
6080                                         break;
6081                                 default:
6082                                         if (AOP_TYPE(left) == AOP_ACC) {
6083                                                 emitpcode(POC_IORLW,  popGetLit(t));
6084                                         } else {
6085                                                 emitpcode(POC_MOVLW,  popGetLit(t));
6086                                                 emitpcode(POC_IORFW,  popGet(AOP(left),offset));
6087                                         }
6088                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));        
6089                                 }
6090                                 continue;
6091                         }
6092                         
6093                         // faster than result <- left, anl result,right
6094                         // and better if result is SFR
6095                         if (AOP_TYPE(left) == AOP_ACC) {
6096                                 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6097                         } else {
6098                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6099                                 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6100                         }
6101                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6102                 }
6103         }
6104
6105 release :
6106         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6107         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6108         freeAsmop(result,NULL,ic,TRUE);     
6109 }
6110
6111 /*-----------------------------------------------------------------*/
6112 /* genXor - code for xclusive or                                   */
6113 /*-----------------------------------------------------------------*/
6114 static void genXor (iCode *ic, iCode *ifx)
6115 {
6116         operand *left, *right, *result;
6117         int size, offset=0;
6118         unsigned long lit = 0L;
6119         
6120         FENTRY;
6121         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6122         
6123         aopOp((left = IC_LEFT(ic)),ic,FALSE);
6124         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6125         aopOp((result=IC_RESULT(ic)),ic,TRUE);
6126         
6127         /* if left is a literal & right is not ||
6128         if left needs acc & right does not */
6129         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6130                 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6131                 operand *tmp = right ;
6132                 right = left;
6133                 left = tmp;
6134         }
6135         
6136         /* if result = right then exchange them */
6137         if(pic14_sameRegs(AOP(result),AOP(right))){
6138                 operand *tmp = right ;
6139                 right = left;
6140                 left = tmp;
6141         }
6142         
6143         /* if right is bit then exchange them */
6144         if (AOP_TYPE(right) == AOP_CRY &&
6145                 AOP_TYPE(left) != AOP_CRY){
6146                 operand *tmp = right ;
6147                 right = left;
6148                 left = tmp;
6149         }
6150         if(AOP_TYPE(right) == AOP_LIT)
6151                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6152         
6153         size = AOP_SIZE(result);
6154         
6155         // if(bit ^ yy)
6156         // xx = bit ^ yy;
6157         if (AOP_TYPE(left) == AOP_CRY){
6158                 if(AOP_TYPE(right) == AOP_LIT){
6159                         // c = bit & literal;
6160                         if(lit>>1){
6161                                 // lit>>1  != 0 => result = 1
6162                                 if(AOP_TYPE(result) == AOP_CRY){
6163                                         if(size)
6164                                         {emitpcode(POC_BSF,  popGet(AOP(result),offset));
6165                                         pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6166                                         else if(ifx)
6167                                                 continueIfTrue(ifx);
6168                                         goto release;
6169                                 }
6170                                 pic14_emitcode("setb","c");
6171                         } else{
6172                                 // lit == (0 or 1)
6173                                 if(lit == 0){
6174                                         // lit == 0, result = left
6175                                         if(size && pic14_sameRegs(AOP(result),AOP(left)))
6176                                                 goto release;
6177                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6178                                 } else{
6179                                         // lit == 1, result = not(left)
6180                                         if(size && pic14_sameRegs(AOP(result),AOP(left))){
6181                                                 emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
6182                                                 emitpcode(POC_XORWF,  popGet(AOP(result),offset));
6183                                                 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6184                                                 goto release;
6185                                         } else {
6186                                                 assert ( !"incomplete genXor" );
6187                                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6188                                                 pic14_emitcode("cpl","c");
6189                                         }
6190                                 }
6191                         }
6192                         
6193                 } else {
6194                         // right != literal
6195                         symbol *tlbl = newiTempLabel(NULL);
6196                         if (AOP_TYPE(right) == AOP_CRY){
6197                                 // c = bit ^ bit;
6198                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6199                         }
6200                         else{
6201                                 int sizer = AOP_SIZE(right);
6202                                 // c = bit ^ val
6203                                 // if val>>1 != 0, result = 1
6204                                 pic14_emitcode("setb","c");
6205                                 while(sizer){
6206                                         MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6207                                         if(sizer == 1)
6208                                                 // test the msb of the lsb
6209                                                 pic14_emitcode("anl","a,#0xfe");
6210                                         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6211                                         sizer--;
6212                                 }
6213                                 // val = (0,1)
6214                                 pic14_emitcode("rrc","a");
6215                         }
6216                         pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6217                         pic14_emitcode("cpl","c");
6218                         pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6219                 }
6220                 // bit = c
6221                 // val = c
6222                 if(size)
6223                         pic14_outBitC(result);
6224                 // if(bit | ...)
6225                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6226                         genIfxJump(ifx, "c");           
6227                 goto release ;
6228         }
6229         
6230         if(pic14_sameRegs(AOP(result),AOP(left))){
6231                 /* if left is same as result */
6232                 for(;size--; offset++) {
6233                         if(AOP_TYPE(right) == AOP_LIT){
6234                                 int t  = (lit >> (offset*8)) & 0x0FFL;
6235                                 if(t == 0x00L)
6236                                         continue;
6237                                 else
6238                                         if (IS_AOP_PREG(left)) {
6239                                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6240                                                 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6241                                                 aopPut(AOP(result),"a",offset);
6242                                         } else {
6243                                                 emitpcode(POC_MOVLW, popGetLit(t));
6244                                                 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6245                                                 pic14_emitcode("xrl","%s,%s",
6246                                                         aopGet(AOP(left),offset,FALSE,TRUE),
6247                                                         aopGet(AOP(right),offset,FALSE,FALSE));
6248                                         }
6249                         } else {
6250                                 if (AOP_TYPE(left) == AOP_ACC)
6251                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6252                                 else {
6253                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6254                                         emitpcode(POC_XORWF,popGet(AOP(left),offset));
6255                                         /*
6256                                         if (IS_AOP_PREG(left)) {
6257                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6258                                         aopPut(AOP(result),"a",offset);
6259                                         } else
6260                                         pic14_emitcode("xrl","%s,a",
6261                                         aopGet(AOP(left),offset,FALSE,TRUE));
6262                                         */
6263                                 }
6264                         }
6265                 }
6266         } else {
6267                 // left & result in different registers
6268                 if(AOP_TYPE(result) == AOP_CRY){
6269                         // result = bit
6270                         // if(size), result in bit
6271                         // if(!size && ifx), conditional oper: if(left ^ right)
6272                         symbol *tlbl = newiTempLabel(NULL);
6273                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6274                         if(size)
6275                                 pic14_emitcode("setb","c");
6276                         while(sizer--){
6277                                 if((AOP_TYPE(right) == AOP_LIT) &&
6278                                         (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6279                                         MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6280                                 } else {
6281                                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6282                                         pic14_emitcode("xrl","a,%s",
6283                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6284                                 }
6285                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6286                                 offset++;
6287                         }
6288                         if(size){
6289                                 CLRC;
6290                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6291                                 pic14_outBitC(result);
6292                         } else if(ifx)
6293                                 jmpTrueOrFalse(ifx, tlbl);
6294                 } else for(;(size--);offset++){
6295                         // normal case
6296                         // result = left & right
6297                         if(AOP_TYPE(right) == AOP_LIT){
6298                                 int t = (lit >> (offset*8)) & 0x0FFL;
6299                                 switch(t) { 
6300                                 case 0x00:
6301                                         if (AOP_TYPE(left) != AOP_ACC) {
6302                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6303                                         }
6304                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6305                                         pic14_emitcode("movf","%s,w",
6306                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6307                                         pic14_emitcode("movwf","%s",
6308                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6309                                         break;
6310                                 case 0xff:
6311                                         if (AOP_TYPE(left) == AOP_ACC) {
6312                                                 emitpcode(POC_XORLW, popGetLit(t));
6313                                         } else {
6314                                                 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6315                                         }
6316                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6317                                         break;
6318                                 default:
6319                                         if (AOP_TYPE(left) == AOP_ACC) {
6320                                                 emitpcode(POC_XORLW, popGetLit(t));
6321                                         } else {
6322                                                 emitpcode(POC_MOVLW, popGetLit(t));
6323                                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6324                                         }
6325                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6326                                         pic14_emitcode("movlw","0x%x",t);
6327                                         pic14_emitcode("xorwf","%s,w",
6328                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6329                                         pic14_emitcode("movwf","%s",
6330                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6331                                         
6332                                 }
6333                                 continue;
6334                         }
6335                         
6336                         // faster than result <- left, anl result,right
6337                         // and better if result is SFR
6338                         if (AOP_TYPE(left) == AOP_ACC) {
6339                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6340                         } else {
6341                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6342                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6343                         }
6344                         if ( AOP_TYPE(result) != AOP_ACC){
6345                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6346                         }
6347                 }
6348         }
6349         
6350 release :
6351         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6352         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6353         freeAsmop(result,NULL,ic,TRUE);     
6354 }
6355
6356 /*-----------------------------------------------------------------*/
6357 /* genInline - write the inline code out                           */
6358 /*-----------------------------------------------------------------*/
6359 static void genInline (iCode *ic)
6360 {
6361   char *buffer, *bp, *bp1;
6362
6363   FENTRY;
6364   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6365
6366   _G.inLine += (!options.asmpeep);
6367
6368   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6369   strcpy(buffer,IC_INLINE(ic));
6370
6371   /* emit each line as a code */
6372   while (*bp) {
6373     if (*bp == '\n') {
6374       *bp++ = '\0';
6375       
6376       if(*bp1)
6377         addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6378       bp1 = bp;
6379     } else {
6380       if (*bp == ':') {
6381         bp++;
6382         *bp = '\0';
6383         bp++;
6384
6385         /* print label, use this special format with NULL directive
6386          * to denote that the argument should not be indented with tab */
6387         addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6388
6389         bp1 = bp;
6390       } else
6391         bp++;
6392     }
6393   }
6394   if ((bp1 != bp) && *bp1)
6395     addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6396
6397   Safe_free(buffer);
6398
6399   _G.inLine -= (!options.asmpeep);
6400 }
6401
6402 /*-----------------------------------------------------------------*/
6403 /* genRRC - rotate right with carry                                */
6404 /*-----------------------------------------------------------------*/
6405 static void genRRC (iCode *ic)
6406 {
6407         operand *left , *result ;
6408         int size, offset = 0, same;
6409         
6410         FENTRY;
6411         /* rotate right with carry */
6412         left = IC_LEFT(ic);
6413         result=IC_RESULT(ic);
6414         aopOp (left,ic,FALSE);
6415         aopOp (result,ic,FALSE);
6416         
6417         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6418         
6419         same = pic14_sameRegs(AOP(result),AOP(left));
6420         
6421         size = AOP_SIZE(result);    
6422         
6423         /* get the lsb and put it into the carry */
6424         emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6425         
6426         offset = 0 ;
6427         
6428         while(size--) {
6429                 
6430                 if(same) {
6431                         emitpcode(POC_RRF, popGet(AOP(left),offset));
6432                 } else {
6433                         emitpcode(POC_RRFW, popGet(AOP(left),offset));
6434                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6435                 }
6436                 
6437                 offset++;
6438         }
6439         
6440         freeAsmop(left,NULL,ic,TRUE);
6441         freeAsmop(result,NULL,ic,TRUE);
6442 }
6443
6444 /*-----------------------------------------------------------------*/
6445 /* genRLC - generate code for rotate left with carry               */
6446 /*-----------------------------------------------------------------*/
6447 static void genRLC (iCode *ic)
6448 {    
6449         operand *left , *result ;
6450         int size, offset = 0;
6451         int same;
6452         
6453         FENTRY;
6454         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6455         /* rotate right with carry */
6456         left = IC_LEFT(ic);
6457         result=IC_RESULT(ic);
6458         aopOp (left,ic,FALSE);
6459         aopOp (result,ic,FALSE);
6460         
6461         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6462         
6463         same = pic14_sameRegs(AOP(result),AOP(left));
6464         
6465         /* move it to the result */
6466         size = AOP_SIZE(result);    
6467         
6468         /* get the msb and put it into the carry */
6469         emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6470         
6471         offset = 0 ;
6472         
6473         while(size--) {
6474                 
6475                 if(same) {
6476                         emitpcode(POC_RLF, popGet(AOP(left),offset));
6477                 } else {
6478                         emitpcode(POC_RLFW, popGet(AOP(left),offset));
6479                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6480                 }
6481                 
6482                 offset++;
6483         }
6484         
6485         
6486         freeAsmop(left,NULL,ic,TRUE);
6487         freeAsmop(result,NULL,ic,TRUE);
6488 }
6489
6490 /*-----------------------------------------------------------------*/
6491 /* genGetHbit - generates code get highest order bit               */
6492 /*-----------------------------------------------------------------*/
6493 static void genGetHbit (iCode *ic)
6494 {
6495         operand *left, *result;
6496         left = IC_LEFT(ic);
6497         result=IC_RESULT(ic);
6498         aopOp (left,ic,FALSE);
6499         aopOp (result,ic,FALSE);
6500         
6501         FENTRY;
6502         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6503         /* get the highest order byte into a */
6504         MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6505         if(AOP_TYPE(result) == AOP_CRY){
6506                 pic14_emitcode("rlc","a");
6507                 pic14_outBitC(result);
6508         }
6509         else{
6510                 pic14_emitcode("rl","a");
6511                 pic14_emitcode("anl","a,#0x01");
6512                 pic14_outAcc(result);
6513         }
6514         
6515         
6516         freeAsmop(left,NULL,ic,TRUE);
6517         freeAsmop(result,NULL,ic,TRUE);
6518 }
6519
6520 /*-----------------------------------------------------------------*/
6521 /* AccLsh - shift left accumulator by known count                  */
6522 /* MARK: pic14 always rotates through CARRY!                       */
6523 /*-----------------------------------------------------------------*/
6524 static void AccLsh (pCodeOp *pcop,int shCount)
6525 {
6526         FENTRY;
6527         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6528         shCount &= 0x0007;              // shCount : 0..7
6529         switch(shCount){
6530         case 0 :
6531                 return;
6532                 break;
6533         case 1 :
6534                 emitCLRC;
6535                 emitpcode(POC_RLF,pcop);
6536                 return;
6537                 break;
6538         case 2 :
6539                 emitpcode(POC_RLF,pcop);
6540                 emitpcode(POC_RLF,pcop);
6541                 break;
6542         case 3 :
6543                 emitpcode(POC_RLF,pcop);
6544                 emitpcode(POC_RLF,pcop);
6545                 emitpcode(POC_RLF,pcop);
6546                 break;
6547         case 4 :
6548                 emitpcode(POC_SWAPF,pcop);
6549                 break;
6550         case 5 :
6551                 emitpcode(POC_SWAPF,pcop);
6552                 emitpcode(POC_RLF,pcop);
6553                 break;
6554         case 6 :
6555                 emitpcode(POC_SWAPF,pcop);
6556                 emitpcode(POC_RLF,pcop);
6557                 emitpcode(POC_RLF,pcop);
6558                 break;
6559         case 7 :
6560                 emitpcode(POC_RRFW,pcop);
6561                 emitpcode(POC_RRF,pcop);
6562                 break;
6563         }
6564         /* clear invalid bits */
6565         emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6566         emitpcode(POC_ANDWF, pcop);
6567 }
6568
6569 /*-----------------------------------------------------------------*/
6570 /* AccRsh - shift right accumulator by known count                 */
6571 /* MARK: pic14 always rotates through CARRY!                       */
6572 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6573 /*            1: mask out invalid bits (zero-extend)               */
6574 /*            2: sign-extend result (pretty slow)                  */
6575 /*-----------------------------------------------------------------*/
6576 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6577 {
6578         FENTRY;
6579         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6580         shCount &= 0x0007;              // shCount : 0..7
6581         switch(shCount){
6582         case 0 :
6583                 return;
6584                 break;
6585         case 1 :
6586                 /* load sign if needed */
6587                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6588                 else if (mask_mode == 1) emitCLRC;
6589                 emitpcode(POC_RRF,pcop);
6590                 return;
6591                 break;
6592         case 2 :
6593                 /* load sign if needed */
6594                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6595                 emitpcode(POC_RRF,pcop);
6596                 /* load sign if needed */
6597                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6598                 emitpcode(POC_RRF,pcop);
6599                 if (mask_mode == 2) return;
6600                 break;
6601         case 3 :
6602                 /* load sign if needed */
6603                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6604                 emitpcode(POC_RRF,pcop);
6605                 /* load sign if needed */
6606                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6607                 emitpcode(POC_RRF,pcop);
6608                 /* load sign if needed */
6609                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6610                 emitpcode(POC_RRF,pcop);
6611                 if (mask_mode == 2) return;
6612                 break;
6613         case 4 :
6614                 emitpcode(POC_SWAPF,pcop);
6615                 break;
6616         case 5 :
6617                 emitpcode(POC_SWAPF,pcop);
6618                 emitpcode(POC_RRF,pcop);
6619                 break;
6620         case 6 :
6621                 emitpcode(POC_SWAPF,pcop);
6622                 emitpcode(POC_RRF,pcop);
6623                 emitpcode(POC_RRF,pcop);
6624                 break;
6625         case 7 :
6626                 if (mask_mode == 2)
6627                 {
6628                         /* load sign */
6629                         emitpcode(POC_RLFW,pcop);
6630                         emitpcode(POC_CLRF,pcop);
6631                         emitSKPNC;
6632                         emitpcode(POC_COMF,pcop);
6633                         return;
6634                 } else {
6635                         emitpcode(POC_RLFW,pcop);
6636                         emitpcode(POC_RLF,pcop);
6637                 }
6638                 break;
6639         }
6640
6641         if (mask_mode == 0)
6642         {
6643                 /* leave invalid bits undefined */
6644                 return;
6645         }
6646         
6647         /* clear invalid bits -- zero-extend */
6648         emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6649         emitpcode(POC_ANDWF, pcop);
6650
6651         if (mask_mode == 2) {
6652           /* sign-extend */
6653           emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6654           emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6655           emitpcode(POC_IORWF, pcop);
6656         }
6657 }
6658
6659 #if 0
6660 /*-----------------------------------------------------------------*/
6661 /* AccSRsh - signed right shift accumulator by known count                 */
6662 /*-----------------------------------------------------------------*/
6663 static void AccSRsh (int shCount)
6664 {
6665         symbol *tlbl ;
6666         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6667         if(shCount != 0){
6668                 if(shCount == 1){
6669                         pic14_emitcode("mov","c,acc.7");
6670                         pic14_emitcode("rrc","a");
6671                 } else if(shCount == 2){
6672                         pic14_emitcode("mov","c,acc.7");
6673                         pic14_emitcode("rrc","a");
6674                         pic14_emitcode("mov","c,acc.7");
6675                         pic14_emitcode("rrc","a");
6676                 } else {
6677                         tlbl = newiTempLabel(NULL);
6678                         /* rotate right accumulator */
6679                         AccRol(8 - shCount);
6680                         /* and kill the higher order bits */
6681                         pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6682                         pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6683                         pic14_emitcode("orl","a,#0x%02x",
6684                                 (unsigned char)~SRMask[shCount]);
6685                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6686                 }
6687         }
6688 }
6689
6690 /*-----------------------------------------------------------------*/
6691 /* shiftR1Left2Result - shift right one byte from left to result   */
6692 /*-----------------------------------------------------------------*/
6693 static void shiftR1Left2ResultSigned (operand *left, int offl,
6694                                                                           operand *result, int offr,
6695                                                                           int shCount)
6696 {
6697         int same;
6698         
6699         FENTRY;
6700         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6701         
6702         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6703         
6704         switch(shCount) {
6705         case 1:
6706                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6707                 if(same) 
6708                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6709                 else {
6710                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6711                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6712                 }
6713                 
6714                 break;
6715         case 2:
6716                 
6717                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6718                 if(same) 
6719                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6720                 else {
6721                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6722                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6723                 }
6724                 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6725                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6726                 
6727                 break;
6728                 
6729         case 3:
6730                 if(same)
6731                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6732                 else {
6733                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6734                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6735                 }
6736                 
6737                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6738                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6739                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6740                 
6741                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6742                 emitpcode(POC_IORLW, popGetLit(0xe0));
6743                 
6744                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6745                 break;
6746                 
6747         case 4:
6748                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6749                 emitpcode(POC_ANDLW,  popGetLit(0x0f));
6750                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6751                 emitpcode(POC_IORLW,  popGetLit(0xf0));
6752                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6753                 break;
6754         case 5:
6755                 if(same) {
6756                         emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6757                 } else {
6758                         emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6759                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6760                 }
6761                 emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6762                 emitpcode(POC_ANDLW,  popGetLit(0x07));
6763                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6764                 emitpcode(POC_IORLW,  popGetLit(0xf8));
6765                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6766                 break;
6767                 
6768         case 6:
6769                 if(same) {
6770                         emitpcode(POC_MOVLW, popGetLit(0x00));
6771                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6772                         emitpcode(POC_MOVLW, popGetLit(0xfe));
6773                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6774                         emitpcode(POC_IORLW, popGetLit(0x01));
6775                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6776                 } else {
6777                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6778                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6779                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6780                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6781                         emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6782                 }
6783                 break;
6784                 
6785         case 7:
6786                 if(same) {
6787                         emitpcode(POC_MOVLW, popGetLit(0x00));
6788                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6789                         emitpcode(POC_MOVLW, popGetLit(0xff));
6790                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6791                 } else {
6792                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6793                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6794                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6795                 }
6796                 
6797         default:
6798                 break;
6799         }
6800 }
6801
6802 /*-----------------------------------------------------------------*/
6803 /* shiftR1Left2Result - shift right one byte from left to result   */
6804 /*-----------------------------------------------------------------*/
6805 static void shiftR1Left2Result (operand *left, int offl,
6806                                                                 operand *result, int offr,
6807                                                                 int shCount, int sign)
6808 {
6809         int same;
6810         
6811         FENTRY;
6812         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6813         
6814         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6815         
6816         /* Copy the msb into the carry if signed. */
6817         if(sign) {
6818                 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6819                 return;
6820         }
6821         
6822         
6823         
6824         switch(shCount) {
6825         case 1:
6826                 emitCLRC;
6827                 if(same) 
6828                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6829                 else {
6830                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6831                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6832                 }
6833                 break;
6834         case 2:
6835                 emitCLRC;
6836                 if(same) {
6837                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6838                 } else {
6839                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6840                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6841                 }
6842                 emitCLRC;
6843                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6844                 
6845                 break;
6846         case 3:
6847                 if(same)
6848                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6849                 else {
6850                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6851                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6852                 }
6853                 
6854                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6855                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6856                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6857                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6858                 break;
6859                 
6860         case 4:
6861                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6862                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6863                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6864                 break;
6865                 
6866         case 5:
6867                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6868                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6869                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6870                 emitCLRC;
6871                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6872                 
6873                 break;
6874         case 6:
6875                 
6876                 emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6877                 emitpcode(POC_ANDLW, popGetLit(0x80));
6878                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6879                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6880                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6881                 break;
6882                 
6883         case 7:
6884                 
6885                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6886                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6887                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6888                 
6889                 break;
6890                 
6891         default:
6892                 break;
6893         }
6894 }
6895
6896 /*-----------------------------------------------------------------*/
6897 /* shiftL1Left2Result - shift left one byte from left to result    */
6898 /*-----------------------------------------------------------------*/
6899 static void shiftL1Left2Result (operand *left, int offl,
6900                                                                 operand *result, int offr, int shCount)
6901 {
6902         int same;
6903         
6904         //    char *l;
6905         FENTRY;
6906         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6907         
6908         same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6909         DEBUGpic14_emitcode ("; ***","same =  %d",same);
6910         //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6911         //    MOVA(l);
6912         /* shift left accumulator */
6913         //AccLsh(shCount); // don't comment out just yet...
6914         //    aopPut(AOP(result),"a",offr);
6915         
6916         switch(shCount) {
6917         case 1:
6918                 /* Shift left 1 bit position */
6919                 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6920                 if(same) {
6921                         emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6922                 } else {
6923                         emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6924                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6925                 }
6926                 break;
6927         case 2:
6928                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6929                 emitpcode(POC_ANDLW,popGetLit(0x7e));
6930                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6931                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6932                 break;
6933         case 3:
6934                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6935                 emitpcode(POC_ANDLW,popGetLit(0x3e));
6936                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6937                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6938                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6939                 break;
6940         case 4:
6941                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6942                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6943                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6944                 break;
6945         case 5:
6946                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6947                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6948                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6949                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6950                 break;
6951         case 6:
6952                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6953                 emitpcode(POC_ANDLW, popGetLit(0x30));
6954                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6955                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6956                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6957                 break;
6958         case 7:
6959                 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6960                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6961                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6962                 break;
6963                 
6964         default:
6965                 DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6966         }
6967         
6968 }
6969 #endif
6970
6971 /*-----------------------------------------------------------------*/
6972 /* movLeft2Result - move byte from left to result                  */
6973 /*-----------------------------------------------------------------*/
6974 static void movLeft2Result (operand *left, int offl,
6975                                                         operand *result, int offr)
6976 {
6977         char *l;
6978         FENTRY;
6979         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6980         if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6981                 l = aopGet(AOP(left),offl,FALSE,FALSE);
6982                 
6983                 if (*l == '@' && (IS_AOP_PREG(result))) {
6984                         pic14_emitcode("mov","a,%s",l);
6985                         aopPut(AOP(result),"a",offr);
6986                 } else {
6987                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6988                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6989                 }
6990         }
6991 }
6992
6993 /*-----------------------------------------------------------------*/
6994 /* shiftLeft_Left2ResultLit - shift left by known count            */
6995 /*-----------------------------------------------------------------*/
6996
6997 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6998 {
6999         int size, same, offr, i;
7000
7001         size = AOP_SIZE(left);
7002         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7003         
7004         same = pic14_sameRegs (AOP(left), AOP(result));
7005         
7006         offr = shCount / 8;
7007         shCount = shCount & 0x07;
7008
7009         size -= offr;
7010
7011         switch (shCount)
7012         {
7013         case 0: /* takes 0 or 2N cycles (for offr==0) */
7014                 if (!same || offr) {
7015                         for (i=size-1; i >= 0; i--)
7016                                 movLeft2Result (left, i, result, offr + i);
7017                 } // if
7018                 break;
7019                 
7020         case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
7021                 if (same && offr) {
7022                         shiftLeft_Left2ResultLit (left, result, 8 * offr);
7023                         shiftLeft_Left2ResultLit (result, result, shCount);
7024                         return; /* prevent clearing result again */
7025                 } else {
7026                         emitCLRC;
7027                         for (i=0; i < size; i++) {
7028                                 if (same && !offr) {
7029                                         emitpcode (POC_RLF, popGet (AOP(left), i));
7030                                 } else {
7031                                         emitpcode (POC_RLFW, popGet (AOP(left), i));
7032                                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7033                                 } // if
7034                         } // for
7035                 } // if (offr)
7036                 break;
7037                 
7038         case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
7039                 /* works in-place/with offr as well */
7040                 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
7041                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7042                 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
7043
7044                 for (i = size - 2; i >= 0; i--)
7045                 {
7046                         emitpcode (POC_SWAPFW, popGet (AOP(left), i));
7047                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7048                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7049                         emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
7050                         emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
7051                 } // for i
7052                 break;
7053                 
7054         case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7055                 /* works in-place/with offr as well */
7056                 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7057                 for (i = size-2; i >= 0; i--) {
7058                         emitpcode (POC_RRFW, popGet (AOP(left), i));
7059                         emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7060                 } // for i
7061                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7062                 emitpcode (POC_RRF, popGet (AOP(result), offr));
7063                 break;
7064         
7065         default:
7066                 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7067                 shiftLeft_Left2ResultLit (result, result, 1);
7068                 return; /* prevent clearing result again */
7069                 break;
7070         } // switch
7071
7072         while (0 < offr--)
7073         {
7074                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7075         } // while
7076 }
7077
7078 /*-----------------------------------------------------------------*/
7079 /* shiftRight_Left2ResultLit - shift right by known count          */
7080 /*-----------------------------------------------------------------*/
7081
7082 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7083 {
7084         int size, same, offr, i;
7085
7086         size = AOP_SIZE(left);
7087         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7088         
7089         same = pic14_sameRegs (AOP(left), AOP(result));
7090         
7091         offr = shCount / 8;
7092         shCount = shCount & 0x07;
7093
7094         size -= offr;
7095
7096         if (size)
7097         {
7098                 switch (shCount)
7099                 {
7100                 case 0: /* takes 0 or 2N cycles (for offr==0) */
7101                         if (!same || offr) {
7102                                 for (i=0; i < size; i++)
7103                                         movLeft2Result (left, i + offr, result, i);
7104                         } // if
7105                         break;
7106                         
7107                 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7108                         emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7109                         if (same && offr) {
7110                                 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7111                                 shiftRight_Left2ResultLit (result, result, shCount, sign);
7112                                 return; /* prevent sign-extending result again */
7113                         } else {
7114                                 emitCLRC;
7115                                 if (sign) {
7116                                         emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7117                                         emitSETC;
7118                                 }
7119                                 for (i = size-1; i >= 0; i--) {
7120                                         if (same && !offr) {
7121                                                 emitpcode (POC_RRF, popGet (AOP(left), i));
7122                                         } else {
7123                                                 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7124                                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7125                                         }
7126                                 } // for i
7127                         } // if (offr)
7128                         break;
7129                         
7130                 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7131                         /* works in-place/with offr as well */
7132                         emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7133                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7134                         emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7135
7136                         for (i = 1; i < size; i++)
7137                         {
7138                                 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7139                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7140                                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7141                                 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7142                                 emitpcode (POC_XORWF, popGet (AOP(result), i));
7143                         } // for i
7144
7145                         if (sign)
7146                         {
7147                                 emitpcode (POC_MOVLW, popGetLit (0xF0));
7148                                 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7149                                 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7150                         } // if
7151                         break;
7152                         
7153                 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7154                         /* works in-place/with offr as well */
7155                         emitpcode (POC_RLFW, popGet (AOP(left), offr));
7156                         for (i = 0; i < size-1; i++) {
7157                                 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7158                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7159                         } // for i
7160                         emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7161                         if (!sign) {
7162                                 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7163                         } else {
7164                                 emitSKPNC;
7165                                 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7166                         }
7167                         break;
7168                 
7169                 default:
7170                         shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7171                         shiftRight_Left2ResultLit (result, result, 1, sign);
7172                         return; /* prevent sign extending result again */
7173                         break;
7174                 } // switch
7175         } // if
7176
7177         addSign (result, size, sign);
7178 }
7179
7180 #if 0
7181 /*-----------------------------------------------------------------*/
7182 /* shiftL2Left2Result - shift left two bytes from left to result   */
7183 /*-----------------------------------------------------------------*/
7184 static void shiftL2Left2Result (operand *left, int offl,
7185                                                                 operand *result, int offr, int shCount)
7186 {
7187         FENTRY;
7188         
7189         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7190         
7191         if(pic14_sameRegs(AOP(result), AOP(left))) {
7192                 switch(shCount) {
7193                 case 0:
7194                         break;
7195                 case 1:
7196                 case 2:
7197                 case 3:
7198                         
7199                         emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7200                         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7201                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7202                         
7203                         while(--shCount) {
7204                                 emitCLRC;
7205                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7206                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7207                         }
7208                         
7209                         break;
7210                 case 4:
7211                 case 5:
7212                         emitpcode(POC_MOVLW, popGetLit(0x0f));
7213                         emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7214                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7215                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7216                         emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7217                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7218                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7219                         if(shCount >=5) {
7220                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7221                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7222                         }
7223                         break;
7224                 case 6:
7225                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7226                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7227                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7228                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7229                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7230                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7231                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7232                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7233                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7234                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7235                         break;
7236                 case 7:
7237                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7238                         emitpcode(POC_RRFW, popGet(AOP(result),offr));
7239                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7240                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7241                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7242                 }
7243                 
7244         } else {
7245                 switch(shCount) {
7246                 case 0:
7247                         break;
7248                 case 1:
7249                 case 2:
7250                 case 3:
7251                 /* note, use a mov/add for the shift since the mov has a
7252                         chance of getting optimized out */
7253                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7254                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7255                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7256                         emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
7257                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7258                         
7259                         while(--shCount) {
7260                                 emitCLRC;
7261                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7262                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7263                         }
7264                         break;
7265                         
7266                 case 4:
7267                 case 5:
7268                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7269                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7270                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7271                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7272                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7273                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7274                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7275                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7276                         
7277                         
7278                         if(shCount == 5) {
7279                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7280                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7281                         }
7282                         break;
7283                 case 6:
7284                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7285                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7286                         emitpcode(POC_RRFW, popGet(AOP(result),offl));
7287                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
7288                         
7289                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7290                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7291                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7292                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7293                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7294                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7295                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7296                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7297                         break;
7298                 case 7:
7299                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7300                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7301                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7302                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7303                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7304                 }
7305         }
7306         
7307 }
7308
7309 /*-----------------------------------------------------------------*/
7310 /* shiftR2Left2Result - shift right two bytes from left to result  */
7311 /*-----------------------------------------------------------------*/
7312 static void shiftR2Left2Result (operand *left, int offl,
7313                                                                 operand *result, int offr,
7314                                                                 int shCount, int sign)
7315 {
7316         int same=0;
7317         
7318         FENTRY;
7319         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7320         same = pic14_sameRegs(AOP(result), AOP(left));
7321         
7322         if(same && ((offl + MSB16) == offr)){
7323                 same=1;
7324                 /* don't crash result[offr] */
7325                 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7326                 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7327         }
7328         /* else {
7329         movLeft2Result(left,offl, result, offr);
7330         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7331         }
7332         */
7333         /* a:x >> shCount (x = lsb(result))*/
7334         /*
7335         if(sign)
7336         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7337         else {
7338         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7339         */
7340         switch(shCount) {
7341         case 0:
7342                 break;
7343         case 1:
7344         case 2:
7345         case 3:
7346                 if(sign)
7347                         emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7348                 else
7349                         emitCLRC;
7350                 
7351                 if(same) {
7352                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7353                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7354                 } else {
7355                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7356                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7357                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7358                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7359                 }
7360                 
7361                 while(--shCount) {
7362                         if(sign)
7363                                 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7364                         else
7365                                 emitCLRC;
7366                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7367                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7368                 }
7369                 break;
7370         case 4:
7371         case 5:
7372                 if(same) {
7373                         
7374                         emitpcode(POC_MOVLW, popGetLit(0xf0));
7375                         emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7376                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7377                         
7378                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7379                         emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7380                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7381                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7382                 } else {
7383                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7384                         emitpcode(POC_ANDLW, popGetLit(0x0f));
7385                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7386                         
7387                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7388                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7389                         emitpcode(POC_ANDLW, popGetLit(0xf0));
7390                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7391                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7392                 }
7393                 
7394                 if(shCount >=5) {
7395                         emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7396                         emitpcode(POC_RRF, popGet(AOP(result),offr));
7397                 }
7398                 
7399                 if(sign) {
7400                         emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7401                         emitpcode(POC_BTFSC, 
7402                                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7403                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7404                 }
7405                 
7406                 break;
7407                 
7408         case 6:
7409                 if(same) {
7410                         
7411                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7412                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7413                         
7414                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7415                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7416                         emitpcode(POC_RLFW, popGet(AOP(result),offr));
7417                         emitpcode(POC_ANDLW,popGetLit(0x03));
7418                         if(sign) {
7419                                 emitpcode(POC_BTFSC, 
7420                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7421                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7422                         }
7423                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7424                         emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7425                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7426                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7427                 } else {
7428                         emitpcode(POC_RLFW, popGet(AOP(left),offl));
7429                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7430                         emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7431                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7432                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7433                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7434                         emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7435                         emitpcode(POC_ANDLW,popGetLit(0x03));
7436                         if(sign) {
7437                                 emitpcode(POC_BTFSC, 
7438                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7439                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7440                         }
7441                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7442                         //emitpcode(POC_RLF,  popGet(AOP(result),offr));
7443                         
7444                         
7445                 }
7446                 
7447                 break;
7448         case 7:
7449                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7450                 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7451                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7452                 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7453                 if(sign) {
7454                         emitSKPNC;
7455                         emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7456                 } else 
7457                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7458   }
7459 }
7460
7461 /*-----------------------------------------------------------------*/
7462 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7463 /*-----------------------------------------------------------------*/
7464 static void shiftLLeftOrResult (operand *left, int offl,
7465                                                                 operand *result, int offr, int shCount)
7466 {
7467         FENTRY;
7468         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7469         
7470         /* shift left accumulator */
7471         AccLsh(left,offl,shCount);
7472         /* or with result */
7473         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7474         assert ( !"broken (modifies left, fails for left==result))" );
7475 }
7476
7477 /*-----------------------------------------------------------------*/
7478 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7479 /*-----------------------------------------------------------------*/
7480 static void shiftRLeftOrResult (operand *left, int offl,
7481                                                                 operand *result, int offr, int shCount)
7482 {
7483         FENTRY;
7484         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7485         
7486         /* shift right accumulator */
7487         AccRsh(left,offl,shCount);
7488         /* or with result */
7489         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7490         assert ( !"broken (modifies left, fails for left==result))" );
7491 }
7492
7493 /*-----------------------------------------------------------------*/
7494 /* genlshOne - left shift a one byte quantity by known count       */
7495 /*-----------------------------------------------------------------*/
7496 static void genlshOne (operand *result, operand *left, int shCount)
7497 {       
7498         FENTRY;
7499         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7500         shiftL1Left2Result(left, LSB, result, LSB, shCount);
7501 }
7502
7503 /*-----------------------------------------------------------------*/
7504 /* genlshTwo - left shift two bytes by known amount != 0           */
7505 /*-----------------------------------------------------------------*/
7506 static void genlshTwo (operand *result,operand *left, int shCount)
7507 {
7508         int size;
7509         
7510         FENTRY;
7511         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7512         size = pic14_getDataSize(result);
7513         
7514         /* if shCount >= 8 */
7515         if (shCount >= 8) {
7516                 shCount -= 8 ;
7517                 
7518                 if (size > 1){
7519                         if (shCount)
7520                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7521                         else 
7522                                 movLeft2Result(left, LSB, result, MSB16);
7523                 }
7524                 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7525         }
7526         
7527         /*  1 <= shCount <= 7 */
7528         else {  
7529                 if(size == 1)
7530                         shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7531                 else 
7532                         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7533         }
7534 }
7535
7536 /*-----------------------------------------------------------------*/
7537 /* shiftLLong - shift left one long from left to result            */
7538 /* offl = LSB or MSB16                                             */
7539 /*-----------------------------------------------------------------*/
7540 static void shiftLLong (operand *left, operand *result, int offr )
7541 {
7542         char *l;
7543         int size = AOP_SIZE(result);
7544         
7545         FENTRY;
7546         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7547         if(size >= LSB+offr){
7548                 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7549                 MOVA(l);
7550                 pic14_emitcode("add","a,acc");
7551                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7552                         size >= MSB16+offr && offr != LSB )
7553                         pic14_emitcode("xch","a,%s",
7554                         aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7555                 else      
7556                         aopPut(AOP(result),"a",LSB+offr);
7557         }
7558         
7559         if(size >= MSB16+offr){
7560                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7561                         l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7562                         MOVA(l);
7563                 }
7564                 pic14_emitcode("rlc","a");
7565                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7566                         size >= MSB24+offr && offr != LSB)
7567                         pic14_emitcode("xch","a,%s",
7568                         aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7569                 else      
7570                         aopPut(AOP(result),"a",MSB16+offr);
7571         }
7572         
7573         if(size >= MSB24+offr){
7574                 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7575                         l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7576                         MOVA(l);
7577                 }
7578                 pic14_emitcode("rlc","a");
7579                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7580                         size >= MSB32+offr && offr != LSB )
7581                         pic14_emitcode("xch","a,%s",
7582                         aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7583                 else      
7584                         aopPut(AOP(result),"a",MSB24+offr);
7585         }
7586         
7587         if(size > MSB32+offr){
7588                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7589                         l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7590                         MOVA(l);  
7591                 }
7592                 pic14_emitcode("rlc","a");
7593                 aopPut(AOP(result),"a",MSB32+offr);
7594         }
7595         if(offr != LSB)
7596                 aopPut(AOP(result),zero,LSB);       
7597 }
7598
7599 /*-----------------------------------------------------------------*/
7600 /* genlshFour - shift four byte by a known amount != 0             */
7601 /*-----------------------------------------------------------------*/
7602 static void genlshFour (operand *result, operand *left, int shCount)
7603 {
7604         int size;
7605         
7606         FENTRY;
7607         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7608         size = AOP_SIZE(result);
7609         
7610         /* if shifting more that 3 bytes */
7611         if (shCount >= 24 ) {
7612                 shCount -= 24;
7613                 if (shCount)
7614                 /* lowest order of left goes to the highest
7615                 order of the destination */
7616                 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7617                 else
7618                         movLeft2Result(left, LSB, result, MSB32);
7619                 aopPut(AOP(result),zero,LSB);
7620                 aopPut(AOP(result),zero,MSB16);
7621                 aopPut(AOP(result),zero,MSB32);
7622                 return;
7623         }
7624         
7625         /* more than two bytes */
7626         else if ( shCount >= 16 ) {
7627                 /* lower order two bytes goes to higher order two bytes */
7628                 shCount -= 16;
7629                 /* if some more remaining */
7630                 if (shCount)
7631                         shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7632                 else {
7633                         movLeft2Result(left, MSB16, result, MSB32);
7634                         movLeft2Result(left, LSB, result, MSB24);
7635                 }
7636                 aopPut(AOP(result),zero,MSB16);
7637                 aopPut(AOP(result),zero,LSB);
7638                 return;
7639         }    
7640         
7641         /* if more than 1 byte */
7642         else if ( shCount >= 8 ) {
7643                 /* lower order three bytes goes to higher order  three bytes */
7644                 shCount -= 8;
7645                 if(size == 2){
7646                         if(shCount)
7647                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7648                         else
7649                                 movLeft2Result(left, LSB, result, MSB16);
7650                 }
7651                 else{   /* size = 4 */
7652                         if(shCount == 0){
7653                                 movLeft2Result(left, MSB24, result, MSB32);
7654                                 movLeft2Result(left, MSB16, result, MSB24);
7655                                 movLeft2Result(left, LSB, result, MSB16);
7656                                 aopPut(AOP(result),zero,LSB);
7657                         }
7658                         else if(shCount == 1)
7659                                 shiftLLong(left, result, MSB16);
7660                         else{
7661                                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7662                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7663                                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7664                                 aopPut(AOP(result),zero,LSB);
7665                         }
7666                 }
7667         }
7668         
7669         /* 1 <= shCount <= 7 */
7670         else if(shCount <= 2){
7671                 shiftLLong(left, result, LSB);
7672                 if(shCount == 2)
7673                         shiftLLong(result, result, LSB);
7674         }
7675         /* 3 <= shCount <= 7, optimize */
7676         else{
7677                 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7678                 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7679                 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7680         }
7681 }
7682 #endif
7683
7684 #if 0
7685 /*-----------------------------------------------------------------*/
7686 /* genLeftShiftLiteral - left shifting by known count              */
7687 /*-----------------------------------------------------------------*/
7688 static void genLeftShiftLiteral (operand *left,
7689                                                                  operand *right,
7690                                                                  operand *result,
7691                                                                  iCode *ic)
7692 {    
7693         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7694         //int size;
7695         
7696         FENTRY;
7697         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7698         freeAsmop(right,NULL,ic,TRUE);
7699         
7700         aopOp(left,ic,FALSE);
7701         aopOp(result,ic,FALSE);
7702
7703         size = getSize(operandType(result));
7704         
7705 #if VIEW_SIZE
7706         pic14_emitcode("; shift left ","result %d, left %d",size,
7707                 AOP_SIZE(left));
7708 #endif
7709         
7710         /* I suppose that the left size >= result size */
7711         if(shCount == 0){
7712                 while(size--){
7713                         movLeft2Result(left, size, result, size);
7714                 }
7715         }
7716         
7717         else if(shCount >= (size * 8))
7718                 while(size--)
7719                         aopPut(AOP(result),zero,size);
7720                 else{
7721                         switch (size) {
7722                         case 1:
7723                                 genlshOne (result,left,shCount);
7724                                 break;
7725                                 
7726                         case 2:
7727                         case 3:
7728                                 genlshTwo (result,left,shCount);
7729                                 break;
7730                                 
7731                         case 4:
7732                                 genlshFour (result,left,shCount);
7733                                 break;
7734                         }
7735                 }
7736                 freeAsmop(left,NULL,ic,TRUE);
7737                 freeAsmop(result,NULL,ic,TRUE);
7738 }
7739 #endif
7740
7741 /*-----------------------------------------------------------------*
7742 * genMultiAsm - repeat assembly instruction for size of register.
7743 * if endian == 1, then the high byte (i.e base address + size of 
7744 * register) is used first else the low byte is used first;
7745 *-----------------------------------------------------------------*/
7746 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7747 {
7748         
7749         int offset = 0;
7750         
7751         FENTRY;
7752         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7753         
7754         if(!reg)
7755                 return;
7756         
7757         if(!endian) {
7758                 endian = 1;
7759         } else {
7760                 endian = -1;
7761                 offset = size-1;
7762         }
7763         
7764         while(size--) {
7765                 emitpcode(poc,    popGet(AOP(reg),offset));
7766                 offset += endian;
7767         }
7768         
7769 }
7770
7771 #if 0
7772 /*-----------------------------------------------------------------*/
7773 /* genLeftShift - generates code for left shifting                 */
7774 /*-----------------------------------------------------------------*/
7775 static void genLeftShift (iCode *ic)
7776 {
7777         operand *left,*right, *result;
7778         int size, offset;
7779         unsigned long lit = 0L;
7780         char *l;
7781         symbol *tlbl , *tlbl1;
7782         pCodeOp *pctemp;
7783         
7784         FENTRY;
7785         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7786         
7787         right = IC_RIGHT(ic);
7788         left  = IC_LEFT(ic);
7789         result = IC_RESULT(ic);
7790         
7791         aopOp(right,ic,FALSE);
7792         aopOp(left,ic,FALSE);
7793         aopOp(result,ic,FALSE);
7794         
7795         
7796         /* if the shift count is known then do it 
7797         as efficiently as possible */
7798         if (AOP_TYPE(right) == AOP_LIT) {
7799                 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7800                 return ;
7801         }
7802         
7803         /* shift count is unknown then we have to form 
7804         a loop get the loop count in B : Note: we take
7805         only the lower order byte since shifting
7806         more that 32 bits make no sense anyway, ( the
7807         largest size of an object can be only 32 bits ) */  
7808         
7809         /* this code fails for RIGHT == RESULT */
7810         assert (!pic14_sameRegs (AOP(right), AOP(result)));
7811         
7812         /* now move the left to the result if they are not the
7813         same */
7814         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7815                 AOP_SIZE(result) > 1) {
7816                 
7817                 size = AOP_SIZE(result);
7818                 offset=0;
7819                 while (size--) {
7820                         l = aopGet(AOP(left),offset,FALSE,TRUE);
7821                         if (*l == '@' && (IS_AOP_PREG(result))) {
7822                                 
7823                                 pic14_emitcode("mov","a,%s",l);
7824                                 aopPut(AOP(result),"a",offset);
7825                         } else {
7826                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7827                                 emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7828                                 //aopPut(AOP(result),l,offset);
7829                         }
7830                         offset++;
7831                 }
7832         }
7833         
7834         if(AOP_TYPE(left) == AOP_LIT)
7835                 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7836
7837         size = AOP_SIZE(result);
7838         
7839         /* if it is only one byte then */
7840         if (size == 1) {
7841                 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7842                         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7843                         emitpcode(POC_ANDLW,  popGetLit(0xf0));
7844                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7845                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7846                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7847                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7848                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7849                         emitpcode(POC_RLFW,   popGet(AOP(result),0));
7850                         emitpcode(POC_ANDLW,  popGetLit(0xfe));
7851                         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7852                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7853                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7854                 } else {
7855                         
7856                         tlbl = newiTempLabel(NULL);
7857                         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7858                                 mov2w (AOP(left), 0);
7859                                 emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7860                         }
7861                         
7862                         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7863                         emitpcode(POC_RRF,    popGet(AOP(result),0));
7864                         emitpLabel(tlbl->key);
7865                         emitpcode(POC_RLF,    popGet(AOP(result),0));
7866                         emitpcode(POC_ADDLW,  popGetLit(1));
7867                         emitSKPC;
7868                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7869                 }
7870                 goto release ;
7871         }
7872         
7873         if (pic14_sameRegs(AOP(left),AOP(result))) {
7874                 
7875                 tlbl = newiTempLabel(NULL);
7876                 emitpcode(POC_COMFW,  popGet(AOP(right),0));
7877                 genMultiAsm(POC_RRF, result, size,1);
7878                 emitpLabel(tlbl->key);
7879                 genMultiAsm(POC_RLF, result, size,0);
7880                 emitpcode(POC_ADDLW,  popGetLit(1));
7881                 emitSKPC;
7882                 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7883                 goto release;
7884         }
7885         
7886         //tlbl = newiTempLabel(NULL);
7887         //offset = 0 ;   
7888         //tlbl1 = newiTempLabel(NULL);
7889         
7890         //reAdjustPreg(AOP(result));    
7891         
7892         //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7893         //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7894         //l = aopGet(AOP(result),offset,FALSE,FALSE);
7895         //MOVA(l);
7896         //pic14_emitcode("add","a,acc");         
7897         //aopPut(AOP(result),"a",offset++);
7898         //while (--size) {
7899         //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7900         //  MOVA(l);
7901         //  pic14_emitcode("rlc","a");         
7902         //  aopPut(AOP(result),"a",offset++);
7903         //}
7904         //reAdjustPreg(AOP(result));
7905         
7906         //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7907         //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7908         
7909         
7910         tlbl = newiTempLabel(NULL);
7911         tlbl1= newiTempLabel(NULL);
7912         
7913         size = AOP_SIZE(result);
7914         offset = 1;
7915         
7916         pctemp = popGetTempReg();  /* grab a temporary working register. */
7917         
7918         emitpcode(POC_MOVFW, popGet(AOP(right),0));
7919         
7920         /* offset should be 0, 1 or 3 */
7921         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7922         emitSKPNZ;
7923         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7924         
7925         emitpcode(POC_MOVWF, pctemp);
7926         
7927         
7928         emitpLabel(tlbl->key);
7929         
7930         emitCLRC;
7931         emitpcode(POC_RLF,  popGet(AOP(result),0));
7932         while(--size)
7933                 emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7934         
7935         emitpcode(POC_DECFSZ,  pctemp);
7936         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7937         emitpLabel(tlbl1->key);
7938         
7939         popReleaseTempReg(pctemp);
7940         
7941         
7942 release:
7943         freeAsmop (right,NULL,ic,TRUE);
7944         freeAsmop(left,NULL,ic,TRUE);
7945         freeAsmop(result,NULL,ic,TRUE);
7946 }
7947 #endif
7948
7949 #if 0
7950 /*-----------------------------------------------------------------*/
7951 /* genrshOne - right shift a one byte quantity by known count      */
7952 /*-----------------------------------------------------------------*/
7953 static void genrshOne (operand *result, operand *left,
7954                                            int shCount, int sign)
7955 {
7956         FENTRY;
7957         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7958         shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7959 }
7960
7961 /*-----------------------------------------------------------------*/
7962 /* genrshTwo - right shift two bytes by known amount != 0          */
7963 /*-----------------------------------------------------------------*/
7964 static void genrshTwo (operand *result,operand *left,
7965                                            int shCount, int sign)
7966 {
7967         FENTRY;
7968         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7969         /* if shCount >= 8 */
7970         if (shCount >= 8) {
7971                 shCount -= 8 ;
7972                 if (shCount)
7973                         shiftR1Left2Result(left, MSB16, result, LSB,
7974                         shCount, sign);
7975                 else
7976                         movLeft2Result(left, MSB16, result, LSB);
7977                 
7978                 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7979                 
7980                 if(sign) {
7981                         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7982                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7983                 }
7984         }
7985         
7986         /*  1 <= shCount <= 7 */
7987         else
7988                 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7989 }
7990
7991 /*-----------------------------------------------------------------*/
7992 /* shiftRLong - shift right one long from left to result           */
7993 /* offl = LSB or MSB16                                             */
7994 /*-----------------------------------------------------------------*/
7995 static void shiftRLong (operand *left, int offl,
7996                                                 operand *result, int sign)
7997 {
7998         int size, same;
7999         
8000         FENTRY;
8001         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8002         
8003         size = AOP_SIZE(left);
8004         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
8005         
8006         if (sign)
8007                 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
8008         else
8009                 emitCLRC;
8010
8011         assert (offl >= 0 && offl < size);
8012
8013         same = pic14_sameRegs (AOP(left), AOP(result));
8014
8015         /* perform the shift */
8016         while (size--)
8017         {
8018                 if (same && !offl) {
8019                         emitpcode (POC_RRF, popGet (AOP(result), size));
8020                 } else {
8021                         emitpcode (POC_RRFW, popGet (AOP(left), size));
8022                         emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
8023                 }
8024         } // while
8025
8026         addSign (result, AOP_SIZE(left) - offl, sign);
8027 }
8028
8029 /*-----------------------------------------------------------------*/
8030 /* genrshFour - shift four byte by a known amount != 0             */
8031 /*-----------------------------------------------------------------*/
8032 static void genrshFour (operand *result, operand *left,
8033                                                 int shCount, int sign)
8034 {
8035         FENTRY;
8036         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8037         /* if shifting more that 3 bytes */
8038         if(shCount >= 24 ) {
8039                 shCount -= 24;
8040                 if(shCount)
8041                         shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8042                 else
8043                         movLeft2Result(left, MSB32, result, LSB);
8044                 
8045                 addSign(result, MSB16, sign);
8046         }
8047         else if(shCount >= 16){
8048                 shCount -= 16;
8049                 if(shCount)
8050                         shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8051                 else{
8052                         movLeft2Result(left, MSB24, result, LSB);
8053                         movLeft2Result(left, MSB32, result, MSB16);
8054                 }
8055                 addSign(result, MSB24, sign);
8056         }
8057         else if(shCount >= 8){
8058                 shCount -= 8;
8059                 if(shCount == 1)
8060                         shiftRLong(left, MSB16, result, sign);
8061                 else if(shCount == 0){
8062                         movLeft2Result(left, MSB16, result, LSB);
8063                         movLeft2Result(left, MSB24, result, MSB16);
8064                         movLeft2Result(left, MSB32, result, MSB24);
8065                         addSign(result, MSB32, sign);
8066                 }
8067                 else{
8068                         shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8069                         shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8070                         /* the last shift is signed */
8071                         shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8072                         addSign(result, MSB32, sign);
8073                 }
8074         }
8075         else{   /* 1 <= shCount <= 7 */
8076                 if(shCount <= 2){
8077                         shiftRLong(left, LSB, result, sign);
8078                         if(shCount == 2)
8079                                 shiftRLong(result, LSB, result, sign);
8080                 }
8081                 else{
8082                         shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8083                         shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8084                         shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8085                 }
8086         }
8087 }
8088
8089 /*-----------------------------------------------------------------*/
8090 /* genRightShiftLiteral - right shifting by known count            */
8091 /*-----------------------------------------------------------------*/
8092 static void genRightShiftLiteral (operand *left,
8093                                                                   operand *right,
8094                                                                   operand *result,
8095                                                                   iCode *ic,
8096                                                                   int sign)
8097 {    
8098         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8099         int lsize,res_size;
8100         
8101         FENTRY;
8102         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8103         freeAsmop(right,NULL,ic,TRUE);
8104         
8105         aopOp(left,ic,FALSE);
8106         aopOp(result,ic,FALSE);
8107         
8108 #if VIEW_SIZE
8109         pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8110                 AOP_SIZE(left));
8111 #endif
8112         
8113         lsize = pic14_getDataSize(left);
8114         res_size = pic14_getDataSize(result);
8115         /* test the LEFT size !!! */
8116         
8117         /* I suppose that the left size >= result size */
8118         if(shCount == 0){
8119                 while(res_size--)
8120                         movLeft2Result(left, res_size, result, res_size);
8121         }
8122         
8123         else if(shCount >= (lsize * 8)){
8124                 
8125                 if(res_size == 1) {
8126                         emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8127                         if(sign) {
8128                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8129                                 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8130                         }
8131                 } else {
8132                         
8133                         if(sign) {
8134                                 emitpcode(POC_MOVLW, popGetLit(0));
8135                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8136                                 emitpcode(POC_MOVLW, popGetLit(0xff));
8137                                 while(res_size--)
8138                                         emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8139                                 
8140                         } else {
8141                                 
8142                                 while(res_size--)
8143                                         emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8144                         }
8145                 }
8146         } else {
8147                 
8148                 switch (res_size) {
8149                 case 1:
8150                         genrshOne (result,left,shCount,sign);
8151                         break;
8152                         
8153                 case 2:
8154                         genrshTwo (result,left,shCount,sign);
8155                         break;
8156                         
8157                 case 4:
8158                         genrshFour (result,left,shCount,sign);
8159                         break;
8160                 default :
8161                         break;
8162                 }
8163                 
8164         }
8165
8166         freeAsmop(left,NULL,ic,TRUE);
8167         freeAsmop(result,NULL,ic,TRUE);
8168 }
8169 #endif
8170
8171 #if 0
8172 /*-----------------------------------------------------------------*/
8173 /* genSignedRightShift - right shift of signed number              */
8174 /*-----------------------------------------------------------------*/
8175 static void genSignedRightShift (iCode *ic)
8176 {
8177         operand *right, *left, *result;
8178         int size, offset;
8179         //  char *l;
8180         symbol *tlbl, *tlbl1 ;
8181         pCodeOp *pctemp;
8182         
8183         //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8184         
8185         /* we do it the hard way put the shift count in b
8186         and loop thru preserving the sign */
8187         FENTRY;
8188         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8189         
8190         right = IC_RIGHT(ic);
8191         left  = IC_LEFT(ic);
8192         result = IC_RESULT(ic);
8193         
8194         aopOp(right,ic,FALSE);  
8195         aopOp(left,ic,FALSE);
8196         aopOp(result,ic,FALSE);
8197         
8198         
8199         if ( AOP_TYPE(right) == AOP_LIT) {
8200                 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8201                 //genRightShiftLiteral (left,right,result,ic,1);
8202                 return ;
8203         }
8204         /* shift count is unknown then we have to form 
8205         a loop get the loop count in B : Note: we take
8206         only the lower order byte since shifting
8207         more that 32 bits make no sense anyway, ( the
8208         largest size of an object can be only 32 bits ) */  
8209         
8210         //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8211         //pic14_emitcode("inc","b");
8212         //freeAsmop (right,NULL,ic,TRUE);
8213         //aopOp(left,ic,FALSE);
8214         //aopOp(result,ic,FALSE);
8215         
8216         /* now move the left to the result if they are not the
8217         same */
8218         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
8219                 AOP_SIZE(result) > 1) {
8220                 
8221                 size = AOP_SIZE(result);
8222                 offset=0;
8223                 while (size--) { 
8224                         /*
8225                         l = aopGet(AOP(left),offset,FALSE,TRUE);
8226                         if (*l == '@' && IS_AOP_PREG(result)) {
8227                                 pic14_emitcode("mov","a,%s",l);
8228                                 aopPut(AOP(result),"a",offset);
8229                         } else
8230                         aopPut(AOP(result),l,offset);
8231                         */
8232                         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
8233                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
8234                         
8235                         offset++;
8236                 }
8237         }
8238         
8239         /* mov the highest order bit to OVR */    
8240         tlbl = newiTempLabel(NULL);
8241         tlbl1= newiTempLabel(NULL);
8242         
8243         size = AOP_SIZE(result);
8244         offset = size - 1;
8245         
8246         pctemp = popGetTempReg();  /* grab a temporary working register. */
8247         
8248         emitpcode(POC_MOVFW, popGet(AOP(right),0));
8249         
8250         /* offset should be 0, 1 or 3 */
8251         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8252         emitSKPNZ;
8253         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
8254         
8255         emitpcode(POC_MOVWF, pctemp);
8256         
8257         
8258         emitpLabel(tlbl->key);
8259         
8260         emitpcode(POC_RLFW,  popGet(AOP(result),offset));
8261         emitpcode(POC_RRF,   popGet(AOP(result),offset));
8262         
8263         while(--size) {
8264                 emitpcode(POC_RRF,   popGet(AOP(result),--offset));
8265         }
8266         
8267         emitpcode(POC_DECFSZ,  pctemp);
8268         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8269         emitpLabel(tlbl1->key);
8270         
8271         popReleaseTempReg(pctemp);
8272 #if 0
8273         size = AOP_SIZE(result);
8274         offset = size - 1;
8275         pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8276         pic14_emitcode("rlc","a");
8277         pic14_emitcode("mov","ov,c");
8278         /* if it is only one byte then */
8279         if (size == 1) {
8280                 l = aopGet(AOP(left),0,FALSE,FALSE);
8281                 MOVA(l);
8282                 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8283                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8284                 pic14_emitcode("mov","c,ov");
8285                 pic14_emitcode("rrc","a");
8286                 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8287                 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8288                 aopPut(AOP(result),"a",0);
8289                 goto release ;
8290         }
8291         
8292         reAdjustPreg(AOP(result));
8293         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8294         pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
8295         pic14_emitcode("mov","c,ov");
8296         while (size--) {
8297                 l = aopGet(AOP(result),offset,FALSE,FALSE);
8298                 MOVA(l);
8299                 pic14_emitcode("rrc","a");         
8300                 aopPut(AOP(result),"a",offset--);
8301         }
8302         reAdjustPreg(AOP(result));
8303         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8304         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8305         
8306 release:
8307 #endif
8308         
8309         freeAsmop(left,NULL,ic,TRUE);
8310         freeAsmop(result,NULL,ic,TRUE);
8311         freeAsmop(right,NULL,ic,TRUE);
8312 }
8313 #endif
8314
8315 /*-----------------------------------------------------------------*/
8316 /* loadSignToC - load the operand's sign bit into CARRY            */
8317 /*-----------------------------------------------------------------*/
8318
8319 static void loadSignToC (operand *op)
8320 {
8321         FENTRY;
8322         assert (op && AOP(op) && AOP_SIZE(op));
8323
8324         emitCLRC;
8325         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8326         emitSETC;
8327 }
8328
8329 /*-----------------------------------------------------------------*/
8330 /* genRightShift - generate code for right shifting                */
8331 /*-----------------------------------------------------------------*/
8332 static void genGenericShift (iCode *ic, int shiftRight)
8333 {
8334         operand *right, *left, *result;
8335         sym_link *retype ;
8336         int size;
8337         symbol *tlbl, *tlbl1, *inverselbl;
8338         
8339         FENTRY;
8340         /* if signed then we do it the hard way preserve the
8341         sign bit moving it inwards */
8342         retype = getSpec(operandType(IC_RESULT(ic)));
8343         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8344         
8345         /* signed & unsigned types are treated the same : i.e. the
8346         signed is NOT propagated inwards : quoting from the
8347         ANSI - standard : "for E1 >> E2, is equivalent to division
8348         by 2**E2 if unsigned or if it has a non-negative value,
8349         otherwise the result is implementation defined ", MY definition
8350         is that the sign does not get propagated */
8351         
8352         right = IC_RIGHT(ic);
8353         left  = IC_LEFT(ic);
8354         result = IC_RESULT(ic);
8355         
8356         aopOp(right,ic,FALSE);
8357         aopOp(left,ic,FALSE);
8358         aopOp(result,ic,FALSE);
8359         
8360         /* if the shift count is known then do it 
8361         as efficiently as possible */
8362         if (AOP_TYPE(right) == AOP_LIT) {
8363                 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8364                 if (lit < 0)
8365                 {
8366                         lit = -lit;
8367                         shiftRight = !shiftRight;
8368                 }
8369                 
8370                 if (shiftRight)
8371                         shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8372                 else
8373                         shiftLeft_Left2ResultLit (left, result, lit);
8374                 //genRightShiftLiteral (left,right,result,ic, 0);
8375                 return ;
8376         }
8377         
8378         /* shift count is unknown then we have to form 
8379         a loop get the loop count in B : Note: we take
8380         only the lower order byte since shifting
8381         more that 32 bits make no sense anyway, ( the
8382         largest size of an object can be only 32 bits ) */  
8383
8384         /* we must not overwrite the shift counter */
8385         assert (!pic14_sameRegs(AOP(right),AOP(result)));
8386         
8387         /* now move the left to the result if they are not the
8388         same */
8389         if (!pic14_sameRegs(AOP(left),AOP(result)))
8390         {
8391                 size = min(AOP_SIZE(result), AOP_SIZE(left));
8392                 while (size--) {
8393                         mov2w(AOP(left), size);
8394                         movwf(AOP(result), size);
8395                 }
8396                 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8397         }
8398         
8399         tlbl = newiTempLabel(NULL);
8400         tlbl1= newiTempLabel(NULL);
8401         inverselbl = NULL;
8402         size = AOP_SIZE(result);
8403
8404         mov2w(AOP(right),0);
8405         if (!SPEC_USIGN(operandType(right)))
8406         {
8407                 inverselbl = newiTempLabel(NULL);
8408                 /* signed shift count -- invert shift direction for c<0 */
8409                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8410                 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8411         } // if
8412         emitpcode(POC_SUBLW, popGetLit(0));     /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8413         /* check for `a = b >> c' with `-c == 0' */
8414         emitSKPNZ;
8415         emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8416         emitpLabel(tlbl->key);
8417         /* propagate the sign bit inwards for SIGNED result */
8418         if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8419         genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8420         emitpcode(POC_ADDLW,  popGetLit(1));    /* clears CARRY (unless W==0 afterwards) */
8421         emitSKPC;
8422         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8423
8424         if (!SPEC_USIGN(operandType(right)))
8425         {
8426                 symbol *inv_loop = newiTempLabel(NULL);
8427
8428                 shiftRight = !shiftRight;       /* invert shift direction */
8429                 
8430                 /* we came here from the code above -- we are done */
8431                 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8432                 
8433                 /* emit code for shifting N<0 steps, count is already in W */
8434                 emitpLabel(inverselbl->key);
8435                 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8436                 emitpLabel(inv_loop->key);
8437                 /* propagate the sign bit inwards for SIGNED result */
8438                 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8439                 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8440                 emitpcode(POC_ADDLW, popGetLit(1));
8441                 emitSKPC;
8442                 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8443         } // if
8444         
8445         emitpLabel(tlbl1->key);
8446         
8447         freeAsmop(left,NULL,ic,TRUE);
8448         freeAsmop (right,NULL,ic,TRUE);
8449         freeAsmop(result,NULL,ic,TRUE);
8450 }
8451
8452 static void genRightShift (iCode *ic)
8453 {
8454         genGenericShift(ic, 1);
8455 }
8456
8457 static void genLeftShift (iCode *ic)
8458 {
8459         genGenericShift(ic, 0);
8460 }
8461
8462 /*-----------------------------------------------------------------*/
8463 /* SetIrp - Set IRP bit                                            */
8464 /*-----------------------------------------------------------------*/
8465 void SetIrp(operand *result) {
8466         FENTRY;
8467         if (AOP_TYPE(result) == AOP_LIT) {
8468                 unsigned lit = (unsigned)operandLitValue(result);
8469                 if (lit&0x100)
8470                         emitSETIRP;
8471                 else
8472                         emitCLRIRP;
8473         } else {
8474                 if (PCOP(AOP(result))->type == PO_LITERAL) {
8475                         int addrs = PCOL(AOP(result))->lit;
8476                         if (addrs & 0x100)
8477                                 emitSETIRP;
8478                         else
8479                                 emitCLRIRP;
8480                 } else {
8481                         emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8482                         if(AOP_SIZE(result) > 1) {
8483                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8484                                 emitSETIRP;
8485                         }
8486                 }
8487         }
8488 }
8489
8490 static void
8491 setup_fsr (operand *ptr)
8492 {
8493   mov2w_op(ptr, 0);
8494   emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8495
8496   /* also setup-up IRP */
8497   SetIrp (ptr);
8498 }
8499
8500 /*-----------------------------------------------------------------*/
8501 /* emitPtrByteGet - emits code to get a byte into WREG from an     */
8502 /*                  arbitrary pointer (__code, __data, generic)    */
8503 /*-----------------------------------------------------------------*/
8504 static void
8505 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8506 {
8507     FENTRY;
8508     switch (p_type)
8509     {
8510     case POINTER:
8511     case FPOINTER:
8512       if (!alreadyAddressed) setup_fsr (src);
8513       emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8514       break;
8515     
8516     case CPOINTER:
8517       assert( AOP_SIZE(src) == 2 );
8518       mov2w_op(src, 0);
8519       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8520       mov2w_op(src, 1);
8521       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8522       emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE));   /* GPOINTER tag for __code space */
8523       call_libraryfunc ("__gptrget1");
8524       break;
8525     
8526     case GPOINTER:
8527       assert( AOP_SIZE(src) == 3 );
8528       mov2w_op(src, 0);
8529       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8530       mov2w_op(src, 1);
8531       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8532       mov2w_op(src, 2);
8533       call_libraryfunc ("__gptrget1");
8534       break;
8535     
8536     default:
8537       assert( !"unhandled pointer type" );
8538       break;
8539     }
8540 }
8541
8542 /*-----------------------------------------------------------------*/
8543 /* emitPtrByteSet - emits code to set a byte from src through a    */
8544 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR).       */
8545 /*-----------------------------------------------------------------*/
8546 static void
8547 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8548 {
8549     FENTRY;
8550     switch (p_type)
8551     {
8552     case POINTER:
8553     case FPOINTER:
8554       if (!alreadyAddressed) setup_fsr (dst);
8555       emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8556       break;
8557     
8558     case CPOINTER:
8559       assert( !"trying to assign to __code pointer" );
8560       break;
8561     
8562     case GPOINTER:
8563       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8564       mov2w_op(dst, 0);
8565       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8566       mov2w_op(dst, 1);
8567       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8568       mov2w_op(dst, 2);
8569       call_libraryfunc ("__gptrput1");
8570       break;
8571
8572     default:
8573       assert( !"unhandled pointer type" );
8574       break;
8575     }
8576 }
8577
8578 /*-----------------------------------------------------------------*/
8579 /* genUnpackBits - generates code for unpacking bits               */
8580 /*-----------------------------------------------------------------*/
8581 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8582 {    
8583   int rsize;            /* result size */
8584   sym_link *etype;      /* bitfield type information */
8585   int blen;             /* bitfield length */
8586   int bstr;             /* bitfield starting bit within byte */
8587
8588   FENTRY;
8589   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8590   etype = getSpec(operandType(result));
8591   rsize = getSize (operandType (result));
8592   blen = SPEC_BLEN (etype);
8593   bstr = SPEC_BSTR (etype);
8594
8595   /* single bit field case */
8596   if (blen == 1) {
8597     if (ifx) { /* that is for an if statement */
8598       pCodeOp *pcop;
8599       resolvedIfx rIfx;
8600       resolveIfx(&rIfx,ifx);
8601       if (ptype == -1) /* direct */
8602         pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8603       else
8604         pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8605       emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8606       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8607       ifx->generated=1;
8608     } else {
8609       int i;
8610       assert (!pic14_sameRegs (AOP(result), AOP(left)));
8611       for (i=0; i < AOP_SIZE(result); i++)
8612         emitpcode (POC_CLRF, popGet (AOP(result), i));
8613
8614       switch (ptype)
8615       {
8616       case -1:
8617         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8618         /* adjust result below */
8619         break;
8620         
8621       case POINTER:
8622       case FPOINTER:
8623       case GPOINTER:
8624       case CPOINTER:
8625         emitPtrByteGet (left, ptype, FALSE);
8626         emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8627         emitSKPZ;
8628         /* adjust result below */
8629         break;
8630         
8631       default:
8632         assert( !"unhandled pointer type" );
8633       } // switch
8634
8635       /* move sign-/zero extended bit to result */
8636       if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8637         emitpcode (POC_INCF, popGet (AOP(result), 0));
8638       } else {
8639         emitpcode (POC_DECF, popGet (AOP(result), 0));
8640       }
8641       addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8642     }
8643     return;
8644   }
8645   else if (blen <= 8 && ((blen + bstr) <= 8))
8646   {
8647     /* blen > 1 */
8648     int i;
8649
8650     for (i=0; i < AOP_SIZE(result); i++)
8651       emitpcode (POC_CLRF, popGet (AOP(result), i));
8652
8653     switch (ptype)
8654     {
8655     case -1:
8656       mov2w(AOP(left), 0);
8657       break;
8658       
8659     case POINTER:
8660     case FPOINTER:
8661     case GPOINTER:
8662     case CPOINTER:
8663       emitPtrByteGet (left, ptype, FALSE);
8664       break;
8665       
8666     default:
8667       assert( !"unhandled pointer type" );
8668     } // switch
8669
8670     if (blen < 8)
8671       emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8672     movwf(AOP(result), 0);
8673     AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8674
8675     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8676     {
8677       /* signed bitfield */
8678       assert (bstr + blen > 0);
8679       emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8680       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8681       emitpcode(POC_IORWF, popGet(AOP(result),0));
8682     }
8683     addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8684     return;
8685   }
8686
8687   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8688 }
8689
8690 #if 1
8691 /*-----------------------------------------------------------------*/
8692 /* genDataPointerGet - generates code when ptr offset is known     */
8693 /*-----------------------------------------------------------------*/
8694 static void genDataPointerGet (operand *left, 
8695         operand *result, 
8696         iCode *ic)
8697 {
8698         int size , offset = 0;
8699                 
8700         FENTRY;
8701         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8702         
8703         
8704         /* optimization - most of the time, left and result are the same
8705         * address, but different types. for the pic code, we could omit
8706         * the following
8707         */
8708         aopOp(result,ic,TRUE);
8709         
8710         if (pic14_sameRegs (AOP(left), AOP(result)))
8711                 return;
8712         
8713         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8714         
8715         //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8716         
8717         size = AOP_SIZE(result);
8718         if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8719         
8720         offset = 0;
8721         while (size--) {
8722                 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8723                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8724                 offset++;
8725         }
8726         
8727         freeAsmop(left,NULL,ic,TRUE);
8728         freeAsmop(result,NULL,ic,TRUE);
8729 }
8730 #endif
8731
8732 /*-----------------------------------------------------------------*/
8733 /* genNearPointerGet - pic14_emitcode for near pointer fetch       */
8734 /*-----------------------------------------------------------------*/
8735 static void genNearPointerGet (operand *left, 
8736                                                            operand *result, 
8737                                                            iCode *ic)
8738 {
8739         asmop *aop = NULL;
8740         sym_link *ltype = operandType(left);
8741         sym_link *rtype = operandType(result);
8742         sym_link *retype= getSpec(rtype);      /* bitfield type information */
8743         int direct = 0;
8744
8745         FENTRY;
8746         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8747         
8748         
8749         aopOp(left,ic,FALSE);
8750         
8751         /* if left is rematerialisable and
8752         result is not bit variable type and
8753         the left is pointer to data space i.e
8754         lower 128 bytes of space */
8755         if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8756                 !IS_BITVAR(retype)         &&
8757                 PIC_IS_DATA_PTR(ltype)) {
8758                 genDataPointerGet (left,result,ic);
8759                 return ;
8760         }
8761         
8762         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8763         aopOp (result,ic,FALSE);
8764         
8765         /* Check if can access directly instead of via a pointer */
8766         if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8767                 && AOP_SIZE(result) == 1)
8768         {
8769                 direct = 1;
8770         }
8771
8772         if (IS_BITFIELD(getSpec(operandType(result)))) 
8773         {
8774                 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8775                 goto release;
8776         }
8777         
8778         /* If the pointer value is not in a the FSR then need to put it in */
8779         /* Must set/reset IRP bit for use with FSR. */
8780         if (!direct)
8781           setup_fsr (left);
8782         
8783 //      sym_link *etype;
8784         /* if bitfield then unpack the bits */
8785         {
8786                 /* we have can just get the values */
8787                 int size = AOP_SIZE(result);
8788                 int offset = 0 ;  
8789                 
8790                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8791                 
8792                 while(size--) {
8793                         if (direct)
8794                                 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8795                         else
8796                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8797                         if (AOP_TYPE(result) == AOP_LIT) {
8798                                 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8799                         } else {
8800                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8801                         }
8802                         if (size && !direct)
8803                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8804                         offset++;
8805                 }
8806         }
8807         
8808         /* now some housekeeping stuff */
8809         if (aop) {
8810                 /* we had to allocate for this iCode */
8811                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8812                 freeAsmop(NULL,aop,ic,TRUE);
8813         } else { 
8814                 /* we did not allocate which means left
8815                 already in a pointer register, then
8816                 if size > 0 && this could be used again
8817                 we have to point it back to where it 
8818                 belongs */
8819                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8820                 if (AOP_SIZE(result) > 1 &&
8821                         !OP_SYMBOL(left)->remat &&
8822                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8823                         ic->depth )) {
8824                         int size = AOP_SIZE(result) - 1;
8825                         while (size--)
8826                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8827                 }
8828         }
8829         
8830 release:
8831         /* done */
8832         freeAsmop(left,NULL,ic,TRUE);
8833         freeAsmop(result,NULL,ic,TRUE);
8834
8835 }
8836
8837 #if 0
8838 /*-----------------------------------------------------------------*/
8839 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8840 /*-----------------------------------------------------------------*/
8841 static void genPagedPointerGet (operand *left, 
8842                                                                 operand *result, 
8843                                                                 iCode *ic)
8844 {
8845         asmop *aop = NULL;
8846         regs *preg = NULL ;
8847         char *rname ;
8848         sym_link *rtype, *retype;    
8849         
8850         FENTRY;
8851         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8852         
8853         rtype = operandType(result);
8854         retype= getSpec(rtype);
8855         
8856         aopOp(left,ic,FALSE);
8857         
8858         /* if the value is already in a pointer register
8859         then don't need anything more */
8860         if (!AOP_INPREG(AOP(left))) {
8861                 /* otherwise get a free pointer register */
8862                 aop = newAsmop(0);
8863                 preg = getFreePtr(ic,&aop,FALSE);
8864                 pic14_emitcode("mov","%s,%s",
8865                         preg->name,
8866                         aopGet(AOP(left),0,FALSE,TRUE));
8867                 rname = preg->name ;
8868         } else
8869                 rname = aopGet(AOP(left),0,FALSE,FALSE);
8870         
8871         freeAsmop(left,NULL,ic,TRUE);
8872         aopOp (result,ic,FALSE);
8873         
8874         /* if bitfield then unpack the bits */
8875         if (IS_BITFIELD(retype)) 
8876                 genUnpackBits (result,left,rname,PPOINTER,0);
8877         else {
8878                 /* we have can just get the values */
8879                 int size = AOP_SIZE(result);
8880                 int offset = 0 ;  
8881                 
8882                 while (size--) {
8883                         
8884                         pic14_emitcode("movx","a,@%s",rname);
8885                         aopPut(AOP(result),"a",offset);
8886                         
8887                         offset++ ;
8888                         
8889                         if (size)
8890                                 pic14_emitcode("inc","%s",rname);
8891                 }
8892         }
8893         
8894         /* now some housekeeping stuff */
8895         if (aop) {
8896                 /* we had to allocate for this iCode */
8897                 freeAsmop(NULL,aop,ic,TRUE);
8898         } else { 
8899         /* we did not allocate which means left
8900         already in a pointer register, then
8901         if size > 0 && this could be used again
8902         we have to point it back to where it 
8903                 belongs */
8904                 if (AOP_SIZE(result) > 1 &&
8905                         !OP_SYMBOL(left)->remat &&
8906                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8907                         ic->depth )) {
8908                         int size = AOP_SIZE(result) - 1;
8909                         while (size--)
8910                                 pic14_emitcode("dec","%s",rname);
8911                 }
8912         }
8913         
8914         /* done */
8915         freeAsmop(result,NULL,ic,TRUE);
8916         
8917         
8918 }
8919
8920 /*-----------------------------------------------------------------*/
8921 /* genFarPointerGet - gget value from far space                    */
8922 /*-----------------------------------------------------------------*/
8923 static void genFarPointerGet (operand *left,
8924                                                           operand *result, iCode *ic)
8925 {
8926         int size, offset ;
8927         sym_link *retype = getSpec(operandType(result));
8928         
8929         FENTRY;
8930         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8931         
8932         aopOp(left,ic,FALSE);
8933         
8934         /* if the operand is already in dptr 
8935         then we do nothing else we move the value to dptr */
8936         if (AOP_TYPE(left) != AOP_STR) {
8937                 /* if this is remateriazable */
8938                 if (AOP_TYPE(left) == AOP_IMMD)
8939                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8940                 else { /* we need to get it byte by byte */
8941                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8942                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8943                         if (options.model == MODEL_FLAT24)
8944                         {
8945                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8946                         }
8947                 }
8948         }
8949         /* so dptr know contains the address */
8950         freeAsmop(left,NULL,ic,TRUE);
8951         aopOp(result,ic,FALSE);
8952         
8953         /* if bit then unpack */
8954         if (IS_BITFIELD(retype)) 
8955                 genUnpackBits(result,left,"dptr",FPOINTER,0);
8956         else {
8957                 size = AOP_SIZE(result);
8958                 offset = 0 ;
8959                 
8960                 while (size--) {
8961                         pic14_emitcode("movx","a,@dptr");
8962                         aopPut(AOP(result),"a",offset++);
8963                         if (size)
8964                                 pic14_emitcode("inc","dptr");
8965                 }
8966         }
8967         
8968         freeAsmop(result,NULL,ic,TRUE);
8969 }
8970 #endif
8971
8972 #if 0
8973 /*-----------------------------------------------------------------*/
8974 /* genCodePointerGet - get value from code space                  */
8975 /*-----------------------------------------------------------------*/
8976 static void genCodePointerGet (operand *left,
8977                                                            operand *result, iCode *ic)
8978 {
8979         int size, offset ;
8980         sym_link *retype = getSpec(operandType(result));
8981         
8982         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8983         
8984         aopOp(left,ic,FALSE);
8985         
8986         /* if the operand is already in dptr 
8987         then we do nothing else we move the value to dptr */
8988         if (AOP_TYPE(left) != AOP_STR) {
8989                 /* if this is remateriazable */
8990                 if (AOP_TYPE(left) == AOP_IMMD)
8991                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8992                 else { /* we need to get it byte by byte */
8993                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8994                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8995                         if (options.model == MODEL_FLAT24)
8996                         {
8997                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8998                         }
8999                 }
9000         }
9001         /* so dptr know contains the address */
9002         freeAsmop(left,NULL,ic,TRUE);
9003         aopOp(result,ic,FALSE);
9004         
9005         /* if bit then unpack */
9006         if (IS_BITFIELD(retype)) 
9007                 genUnpackBits(result,left,"dptr",CPOINTER,0);
9008         else {
9009                 size = AOP_SIZE(result);
9010                 offset = 0 ;
9011                 
9012                 while (size--) {
9013                         pic14_emitcode("clr","a");
9014                         pic14_emitcode("movc","a,@a+dptr");
9015                         aopPut(AOP(result),"a",offset++);
9016                         if (size)
9017                                 pic14_emitcode("inc","dptr");
9018                 }
9019         }
9020         
9021         freeAsmop(result,NULL,ic,TRUE);
9022 }
9023 #endif
9024 /*-----------------------------------------------------------------*/
9025 /* genGenPointerGet - gget value from generic pointer space        */
9026 /*-----------------------------------------------------------------*/
9027 static void genGenPointerGet (operand *left,
9028                                                           operand *result, iCode *ic)
9029 {
9030         FENTRY;
9031         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9032         aopOp(left,ic,FALSE);
9033         aopOp(result,ic,FALSE);
9034         
9035         
9036         DEBUGpic14_AopType(__LINE__,left,NULL,result);
9037
9038         if (IS_BITFIELD(getSpec(operandType(result))))
9039         {
9040           genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
9041           return;
9042         }
9043
9044         {
9045           /* emit call to __gptrget */
9046           char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
9047           int size = AOP_SIZE(result);
9048           int idx = 0;
9049
9050           assert (size > 0 && size <= 4);
9051
9052           /* pass arguments */
9053           assert (AOP_SIZE(left) == 3);
9054           mov2w(AOP(left), 0);
9055           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9056           mov2w(AOP(left), 1);
9057           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9058           mov2w(AOP(left), 2);
9059           call_libraryfunc (func[size]);
9060           
9061           /* save result */
9062           movwf (AOP(result), --size);
9063           while (size--) {
9064             emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
9065             movwf (AOP(result), size);
9066           } // while
9067         }
9068         
9069         freeAsmop(left,NULL,ic,TRUE);
9070         freeAsmop(result,NULL,ic,TRUE);
9071         
9072 }
9073
9074 /*-----------------------------------------------------------------*/
9075 /* genConstPointerGet - get value from const generic pointer space */
9076 /*-----------------------------------------------------------------*/
9077 static void genConstPointerGet (operand *left,
9078                                                                 operand *result, iCode *ic)
9079 {
9080         //sym_link *retype = getSpec(operandType(result));
9081         #if 0
9082         symbol *albl, *blbl;//, *clbl;
9083         pCodeOp *pcop;
9084         #endif
9085         PIC_OPCODE poc;
9086         int i, size, lit;
9087         
9088         FENTRY;
9089         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9090         aopOp(left,ic,FALSE);
9091         aopOp(result,ic,FALSE);
9092         
9093         size = AOP_SIZE(result);
9094         
9095         DEBUGpic14_AopType(__LINE__,left,NULL,result);
9096         
9097         DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9098
9099         lit = op_isLitLike (left);
9100         poc = lit ? POC_MOVLW : POC_MOVFW;
9101
9102         if (IS_BITFIELD(getSpec(operandType(result))))
9103         {
9104                 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9105                 goto release;
9106         }
9107
9108         {
9109                 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9110                 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9111                 assert (size > 0 && size <= 4);
9112                 
9113                 mov2w_op(left, 0);
9114                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9115                 mov2w_op(left, 1);
9116                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9117                 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9118                 call_libraryfunc (func[size]);
9119
9120                 movwf(AOP(result),size-1);
9121                 for (i = 1; i < size; i++)
9122                 {
9123                         emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9124                         movwf(AOP(result),size - 1 - i);
9125                 } // for
9126         }
9127         
9128 release:
9129         freeAsmop(left,NULL,ic,TRUE);
9130         freeAsmop(result,NULL,ic,TRUE);
9131         
9132 }
9133 /*-----------------------------------------------------------------*/
9134 /* genPointerGet - generate code for pointer get                   */
9135 /*-----------------------------------------------------------------*/
9136 static void genPointerGet (iCode *ic)
9137 {
9138         operand *left, *result ;
9139         sym_link *type, *etype;
9140         int p_type = -1;
9141         
9142         FENTRY;
9143         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9144         
9145         left = IC_LEFT(ic);
9146         result = IC_RESULT(ic) ;
9147         
9148         /* depending on the type of pointer we need to
9149         move it to the correct pointer register */
9150         type = operandType(left);
9151         etype = getSpec(type);
9152         
9153         if (IS_PTR_CONST(type))
9154                 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9155         
9156         /* if left is of type of pointer then it is simple */
9157         if (IS_PTR(type) && !IS_FUNC(type->next)) 
9158                 p_type = DCL_TYPE(type);
9159         else {
9160                 /* we have to go by the storage class */
9161                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9162                 
9163                 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9164                 
9165                 if (SPEC_OCLS(etype)->codesp ) {
9166                         DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9167                         //p_type = CPOINTER ; 
9168                 }
9169                 else
9170                         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9171                                 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9172                         /*p_type = FPOINTER ;*/ 
9173                         else
9174                                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9175                                         DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9176                                 /*        p_type = PPOINTER; */
9177                                 else
9178                                         if (SPEC_OCLS(etype) == idata )
9179                                                 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9180                                         /*      p_type = IPOINTER; */
9181                                         else
9182                                                 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9183                                         /*      p_type = POINTER ; */
9184         }
9185         
9186         /* now that we have the pointer type we assign
9187         the pointer values */
9188         switch (p_type) {
9189                 
9190         case POINTER: 
9191         case FPOINTER:
9192         //case IPOINTER:
9193                 genNearPointerGet (left,result,ic);
9194                 break;
9195 /*
9196         case PPOINTER:
9197                 genPagedPointerGet(left,result,ic);
9198                 break;
9199                 
9200         case FPOINTER:
9201                 genFarPointerGet (left,result,ic);
9202                 break;
9203 */              
9204         case CPOINTER:
9205                 genConstPointerGet (left,result,ic);
9206                 break;
9207                 
9208         case GPOINTER:
9209                 genGenPointerGet (left,result,ic);
9210                 break;
9211         default:
9212                 assert ( !"unhandled pointer type" );
9213                 break;
9214         }
9215         
9216 }
9217
9218 /*-----------------------------------------------------------------*/
9219 /* genPackBits - generates code for packed bit storage             */
9220 /*-----------------------------------------------------------------*/
9221 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9222 {
9223   int blen;             /* bitfield length */
9224   int bstr;             /* bitfield starting bit within byte */
9225   int litval;           /* source literal value (if AOP_LIT) */
9226   unsigned char mask;   /* bitmask within current byte */
9227
9228   FENTRY;
9229   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9230
9231   blen = SPEC_BLEN (etype);
9232   bstr = SPEC_BSTR (etype);
9233
9234   /* If the bitfield length is less than a byte and does not cross byte boundaries */
9235   if ((blen <= 8) && ((bstr + blen) <= 8))
9236   {
9237     mask = ((unsigned char) (0xFF << (blen + bstr)) |
9238             (unsigned char) (0xFF >> (8 - bstr)));
9239
9240     if (AOP_TYPE (right) == AOP_LIT)
9241     {
9242       /* Case with a bitfield length <8 and literal source */
9243       int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9244       if (blen == 1) {
9245         pCodeOp *pcop;
9246         
9247         switch (p_type)
9248         {
9249         case -1:
9250           if (AOP(result)->type == AOP_PCODE)
9251             pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9252           else
9253             pcop = popGet(AOP(result),0);
9254           emitpcode(lit?POC_BSF:POC_BCF,pcop);
9255           break;
9256         
9257         case POINTER:
9258         case FPOINTER:
9259           setup_fsr (result);
9260           emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9261           break;
9262         
9263         case CPOINTER:
9264           assert( !"trying to assign to bitfield via pointer to __code space" );
9265           break;
9266         
9267         case GPOINTER:
9268           emitPtrByteGet(result, p_type, FALSE);
9269           if (lit) {
9270             emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9271           } else {
9272             emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9273           }
9274           emitPtrByteSet(result, p_type, TRUE);
9275           break;
9276         
9277         default:
9278           assert( !"unhandled pointer type" );
9279           break;
9280         } // switch (p_type)
9281       } else {
9282         /* blen > 1 */
9283         litval = lit << bstr;
9284         litval &= (~mask) & 0x00ff;
9285         
9286         switch (p_type)
9287         {
9288         case -1:
9289           mov2w (AOP(result), 0);
9290           if ((litval|mask) != 0x00ff)
9291             emitpcode(POC_ANDLW, popGetLit (mask));
9292           if (litval != 0x00)
9293             emitpcode(POC_IORLW, popGetLit (litval));
9294           movwf (AOP(result), 0);
9295           break;
9296         
9297         case POINTER:
9298         case FPOINTER:
9299         case GPOINTER:
9300           emitPtrByteGet(result, p_type, FALSE);
9301           if ((litval|mask) != 0x00ff)
9302             emitpcode(POC_ANDLW, popGetLit (mask));
9303           if (litval != 0x00)
9304             emitpcode(POC_IORLW, popGetLit (litval));
9305           emitPtrByteSet(result, p_type, TRUE);
9306           break;
9307         
9308         case CPOINTER:
9309           assert( !"trying to assign to bitfield via pointer to __code space" );
9310           break;
9311         
9312         default:
9313           assert( !"unhandled pointer type" );
9314           break;
9315         } // switch
9316       } // if (blen > 1)
9317     }
9318     else
9319     {
9320       /* right is no literal */
9321       if (blen==1) {
9322         switch (p_type)
9323         {
9324         case -1:
9325           /* Note more efficient code, of pre clearing bit then only setting it if required,
9326            * can only be done if it is known that the result is not a SFR */
9327           emitpcode(POC_RRFW,popGet(AOP(right),0));
9328           emitSKPC;
9329           emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9330           emitSKPNC;
9331           emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9332           break;
9333         
9334         case POINTER:
9335         case FPOINTER:
9336         case GPOINTER:
9337           emitPtrByteGet (result, p_type, FALSE);
9338           emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9339           emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9340           emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9341           emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9342           emitPtrByteSet (result, p_type, TRUE);
9343           break;
9344         
9345         case CPOINTER:
9346           assert( !"trying to assign to bitfield via pointer to __code space" );
9347           break;
9348         
9349         default:
9350           assert( !"unhandled pointer type" );
9351           break;
9352         } // switch
9353         return;
9354       } else {
9355         /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9356         pCodeOp *temp = popGetTempReg ();
9357
9358         mov2w (AOP(right), 0);
9359         if (blen < 8) {
9360           emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9361         }
9362         emitpcode(POC_MOVWF, temp);
9363         if (bstr) {
9364           AccLsh (temp, bstr);
9365         }
9366         
9367         switch (p_type)
9368         {
9369         case -1:
9370           mov2w (AOP(result), 0);
9371           emitpcode(POC_ANDLW, popGetLit (mask));
9372           emitpcode(POC_IORFW, temp);
9373           movwf (AOP(result), 0);
9374           break;
9375         
9376         case POINTER:
9377         case FPOINTER:
9378         case GPOINTER:
9379           emitPtrByteGet (result, p_type, FALSE);
9380           emitpcode(POC_ANDLW, popGetLit (mask));
9381           emitpcode(POC_IORFW, temp);
9382           emitPtrByteSet (result, p_type, TRUE);
9383           break;
9384         
9385         case CPOINTER:
9386           assert( !"trying to assign to bitfield via pointer to __code space" );
9387           break;
9388         
9389         default:
9390           assert( !"unhandled pointer type" );
9391           break;
9392         } // switch
9393
9394         popReleaseTempReg (temp);
9395       } // if (blen > 1)
9396     } // if (AOP(right)->type != AOP_LIT)
9397     return;
9398   } // if (blen <= 8 && ((blen + bstr) <= 8))
9399
9400   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9401 }
9402
9403 /*-----------------------------------------------------------------*/
9404 /* genDataPointerSet - remat pointer to data space                 */
9405 /*-----------------------------------------------------------------*/
9406 static void genDataPointerSet(operand *right,
9407         operand *result,
9408         iCode *ic)
9409 {
9410         int size, offset = 0 ;
9411         int ressize;
9412         
9413         FENTRY;
9414         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9415         aopOp(right,ic,FALSE);
9416         aopOp(result,ic,FALSE);
9417         
9418         assert (IS_SYMOP(result));
9419         assert (IS_PTR(OP_SYM_TYPE(result)));
9420         
9421         if (AOP_TYPE(right) == AOP_LIT)
9422           size = 4;
9423         else
9424           size = AOP_SIZE(right);
9425         ressize = getSize(OP_SYM_ETYPE(result));
9426         if (size > ressize) size = ressize;
9427         //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9428         
9429         //assert( !"what's going on here?" );
9430
9431         /*
9432         if ( AOP_TYPE(result) == AOP_PCODE) {
9433         fprintf(stderr,"genDataPointerSet   %s, %d\n",
9434         AOP(result)->aopu.pcop->name,
9435         PCOI(AOP(result)->aopu.pcop)->offset);
9436         }
9437         */
9438         
9439         // tsd, was l+1 - the underline `_' prefix was being stripped
9440         while (size--) {
9441                 emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
9442                 
9443                 if (AOP_TYPE(right) == AOP_LIT) {
9444                         unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
9445                         //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9446                         if(lit&0xff) {
9447                                 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9448                                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9449                         } else {
9450                                 emitpcode(POC_CLRF, popGet(AOP(result), offset));
9451                         }
9452                 } else {
9453                         //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9454                         emitpcode(POC_MOVFW, popGet(AOP(right), offset));
9455                         emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9456                 }
9457                 
9458                 offset++;
9459         }
9460         
9461         freeAsmop(right,NULL,ic,TRUE);
9462         freeAsmop(result,NULL,ic,TRUE);
9463 }
9464
9465 /*-----------------------------------------------------------------*/
9466 /* genNearPointerSet - pic14_emitcode for near pointer put         */
9467 /*-----------------------------------------------------------------*/
9468 static void genNearPointerSet (operand *right,
9469                                                            operand *result, 
9470                                                            iCode *ic)
9471 {
9472         asmop *aop = NULL;
9473         sym_link *ptype = operandType(result);
9474         sym_link *retype = getSpec(operandType(right));
9475         sym_link *letype = getSpec(ptype);
9476         int direct = 0;
9477         
9478         
9479         FENTRY;
9480         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9481         aopOp(result,ic,FALSE);
9482         
9483 #if 1
9484         /* if the result is rematerializable &
9485         in data space & not a bit variable */
9486         //if (AOP_TYPE(result) == AOP_IMMD &&
9487         if (AOP_TYPE(result) == AOP_PCODE &&
9488                 PIC_IS_DATA_PTR(ptype) &&
9489                 !IS_BITVAR (retype) &&
9490                 !IS_BITVAR (letype)) {
9491                 genDataPointerSet (right,result,ic);
9492                 freeAsmop(result,NULL,ic,TRUE);
9493                 return;
9494         }
9495 #endif
9496
9497         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9498         aopOp(right,ic,FALSE);
9499         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9500         
9501         /* Check if can access directly instead of via a pointer */
9502         if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9503                 direct = 1;
9504         }
9505         
9506         if (IS_BITFIELD (letype))
9507         {
9508           genPackBits (letype, result, right, direct?-1:POINTER);
9509           return;
9510         }
9511         
9512         /* If the pointer value is not in a the FSR then need to put it in */
9513         /* Must set/reset IRP bit for use with FSR. */
9514         /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9515         if (!direct)
9516                 setup_fsr (result);
9517
9518         {
9519                 /* we have can just get the values */
9520                 int size = AOP_SIZE(right);
9521                 int offset = 0 ;    
9522                 
9523                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9524                 while (size--) {
9525                         char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9526                         if (*l == '@' ) {
9527                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9528                         } else {
9529                                 if (AOP_TYPE(right) == AOP_LIT) {
9530                                         emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9531                                 } else {
9532                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9533                                 }
9534                                 if (direct)
9535                                         emitpcode(POC_MOVWF,popGet(AOP(result),0));
9536                                 else
9537                                         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9538                         }
9539                         if (size && !direct)
9540                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9541                         offset++;
9542                 }
9543         }
9544         
9545         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9546         /* now some housekeeping stuff */
9547         if (aop) {
9548                 /* we had to allocate for this iCode */
9549                 freeAsmop(NULL,aop,ic,TRUE);
9550         } else { 
9551                 /* we did not allocate which means left
9552                 already in a pointer register, then
9553                 if size > 0 && this could be used again
9554                 we have to point it back to where it 
9555                 belongs */
9556                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9557                 if (AOP_SIZE(right) > 1 &&
9558                         !OP_SYMBOL(result)->remat &&
9559                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9560                         ic->depth )) {
9561                         int size = AOP_SIZE(right) - 1;
9562                         while (size--)
9563                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9564                 }
9565         }
9566         
9567         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9568         /* done */
9569
9570         freeAsmop(right,NULL,ic,TRUE);
9571         freeAsmop(result,NULL,ic,TRUE);
9572 }
9573
9574 #if 0
9575 /*-----------------------------------------------------------------*/
9576 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
9577 /*-----------------------------------------------------------------*/
9578 static void genPagedPointerSet (operand *right,
9579                                                                 operand *result, 
9580                                                                 iCode *ic)
9581 {
9582         asmop *aop = NULL;
9583         regs *preg = NULL ;
9584         char *rname , *l;
9585         sym_link *retype;
9586         
9587         FENTRY;
9588         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9589         
9590         retype= getSpec(operandType(right));
9591         
9592         aopOp(result,ic,FALSE);
9593         
9594         /* if the value is already in a pointer register
9595         then don't need anything more */
9596         if (!AOP_INPREG(AOP(result))) {
9597                 /* otherwise get a free pointer register */
9598                 aop = newAsmop(0);
9599                 preg = getFreePtr(ic,&aop,FALSE);
9600                 pic14_emitcode("mov","%s,%s",
9601                         preg->name,
9602                         aopGet(AOP(result),0,FALSE,TRUE));
9603                 rname = preg->name ;
9604         } else
9605                 rname = aopGet(AOP(result),0,FALSE,FALSE);
9606         
9607         freeAsmop(result,NULL,ic,TRUE);
9608         aopOp (right,ic,FALSE);
9609         
9610         /* if bitfield then unpack the bits */
9611         if (IS_BITFIELD(retype)) 
9612                 genPackBits (retype,result,right,rname,PPOINTER);
9613         else {
9614                 /* we have can just get the values */
9615                 int size = AOP_SIZE(right);
9616                 int offset = 0 ;  
9617                 
9618                 while (size--) {
9619                         l = aopGet(AOP(right),offset,FALSE,TRUE);
9620                         
9621                         MOVA(l);
9622                         pic14_emitcode("movx","@%s,a",rname);
9623                         
9624                         if (size)
9625                                 pic14_emitcode("inc","%s",rname);
9626                         
9627                         offset++;
9628                 }
9629         }
9630         
9631         /* now some housekeeping stuff */
9632         if (aop) {
9633                 /* we had to allocate for this iCode */
9634                 freeAsmop(NULL,aop,ic,TRUE);
9635         } else { 
9636         /* we did not allocate which means left
9637         already in a pointer register, then
9638         if size > 0 && this could be used again
9639         we have to point it back to where it 
9640                 belongs */
9641                 if (AOP_SIZE(right) > 1 &&
9642                         !OP_SYMBOL(result)->remat &&
9643                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9644                         ic->depth )) {
9645                         int size = AOP_SIZE(right) - 1;
9646                         while (size--)
9647                                 pic14_emitcode("dec","%s",rname);
9648                 }
9649         }
9650         
9651         /* done */
9652         freeAsmop(right,NULL,ic,TRUE);
9653         
9654         
9655 }
9656
9657 /*-----------------------------------------------------------------*/
9658 /* genFarPointerSet - set value from far space                     */
9659 /*-----------------------------------------------------------------*/
9660 static void genFarPointerSet (operand *right,
9661                                                           operand *result, iCode *ic)
9662 {
9663         int size, offset ;
9664         sym_link *retype = getSpec(operandType(right));
9665         
9666         FENTRY;
9667         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9668         aopOp(result,ic,FALSE);
9669         
9670         /* if the operand is already in dptr 
9671         then we do nothing else we move the value to dptr */
9672         if (AOP_TYPE(result) != AOP_STR) {
9673                 /* if this is remateriazable */
9674                 if (AOP_TYPE(result) == AOP_IMMD)
9675                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9676                 else { /* we need to get it byte by byte */
9677                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9678                         pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9679                         if (options.model == MODEL_FLAT24)
9680                         {
9681                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9682                         }
9683                 }
9684         }
9685         /* so dptr know contains the address */
9686         freeAsmop(result,NULL,ic,TRUE);
9687         aopOp(right,ic,FALSE);
9688         
9689         /* if bit then unpack */
9690         if (IS_BITFIELD(retype)) 
9691                 genPackBits(retype,result,right,"dptr",FPOINTER);
9692         else {
9693                 size = AOP_SIZE(right);
9694                 offset = 0 ;
9695                 
9696                 while (size--) {
9697                         char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9698                         MOVA(l);
9699                         pic14_emitcode("movx","@dptr,a");
9700                         if (size)
9701                                 pic14_emitcode("inc","dptr");
9702                 }
9703         }
9704         
9705         freeAsmop(right,NULL,ic,TRUE);
9706 }
9707 #endif
9708
9709 /*-----------------------------------------------------------------*/
9710 /* genGenPointerSet - set value from generic pointer space         */
9711 /*-----------------------------------------------------------------*/
9712 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9713 {
9714         sym_link *retype = getSpec(operandType(result));
9715         
9716         FENTRY;
9717         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9718         aopOp(right,ic,FALSE);
9719         aopOp(result,ic,FALSE);
9720
9721         
9722         DEBUGpic14_AopType(__LINE__,right,NULL,result);
9723
9724         if (IS_BITFIELD(retype))
9725         {
9726           genPackBits (retype, result, right, GPOINTER);
9727           return;
9728         }
9729
9730         {
9731           /* emit call to __gptrput */
9732           char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9733           int size = AOP_SIZE(right);
9734           int idx = 0;
9735
9736           assert (size == getSize(OP_SYM_ETYPE(result)));
9737           assert (size > 0 && size <= 4);
9738
9739           /* pass arguments */
9740           /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9741           {
9742             int off = size;
9743             idx = 2;
9744             while (off--)
9745             {
9746               mov2w_op (right, off);
9747               emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9748             }
9749             idx = 0;
9750           }
9751           /* - address */
9752           assert (AOP_SIZE(result) == 3);
9753           mov2w(AOP(result), 0);
9754           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9755           mov2w(AOP(result), 1);
9756           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9757           mov2w(AOP(result), 2);
9758           call_libraryfunc (func[size]);
9759         }
9760         
9761         freeAsmop(right,NULL,ic,TRUE);
9762         freeAsmop(result,NULL,ic,TRUE);
9763 }
9764
9765 /*-----------------------------------------------------------------*/
9766 /* genPointerSet - stores the value into a pointer location        */
9767 /*-----------------------------------------------------------------*/
9768 static void genPointerSet (iCode *ic)
9769 {    
9770         operand *right, *result ;
9771         sym_link *type, *etype;
9772         int p_type;
9773         
9774         FENTRY;
9775         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9776         
9777         right = IC_RIGHT(ic);
9778         result = IC_RESULT(ic) ;
9779         
9780         /* depending on the type of pointer we need to
9781         move it to the correct pointer register */
9782         type = operandType(result);
9783         etype = getSpec(type);
9784         /* if left is of type of pointer then it is simple */
9785         if (IS_PTR(type) && !IS_FUNC(type->next)) {
9786                 p_type = DCL_TYPE(type);
9787         }
9788         else {
9789                 /* we have to go by the storage class */
9790                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9791                 
9792                 /*  if (SPEC_OCLS(etype)->codesp ) { */
9793                 /*      p_type = CPOINTER ;  */
9794                 /*  } */
9795                 /*  else */
9796                 /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9797                 /*    p_type = FPOINTER ; */
9798                 /*      else */
9799                 /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9800                 /*        p_type = PPOINTER ; */
9801                 /*    else */
9802                 /*        if (SPEC_OCLS(etype) == idata ) */
9803                 /*      p_type = IPOINTER ; */
9804                 /*        else */
9805                 /*      p_type = POINTER ; */
9806         }
9807         
9808         /* now that we have the pointer type we assign
9809         the pointer values */
9810         switch (p_type) {
9811                 
9812         case POINTER:
9813         case FPOINTER:
9814         //case IPOINTER:
9815                 genNearPointerSet (right,result,ic);
9816                 break;
9817 /*
9818         case PPOINTER:
9819                 genPagedPointerSet (right,result,ic);
9820                 break;
9821                 
9822         case FPOINTER:
9823                 genFarPointerSet (right,result,ic);
9824                 break;
9825 */
9826         case GPOINTER:
9827                 genGenPointerSet (right,result,ic);
9828                 break;
9829                 
9830         default:
9831                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9832                         "genPointerSet: illegal pointer type");
9833         }
9834 }
9835
9836 /*-----------------------------------------------------------------*/
9837 /* genIfx - generate code for Ifx statement                        */
9838 /*-----------------------------------------------------------------*/
9839 static void genIfx (iCode *ic, iCode *popIc)
9840 {
9841         operand *cond = IC_COND(ic);
9842         int isbit =0;
9843         
9844         FENTRY;
9845         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9846         
9847         aopOp(cond,ic,FALSE);
9848         
9849         /* get the value into acc */
9850         if (AOP_TYPE(cond) != AOP_CRY)
9851                 pic14_toBoolean(cond);
9852         else
9853                 isbit = 1;
9854         
9855         /* if there was something to be popped then do it */
9856         if (popIc)
9857                 genIpop(popIc);
9858         
9859         if (isbit)
9860         {
9861                 /* This assumes that CARRY is set iff cond is true */
9862                 if (IC_TRUE(ic))
9863                 {
9864                         assert (!IC_FALSE(ic));
9865                         emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9866                         //emitSKPNC;
9867                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9868                 } else {
9869                         assert (IC_FALSE(ic));
9870                         emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9871                         //emitSKPC;
9872                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9873                 }
9874                 if (0)
9875                 {
9876                         static int hasWarned = 0;
9877                         if (!hasWarned)
9878                         {
9879                                 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9880                                 hasWarned = 1;
9881                         }
9882                 }
9883         }
9884         else
9885         {
9886                 /* now Z is set iff !cond */
9887                 if (IC_TRUE(ic))
9888                 {
9889                         assert (!IC_FALSE(ic));
9890                         emitSKPZ;
9891                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9892                 } else {
9893                         emitSKPNZ;
9894                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9895                 }
9896         }
9897         
9898         ic->generated = 1;
9899         
9900         /* the result is now in the accumulator */
9901         freeAsmop(cond,NULL,ic,TRUE);
9902 }
9903
9904 /*-----------------------------------------------------------------*/
9905 /* genAddrOf - generates code for address of                       */
9906 /*-----------------------------------------------------------------*/
9907 static void genAddrOf (iCode *ic)
9908 {
9909         operand *right, *result, *left;
9910         int size, offset ;
9911         
9912         FENTRY;
9913         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9914         
9915         
9916         //aopOp(IC_RESULT(ic),ic,FALSE);
9917         
9918         aopOp((left=IC_LEFT(ic)),ic,FALSE);
9919         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9920         aopOp((result=IC_RESULT(ic)),ic,TRUE);
9921         
9922         DEBUGpic14_AopType(__LINE__,left,right,result);
9923         assert (IS_SYMOP (left));
9924         
9925         /* sanity check: generic pointers to code space are not yet supported,
9926          * pionters to codespace must not be assigned addresses of __data values. */
9927  #if 0
9928         fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9929         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)));
9930         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)));
9931         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)));
9932         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)));
9933 #endif
9934
9935         if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9936           fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9937                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9938                 OP_SYMBOL(left)->name);
9939         } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9940           fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9941                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9942                 OP_SYMBOL(left)->name);
9943         }
9944         
9945         size = AOP_SIZE(IC_RESULT(ic));
9946         if (IS_GENPTR(OP_SYM_TYPE(result))) {
9947                 /* strip tag */
9948                 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9949         }
9950         offset = 0;
9951         
9952         while (size--) {
9953                 /* fixing bug #863624, reported from (errolv) */
9954                 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9955                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9956                 
9957 #if 0
9958                 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9959                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9960 #endif
9961                 offset++;
9962         }
9963
9964         if (IS_GENPTR(OP_SYM_TYPE(result)))
9965         {
9966                 /* provide correct tag */
9967                 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9968                 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9969                 movwf (AOP(result), 2);
9970         }
9971         
9972         freeAsmop(left,NULL,ic,FALSE);
9973         freeAsmop(result,NULL,ic,TRUE);
9974         
9975 }
9976
9977 #if 0
9978 /*-----------------------------------------------------------------*/
9979 /* genFarFarAssign - assignment when both are in far space         */
9980 /*-----------------------------------------------------------------*/
9981 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9982 {
9983         int size = AOP_SIZE(right);
9984         int offset = 0;
9985         char *l ;
9986         /* first push the right side on to the stack */
9987         while (size--) {
9988                 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9989                 MOVA(l);
9990                 pic14_emitcode ("push","acc");
9991         }
9992         
9993         freeAsmop(right,NULL,ic,FALSE);
9994         /* now assign DPTR to result */
9995         aopOp(result,ic,FALSE);
9996         size = AOP_SIZE(result);
9997         while (size--) {
9998                 pic14_emitcode ("pop","acc");
9999                 aopPut(AOP(result),"a",--offset);
10000         }
10001         freeAsmop(result,NULL,ic,FALSE);
10002         
10003 }
10004 #endif
10005
10006 /*-----------------------------------------------------------------*/
10007 /* genAssign - generate code for assignment                        */
10008 /*-----------------------------------------------------------------*/
10009 static void genAssign (iCode *ic)
10010 {
10011         operand *result, *right;
10012         int size, offset,know_W;
10013         unsigned long lit = 0L;
10014         
10015         result = IC_RESULT(ic);
10016         right  = IC_RIGHT(ic) ;
10017         
10018         FENTRY;
10019         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10020         
10021         /* if they are the same */
10022         if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10023                 return ;
10024         
10025         aopOp(right,ic,FALSE);
10026         aopOp(result,ic,TRUE);
10027         
10028         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10029         
10030         /* if they are the same registers */
10031         if (pic14_sameRegs(AOP(right),AOP(result)))
10032                 goto release;
10033
10034         /* special case: assign from __code */
10035         if (!IS_ITEMP(right)                            /* --> iTemps never reside in __code */
10036                 && IS_SYMOP (right)                     /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
10037                 && !IS_FUNC(OP_SYM_TYPE(right))         /* --> we would want its address instead of the first instruction */
10038                 && !IS_CODEPTR(OP_SYM_TYPE(right))      /* --> get symbols address instread */
10039                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
10040         {
10041           emitpComment ("genAssign from CODESPACE");
10042           genConstPointerGet (right, result, ic);
10043           goto release;
10044         }
10045         
10046         /* just for symmetry reasons... */
10047         if (!IS_ITEMP(result)
10048                 && IS_SYMOP (result)
10049                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
10050         {
10051           assert ( !"cannot write to CODESPACE" );
10052         }
10053
10054         /* if the result is a bit */
10055         if (AOP_TYPE(result) == AOP_CRY) {
10056                 
10057         /* if the right size is a literal then
10058                 we know what the value is */
10059                 if (AOP_TYPE(right) == AOP_LIT) {
10060                         
10061                         emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10062                                 popGet(AOP(result),0));
10063                         
10064                         if (((int) operandLitValue(right))) 
10065                                 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10066                                 AOP(result)->aopu.aop_dir,
10067                                 AOP(result)->aopu.aop_dir);
10068                         else
10069                                 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10070                                 AOP(result)->aopu.aop_dir,
10071                                 AOP(result)->aopu.aop_dir);
10072                         goto release;
10073                 }
10074                 
10075                 /* the right is also a bit variable */
10076                 if (AOP_TYPE(right) == AOP_CRY) {
10077                         emitpcode(POC_BCF,    popGet(AOP(result),0));
10078                         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10079                         emitpcode(POC_BSF,    popGet(AOP(result),0));
10080                         
10081                         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10082                                 AOP(result)->aopu.aop_dir,
10083                                 AOP(result)->aopu.aop_dir);
10084                         pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10085                                 AOP(right)->aopu.aop_dir,
10086                                 AOP(right)->aopu.aop_dir);
10087                         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10088                                 AOP(result)->aopu.aop_dir,
10089                                 AOP(result)->aopu.aop_dir);
10090                         goto release ;
10091                 }
10092                 
10093                 /* we need to or */
10094                 emitpcode(POC_BCF,    popGet(AOP(result),0));
10095                 pic14_toBoolean(right);
10096                 emitSKPZ;
10097                 emitpcode(POC_BSF,    popGet(AOP(result),0));
10098                 //aopPut(AOP(result),"a",0);
10099                 goto release ;
10100         }
10101         
10102         /* bit variables done */
10103         /* general case */
10104         size = AOP_SIZE(result);
10105         offset = 0 ;
10106         if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10107                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10108                 if(aopIdx(AOP(result),0) == 4) {
10109                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10110                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10111                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10112                         goto release;
10113                 } else
10114                         DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10115         }
10116         
10117         know_W=-1;
10118         while (size--) {
10119         
10120                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10121                 if(AOP_TYPE(right) == AOP_LIT) {
10122                         lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
10123                         if(lit&0xff) {
10124                                 if(know_W != (int)(lit&0xff))
10125                                         emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10126                                 know_W = lit&0xff;
10127                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10128                         } else
10129                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10130                         
10131                 } else if (AOP_TYPE(right) == AOP_CRY) {
10132                         emitpcode(POC_CLRF, popGet(AOP(result),offset));
10133                         if(offset == 0) {
10134                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10135                                 emitpcode(POC_INCF, popGet(AOP(result),0));
10136                         }
10137                 } else {
10138                         mov2w_op (right, offset);
10139                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10140                 }
10141                 
10142                 offset++;
10143         }
10144         
10145         
10146 release:
10147         freeAsmop (right,NULL,ic,FALSE);
10148         freeAsmop (result,NULL,ic,TRUE);
10149 }   
10150
10151 /*-----------------------------------------------------------------*/
10152 /* genJumpTab - genrates code for jump table                       */
10153 /*-----------------------------------------------------------------*/
10154 static void genJumpTab (iCode *ic)
10155 {
10156         symbol *jtab;
10157         char *l;
10158         
10159         FENTRY;
10160         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10161         
10162         aopOp(IC_JTCOND(ic),ic,FALSE);
10163         /* get the condition into accumulator */
10164         l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10165         MOVA(l);
10166         /* multiply by three */
10167         pic14_emitcode("add","a,acc");
10168         pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10169         
10170         jtab = newiTempLabel(NULL);
10171         pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10172         pic14_emitcode("jmp","@a+dptr");
10173         pic14_emitcode("","%05d_DS_:",jtab->key+100);
10174         
10175         emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10176         emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10177         emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10178         emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10179         emitSKPNC;
10180         emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10181         emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10182         emitpLabel(jtab->key);
10183         
10184         freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10185         
10186         /* now generate the jump labels */
10187         for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10188         jtab = setNextItem(IC_JTLABELS(ic))) {
10189                 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10190                 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10191                 
10192         }
10193         
10194 }
10195
10196 /*-----------------------------------------------------------------*/
10197 /* genMixedOperation - gen code for operators between mixed types  */
10198 /*-----------------------------------------------------------------*/
10199 /*
10200 TSD - Written for the PIC port - but this unfortunately is buggy.
10201 This routine is good in that it is able to efficiently promote 
10202 types to different (larger) sizes. Unfortunately, the temporary
10203 variables that are optimized out by this routine are sometimes
10204 used in other places. So until I know how to really parse the 
10205 iCode tree, I'm going to not be using this routine :(.
10206 */
10207 static int genMixedOperation (iCode *ic)
10208 {
10209         FENTRY;
10210 #if 0
10211         operand *result = IC_RESULT(ic);
10212         sym_link *ctype = operandType(IC_LEFT(ic));
10213         operand *right = IC_RIGHT(ic);
10214         int ret = 0;
10215         int big,small;
10216         int offset;
10217         
10218         iCode *nextic;
10219         operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10220         
10221         pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10222         
10223         nextic = ic->next;
10224         if(!nextic)
10225                 return 0;
10226         
10227         nextright = IC_RIGHT(nextic);
10228         nextleft  = IC_LEFT(nextic);
10229         nextresult = IC_RESULT(nextic);
10230         
10231         aopOp(right,ic,FALSE);
10232         aopOp(result,ic,FALSE);
10233         aopOp(nextright,  nextic, FALSE);
10234         aopOp(nextleft,   nextic, FALSE);
10235         aopOp(nextresult, nextic, FALSE);
10236         
10237         if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10238                 
10239                 operand *t = right;
10240                 right = nextright;
10241                 nextright = t; 
10242                 
10243                 pic14_emitcode(";remove right +","");
10244                 
10245         } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10246         /*
10247         operand *t = right;
10248         right = nextleft;
10249         nextleft = t; 
10250                 */
10251                 pic14_emitcode(";remove left +","");
10252         } else
10253                 return 0;
10254         
10255         big = AOP_SIZE(nextleft);
10256         small = AOP_SIZE(nextright);
10257         
10258         switch(nextic->op) {
10259                 
10260         case '+':
10261                 pic14_emitcode(";optimize a +","");
10262                 /* if unsigned or not an integral type */
10263                 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10264                         pic14_emitcode(";add a bit to something","");
10265                 } else {
10266                         
10267                         pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10268                         
10269                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10270                                 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10271                                 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10272                         } else
10273                                 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10274                         
10275                         offset = 0;
10276                         while(--big) {
10277                                 
10278                                 offset++;
10279                                 
10280                                 if(--small) {
10281                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10282                                                 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10283                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10284                                         }
10285                                         
10286                                         pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10287                                         emitSKPNC;
10288                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10289                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10290                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10291                                         pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10292                                         pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10293                                         
10294                                 } else {
10295                                         pic14_emitcode("rlf","known_zero,w");
10296                                         
10297                                         /*
10298                                         if right is signed
10299                                         btfsc  right,7
10300                                         addlw ff
10301                                         */
10302                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10303                                                 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10304                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10305                                         } else {
10306                                                 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10307                                         }
10308                                 }
10309                         }
10310                         ret = 1;
10311                 }
10312         }
10313         ret = 1;
10314         
10315 release:
10316         freeAsmop(right,NULL,ic,TRUE);
10317         freeAsmop(result,NULL,ic,TRUE);
10318         freeAsmop(nextright,NULL,ic,TRUE);
10319         freeAsmop(nextleft,NULL,ic,TRUE);
10320         if(ret)
10321                 nextic->generated = 1;
10322         
10323         return ret;
10324 #else
10325         return 0;
10326 #endif
10327 }
10328 /*-----------------------------------------------------------------*/
10329 /* genCast - gen code for casting                                  */
10330 /*-----------------------------------------------------------------*/
10331 static void genCast (iCode *ic)
10332 {
10333         operand *result = IC_RESULT(ic);
10334         sym_link *restype = operandType(result);
10335         sym_link *rtype = operandType(IC_RIGHT(ic));
10336         operand *right = IC_RIGHT(ic);
10337         int size, offset ;
10338         
10339         FENTRY;
10340         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10341         /* if they are equivalent then do nothing */
10342         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10343                 return ;
10344         
10345         aopOp(right,ic,FALSE) ;
10346         aopOp(result,ic,FALSE);
10347         
10348         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10349         
10350         /* if the result is a bit */
10351         if (AOP_TYPE(result) == AOP_CRY) {
10352                 assert(!"assigning to bit variables is not supported");
10353         }
10354         
10355         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10356                 int offset = 1;
10357                 size = AOP_SIZE(result);
10358                 
10359                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10360                 
10361                 emitpcode(POC_CLRF,   popGet(AOP(result),0));
10362                 emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10363                 emitpcode(POC_INCF,   popGet(AOP(result),0));
10364                 
10365                 while (size--)
10366                         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
10367                 
10368                 goto release;
10369         }
10370         
10371         if (IS_PTR(restype))
10372         {
10373           operand *result = IC_RESULT(ic);
10374           //operand *left = IC_LEFT(ic);
10375           operand *right = IC_RIGHT(ic);
10376           int tag = 0xff;
10377           
10378           /* copy common part */
10379           int max, size = AOP_SIZE(result);
10380           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10381           DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10382
10383           /* warn if we discard generic opinter tag */
10384           if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10385           {
10386             //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10387           } // if
10388
10389           max = size;
10390           while (size--)
10391           {
10392             mov2w_op (right, size);
10393             movwf (AOP(result), size);
10394           } // while
10395
10396           /* upcast into generic pointer type? */
10397           if (IS_GENPTR(restype)
10398                 && (size < AOP_SIZE(result))
10399                 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10400           {
10401             //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10402             if (IS_PTR(rtype))
10403             {
10404               switch (DCL_TYPE(rtype))
10405               {
10406               case POINTER:     /* __data */
10407               case FPOINTER:    /* __data */
10408                 assert (AOP_SIZE(right) == 2);
10409                 tag = GPTRTAG_DATA;
10410                 break;
10411
10412               case CPOINTER:    /* __code */
10413                 assert (AOP_SIZE(right) == 2);
10414                 tag = GPTRTAG_CODE;
10415                 break;
10416                 
10417               case GPOINTER:    /* unknown destination, __data or __code */
10418                 /* assume __data space (address of immediate) */
10419                 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10420                 if (AOP(right)->code)
10421                   tag = GPTRTAG_CODE;
10422                 else
10423                   tag = GPTRTAG_DATA;
10424                 break;
10425                 
10426               default:
10427                 assert (!"unhandled pointer type");
10428               } // switch
10429             } else {
10430               /* convert other values into pointers to __data space */
10431               tag = GPTRTAG_DATA;
10432             }
10433
10434             assert (AOP_SIZE(result) == 3);
10435             if (tag == 0) {
10436               emitpcode(POC_CLRF, popGet(AOP(result), 2));
10437             } else {
10438               emitpcode(POC_MOVLW, popGetLit(tag));
10439               movwf(AOP(result), 2);
10440             }
10441           } else {
10442             addSign(result, max, 0);
10443           } // if
10444           goto release;
10445         }
10446         
10447         /* if they are the same size : or less */
10448         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10449                 
10450                 /* if they are in the same place */
10451                 if (pic14_sameRegs(AOP(right),AOP(result)))
10452                         goto release;
10453                 
10454                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10455                 if (IS_PTR_CONST(rtype))
10456                         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10457                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10458                         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10459                 
10460                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10461                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10462                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
10463                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10464                         emitpcode(POC_MOVWF, popGet(AOP(result),1));
10465                         if(AOP_SIZE(result) <2)
10466                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10467                         
10468                 } else {
10469                         
10470                         /* if they in different places then copy */
10471                         size = AOP_SIZE(result);
10472                         offset = 0 ;
10473                         while (size--) {
10474                                 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10475                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10476                                 
10477                                 //aopPut(AOP(result),
10478                                 // aopGet(AOP(right),offset,FALSE,FALSE),
10479                                 // offset);
10480                                 
10481                                 offset++;
10482                         }
10483                 }
10484                 goto release;
10485         }
10486         
10487         /* so we now know that the size of destination is greater
10488         than the size of the source.
10489         Now, if the next iCode is an operator then we might be
10490         able to optimize the operation without performing a cast.
10491         */
10492         if(0 && genMixedOperation(ic)) {
10493                 /* XXX: cannot optimize: must copy regs! */
10494                 goto release;
10495         }
10496         
10497         /* we move to result for the size of source */
10498         size = AOP_SIZE(right);
10499         offset = 0 ;
10500         while (size--) {
10501                 emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
10502                 emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
10503                 offset++;
10504         }
10505
10506         addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10507
10508 release:
10509         freeAsmop(right,NULL,ic,TRUE);
10510         freeAsmop(result,NULL,ic,TRUE);
10511         
10512 }
10513
10514 /*-----------------------------------------------------------------*/
10515 /* genDjnz - generate decrement & jump if not zero instrucion      */
10516 /*-----------------------------------------------------------------*/
10517 static int genDjnz (iCode *ic, iCode *ifx)
10518 {
10519         symbol *lbl, *lbl1;
10520         FENTRY;
10521         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10522         
10523         if (!ifx)
10524                 return 0;
10525         
10526                 /* if the if condition has a false label
10527         then we cannot save */
10528         if (IC_FALSE(ifx))
10529                 return 0;
10530         
10531                 /* if the minus is not of the form 
10532         a = a - 1 */
10533         if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10534                 !IS_OP_LITERAL(IC_RIGHT(ic)))
10535                 return 0;
10536         
10537         if (operandLitValue(IC_RIGHT(ic)) != 1)
10538                 return 0;
10539         
10540                 /* if the size of this greater than one then no
10541         saving */
10542         if (getSize(operandType(IC_RESULT(ic))) > 1)
10543                 return 0;
10544         
10545         /* otherwise we can save BIG */
10546         lbl = newiTempLabel(NULL);
10547         lbl1= newiTempLabel(NULL);
10548         
10549         aopOp(IC_RESULT(ic),ic,FALSE);
10550         
10551         if (IS_AOP_PREG(IC_RESULT(ic))) {
10552                 pic14_emitcode("dec","%s",
10553                         aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10554                 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10555                 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10556         } else {  
10557                 
10558                 
10559                 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10560                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10561                 
10562                 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10563                 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10564                 
10565         }
10566         /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10567         /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10568         /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10569         /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10570         
10571         
10572         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10573         ifx->generated = 1;
10574         return 1;
10575 }
10576
10577 /*-----------------------------------------------------------------*/
10578 /* genReceive - generate code for a receive iCode                  */
10579 /*-----------------------------------------------------------------*/
10580 static void genReceive (iCode *ic)
10581 {
10582         FENTRY;
10583         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10584         
10585         if (isOperandInFarSpace(IC_RESULT(ic)) &&
10586                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10587                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10588                 
10589                 int size = getSize(operandType(IC_RESULT(ic)));
10590                 int offset =  fReturnSizePic - size;
10591                 while (size--) {
10592                         pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10593                                 fReturn[fReturnSizePic - offset - 1] : "acc"));
10594                         offset++;
10595                 }
10596                 aopOp(IC_RESULT(ic),ic,FALSE);
10597                 size = AOP_SIZE(IC_RESULT(ic));
10598                 offset = 0;
10599                 while (size--) {
10600                         pic14_emitcode ("pop","acc");
10601                         aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10602                 }
10603                 
10604         } else {
10605                 _G.accInUse++;
10606                 aopOp(IC_RESULT(ic),ic,FALSE);
10607                 _G.accInUse--;
10608                 GpsuedoStkPtr = ic->parmBytes; // address used arg on stack
10609                 assignResultValue(IC_RESULT(ic));
10610         }
10611         
10612         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10613 }
10614
10615 /*-----------------------------------------------------------------*/
10616 /* genDummyRead - generate code for dummy read of volatiles        */
10617 /*-----------------------------------------------------------------*/
10618 static void
10619 genDummyRead (iCode * ic)
10620 {
10621         FENTRY;
10622         pic14_emitcode ("; genDummyRead","");
10623         pic14_emitcode ("; not implemented","");
10624         
10625         ic = ic;
10626 }
10627
10628 /*-----------------------------------------------------------------*/
10629 /* genpic14Code - generate code for pic14 based controllers        */
10630 /*-----------------------------------------------------------------*/
10631 /*
10632 * At this point, ralloc.c has gone through the iCode and attempted
10633 * to optimize in a way suitable for a PIC. Now we've got to generate
10634 * PIC instructions that correspond to the iCode.
10635 *
10636 * Once the instructions are generated, we'll pass through both the
10637 * peep hole optimizer and the pCode optimizer.
10638 *-----------------------------------------------------------------*/
10639
10640 void genpic14Code (iCode *lic)
10641 {
10642         iCode *ic;
10643         int cln = 0;
10644         const char *cline;
10645         
10646         FENTRY;
10647         lineHead = lineCurr = NULL;
10648         
10649         pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10650         addpBlock(pb);
10651         
10652         /* if debug information required */
10653         if (options.debug && currFunc) { 
10654                 if (currFunc) {
10655                         debugFile->writeFunction (currFunc, lic);
10656                 }
10657         }
10658         
10659         
10660         for (ic = lic ; ic ; ic = ic->next ) {
10661                 
10662                 //DEBUGpic14_emitcode(";ic","");
10663                 //fprintf (stderr, "in ic loop\n");
10664                 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10665                 //ic->lineno, printCLine(ic->filename, ic->lineno));
10666                 
10667                 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10668                   cln = ic->lineno;
10669                   //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10670                   cline = printCLine (ic->filename, ic->lineno);
10671                   if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10672                   addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10673                   //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10674                 }
10675                 
10676                 if (options.iCodeInAsm) {
10677                   emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10678                 }
10679                 /* if the result is marked as
10680                 spilt and rematerializable or code for
10681                 this has already been generated then
10682                 do nothing */
10683                 if (resultRemat(ic) || ic->generated ) 
10684                         continue ;
10685                 
10686                 /* depending on the operation */
10687                 switch (ic->op) {
10688                 case '!' :
10689                         genNot(ic);
10690                         break;
10691                         
10692                 case '~' :
10693                         genCpl(ic);
10694                         break;
10695                         
10696                 case UNARYMINUS:
10697                         genUminus (ic);
10698                         break;
10699                         
10700                 case IPUSH:
10701                         genIpush (ic);
10702                         break;
10703                         
10704                 case IPOP:
10705                         /* IPOP happens only when trying to restore a 
10706                         spilt live range, if there is an ifx statement
10707                         following this pop then the if statement might
10708                         be using some of the registers being popped which
10709                         would destory the contents of the register so
10710                         we need to check for this condition and handle it */
10711                         if (ic->next            && 
10712                                 ic->next->op == IFX &&
10713                                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10714                                 genIfx (ic->next,ic);
10715                         else
10716                                 genIpop (ic);
10717                         break; 
10718                         
10719                 case CALL:
10720                         genCall (ic);
10721                         break;
10722                         
10723                 case PCALL:
10724                         genPcall (ic);
10725                         break;
10726                         
10727                 case FUNCTION:
10728                         genFunction (ic);
10729                         break;
10730                         
10731                 case ENDFUNCTION:
10732                         genEndFunction (ic);
10733                         break;
10734                         
10735                 case RETURN:
10736                         genRet (ic);
10737                         break;
10738                         
10739                 case LABEL:
10740                         genLabel (ic);
10741                         break;
10742                         
10743                 case GOTO:
10744                         genGoto (ic);
10745                         break;
10746                         
10747                 case '+' :
10748                         genPlus (ic) ;
10749                         break;
10750                         
10751                 case '-' :
10752                         if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10753                                 genMinus (ic);
10754                         break;
10755                         
10756                 case '*' :
10757                         genMult (ic);
10758                         break;
10759                         
10760                 case '/' :
10761                         genDiv (ic) ;
10762                         break;
10763                         
10764                 case '%' :
10765                         genMod (ic);
10766                         break;
10767                         
10768                 case '>' :
10769                         genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));         
10770                         break;
10771                         
10772                 case '<' :
10773                         genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10774                         break;
10775                         
10776                 case LE_OP:
10777                 case GE_OP:
10778                 case NE_OP:
10779                         
10780                         /* note these two are xlated by algebraic equivalence
10781                         during parsing SDCC.y */
10782                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10783                                 "got '>=' or '<=' shouldn't have come here");
10784                         break;  
10785                         
10786                 case EQ_OP:
10787                         genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10788                         break;      
10789                         
10790                 case AND_OP:
10791                         genAndOp (ic);
10792                         break;
10793                         
10794                 case OR_OP:
10795                         genOrOp (ic);
10796                         break;
10797                         
10798                 case '^' :
10799                         genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10800                         break;
10801                         
10802                 case '|' :
10803                         genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10804                         break;
10805                         
10806                 case BITWISEAND:
10807                         genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10808                         break;
10809                         
10810                 case INLINEASM:
10811                         genInline (ic);
10812                         break;
10813                         
10814                 case RRC:
10815                         genRRC (ic);
10816                         break;
10817                         
10818                 case RLC:
10819                         genRLC (ic);
10820                         break;
10821                         
10822                 case GETHBIT:
10823                         genGetHbit (ic);
10824                         break;
10825                         
10826                 case LEFT_OP:
10827                         genLeftShift (ic);
10828                         break;
10829                         
10830                 case RIGHT_OP:
10831                         genRightShift (ic);
10832                         break;
10833                         
10834                 case GET_VALUE_AT_ADDRESS:
10835                         genPointerGet(ic);
10836                         break;
10837                         
10838                 case '=' :
10839                         if (POINTER_SET(ic))
10840                                 genPointerSet(ic);
10841                         else
10842                                 genAssign(ic);
10843                         break;
10844                         
10845                 case IFX:
10846                         genIfx (ic,NULL);
10847                         break;
10848                         
10849                 case ADDRESS_OF:
10850                         genAddrOf (ic);
10851                         break;
10852                         
10853                 case JUMPTABLE:
10854                         genJumpTab (ic);
10855                         break;
10856                         
10857                 case CAST:
10858                         genCast (ic);
10859                         break;
10860                         
10861                 case RECEIVE:
10862                         genReceive(ic);
10863                         break;
10864                         
10865                 case SEND:
10866                         addSet(&_G.sendSet,ic);
10867                         break;
10868                         
10869                 case DUMMY_READ_VOLATILE:
10870                         genDummyRead (ic);
10871                         break;
10872                         
10873                 default :
10874                         fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10875                         ic = ic;
10876                         break;
10877                 }
10878         }
10879
10880         
10881         /* now we are ready to call the
10882         peep hole optimizer */
10883         if (!options.nopeep) {
10884                 peepHole (&lineHead);
10885         }
10886         /* now do the actual printing */
10887         printLine (lineHead,codeOutFile);
10888         
10889 #ifdef PCODE_DEBUG
10890         DFPRINTF((stderr,"printing pBlock\n\n"));
10891         printpBlock(stdout,pb);
10892 #endif
10893         
10894         return;
10895 }
10896
10897 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10898  * (meaning: representing its own address) or not (referencing its contents).
10899  * This can only be decided based on the operand's type. */
10900 int
10901 aop_isLitLike (asmop *aop)
10902 {
10903   assert (aop);
10904   if (aop->type == AOP_LIT) return 1;
10905 if (aop->type == AOP_IMMD) return 1;
10906   if ((aop->type == AOP_PCODE) &&
10907                 ((aop->aopu.pcop->type == PO_LITERAL)))
10908   {
10909     /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10910      * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10911     return 1;
10912   }
10913   return 0;
10914 }
10915
10916 int
10917 op_isLitLike (operand *op)
10918 {
10919   assert (op);
10920   if (aop_isLitLike (AOP(op))) return 1;
10921   if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10922   if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;
10923   return 0;
10924 }