* src/pic/device.c (register_map): fixed list construction
[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 struct dbuf_s *codeOutBuf;
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         int sign;
3458         
3459         FENTRY;
3460         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3461         
3462         assert (AOP_SIZE(right) == 1);
3463         assert (AOP_SIZE(left) == 1);
3464
3465         size = min(AOP_SIZE(result),AOP_SIZE(left));
3466         sign = !(SPEC_USIGN(operandType(left))
3467                 && SPEC_USIGN(operandType(right)));
3468
3469         if (AOP_TYPE(right) == AOP_LIT)
3470         {
3471                 /* XXX: might add specialized code */
3472         }
3473
3474         if (!sign)
3475         {
3476                 /* unsigned division */
3477         #if 1
3478                 mov2w(AOP(right),0);
3479                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3480                 mov2w(AOP(left),0);
3481                 call_libraryfunc("__divuchar");
3482                 movwf(AOP(result),0);
3483         #else
3484                 pCodeOp *temp;
3485                 symbol *lbl;
3486
3487                 temp = popGetTempReg();
3488                 lbl = newiTempLabel(NULL);
3489                 
3490                 /* XXX: improve this naive approach:
3491                    [result] = [a] / [b]
3492                         ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3493
3494                    In PIC assembler:
3495                    movf  left,W
3496                    movwf temp           // temp <-- left
3497                    movf  right,W        // W <-- right
3498                    clrf  result
3499                    label1:
3500                    incf  result
3501                    subwf temp,F         // temp <-- temp - W
3502                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if temp < W
3503                    goto  label1
3504                    decf result          // we just subtract once too often
3505                  */
3506
3507                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3508                 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3509                 
3510                 mov2w(AOP(left),0);
3511                 emitpcode(POC_MOVWF, temp);
3512                 mov2w(AOP(right),0);
3513                 emitpcode(POC_CLRF, popGet(AOP(result),0));
3514
3515                 emitpLabel(lbl->key);
3516                 emitpcode(POC_INCF, popGet(AOP(result),0));
3517                 emitpcode(POC_SUBWF, temp);
3518                 emitSKPNC;
3519                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3520                 emitpcode(POC_DECF, popGet(AOP(result),0));
3521         #endif
3522         }
3523         else
3524         {
3525                 /* signed division */
3526                 mov2w(AOP(right),0);
3527                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3528                 mov2w(AOP(left),0);
3529                 call_libraryfunc("__divschar");
3530                 movwf(AOP(result),0);
3531         }
3532
3533         /* now performed the signed/unsigned division -- extend result */
3534         addSign(result, 1, sign);
3535 }
3536
3537 /*-----------------------------------------------------------------*/
3538 /* genDiv - generates code for division                            */
3539 /*-----------------------------------------------------------------*/
3540 static void genDiv (iCode *ic)
3541 {
3542         operand *left = IC_LEFT(ic);
3543         operand *right = IC_RIGHT(ic);
3544         operand *result= IC_RESULT(ic); 
3545         
3546         FENTRY;
3547         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3548         /* assign the amsops */
3549         aopOp (left,ic,FALSE);
3550         aopOp (right,ic,FALSE);
3551         aopOp (result,ic,TRUE);
3552         
3553         /* special cases first */
3554         /* both are bits */
3555         if (AOP_TYPE(left) == AOP_CRY &&
3556                 AOP_TYPE(right)== AOP_CRY) {
3557                 genDivbits(left,right,result);
3558                 goto release ;
3559         }
3560         
3561         /* if both are of size == 1 */
3562         if (AOP_SIZE(left) == 1 &&
3563                 AOP_SIZE(right) == 1 ) {
3564                 genDivOneByte(left,right,result);
3565                 goto release ;
3566         }
3567         
3568         /* should have been converted to function call */
3569         assert(0);
3570 release :
3571         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3572         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3573         freeAsmop(result,NULL,ic,TRUE); 
3574 }
3575
3576 /*-----------------------------------------------------------------*/
3577 /* genModOneByte : 8 bit modulus                                                                   */
3578 /*-----------------------------------------------------------------*/
3579 static void genModOneByte (operand *left,
3580                                                    operand *right,
3581                                                    operand *result)
3582 {
3583         int size;
3584         int sign;
3585         
3586         FENTRY;
3587         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3588         
3589         assert (AOP_SIZE(right) == 1);
3590         assert (AOP_SIZE(left) == 1);
3591
3592         size = min(AOP_SIZE(result),AOP_SIZE(left));
3593         sign = !(SPEC_USIGN(operandType(left))
3594                 && SPEC_USIGN(operandType(right)));
3595
3596         if (AOP_TYPE(right) == AOP_LIT)
3597         {
3598                 /* XXX: might add specialized code */
3599         }
3600
3601         if (!sign)
3602         {
3603                 /* unsigned division */
3604         #if 1
3605                 mov2w(AOP(right),0);
3606                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3607                 mov2w(AOP(left),0);
3608                 call_libraryfunc("__moduchar");
3609                 movwf(AOP(result),0);
3610         #else
3611                 pCodeOp *temp;
3612                 symbol *lbl;
3613
3614                 lbl = newiTempLabel(NULL);
3615                 
3616                 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3617
3618                 /* XXX: improve this naive approach:
3619                    [result] = [a] % [b]
3620                         ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3621
3622                    In PIC assembler:
3623                    movf  left,W
3624                    movwf result         // result <-- left
3625                    movf  right,W        // W <-- right
3626                    label1:
3627                    subwf result,F       // result <-- result - W
3628                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if result < W
3629                    goto  label1
3630                    addwf result, F      // we just subtract once too often
3631                  */
3632
3633                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3634                 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3635                 
3636                 if (!pic14_sameRegs(AOP(left), AOP(result)))
3637                 {
3638                         mov2w(AOP(left),0);
3639                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
3640                 }
3641                 mov2w(AOP(right),0);
3642
3643                 emitpLabel(lbl->key);
3644                 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3645                 emitSKPNC;
3646                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3647                 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3648         #endif
3649         }
3650         else
3651         {
3652                 /* signed division */
3653                 mov2w(AOP(right),0);
3654                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3655                 mov2w(AOP(left),0);
3656                 call_libraryfunc("__modschar");
3657                 movwf(AOP(result),0);
3658         }
3659
3660         /* now we performed the signed/unsigned modulus -- extend result */
3661         addSign(result, 1, sign);
3662 }
3663
3664 /*-----------------------------------------------------------------*/
3665 /* genMod - generates code for division                                                    */
3666 /*-----------------------------------------------------------------*/
3667 static void genMod (iCode *ic)
3668 {
3669         operand *left = IC_LEFT(ic);
3670         operand *right = IC_RIGHT(ic);
3671         operand *result= IC_RESULT(ic);  
3672         
3673         FENTRY;
3674         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3675         /* assign the amsops */
3676         aopOp (left,ic,FALSE);
3677         aopOp (right,ic,FALSE);
3678         aopOp (result,ic,TRUE);
3679         
3680         /* if both are of size == 1 */
3681         if (AOP_SIZE(left) == 1 &&
3682                 AOP_SIZE(right) == 1 ) {
3683                 genModOneByte(left,right,result);
3684                 goto release ;
3685         }
3686         
3687         /* should have been converted to function call */
3688         assert(0);
3689         
3690 release :
3691         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3692         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3693         freeAsmop(result,NULL,ic,TRUE); 
3694 }
3695
3696 /*-----------------------------------------------------------------*/
3697 /* genIfxJump :- will create a jump depending on the ifx                   */
3698 /*-----------------------------------------------------------------*/
3699 /*
3700 note: May need to add parameter to indicate when a variable is in bit space.
3701 */
3702 static void genIfxJump (iCode *ic, char *jval)
3703 {
3704         
3705         FENTRY;
3706         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3707         /* if true label then we jump if condition
3708         supplied is true */
3709         if ( IC_TRUE(ic) ) {
3710                 
3711                 if(strcmp(jval,"a") == 0)
3712                         emitSKPZ;
3713                 else if (strcmp(jval,"c") == 0)
3714                         emitSKPC;
3715                 else {
3716                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3717                         emitpcode(POC_BTFSC,    newpCodeOpBit(jval,-1,1));
3718                 }
3719                 
3720                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3721                 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3722                 
3723         }
3724         else {
3725                 /* false label is present */
3726                 if(strcmp(jval,"a") == 0)
3727                         emitSKPNZ;
3728                 else if (strcmp(jval,"c") == 0)
3729                         emitSKPNC;
3730                 else {
3731                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3732                         emitpcode(POC_BTFSS,    newpCodeOpBit(jval,-1,1));
3733                 }
3734                 
3735                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3736                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3737                 
3738         }
3739         
3740         
3741         /* mark the icode as generated */
3742         ic->generated = 1;
3743 }
3744
3745 #if 0
3746 /*-----------------------------------------------------------------*/
3747 /* genSkip                                                                                                                 */
3748 /*-----------------------------------------------------------------*/
3749 static void genSkip(iCode *ifx,int status_bit)
3750 {
3751         FENTRY;
3752         if(!ifx)
3753                 return;
3754         
3755         if ( IC_TRUE(ifx) ) {
3756                 switch(status_bit) {
3757                 case 'z':
3758                         emitSKPNZ;
3759                         break;
3760                         
3761                 case 'c':
3762                         emitSKPNC;
3763                         break;
3764                         
3765                 case 'd':
3766                         emitSKPDC;
3767                         break;
3768                         
3769                 }
3770                 
3771                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3772                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3773                 
3774         } else {
3775                 
3776                 switch(status_bit) {
3777                         
3778                 case 'z':
3779                         emitSKPZ;
3780                         break;
3781                         
3782                 case 'c':
3783                         emitSKPC;
3784                         break;
3785                         
3786                 case 'd':
3787                         emitSKPDC;
3788                         break;
3789                 }
3790                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3791                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3792                 
3793         }
3794         
3795 }
3796 #endif
3797
3798 /*-----------------------------------------------------------------*/
3799 /* genSkipc                                                                                                        */
3800 /*-----------------------------------------------------------------*/
3801 static void genSkipc(resolvedIfx *rifx)
3802 {
3803         FENTRY;
3804         if(!rifx)
3805                 return;
3806         
3807         if(rifx->condition)
3808                 emitSKPNC;
3809         else
3810                 emitSKPC;
3811         
3812         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3813         emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3814         rifx->generated = 1;
3815 }
3816
3817 #if 0
3818 /*-----------------------------------------------------------------*/
3819 /* genSkipz2                                                                                                       */
3820 /*-----------------------------------------------------------------*/
3821 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3822 {
3823         FENTRY;
3824         if(!rifx)
3825                 return;
3826         
3827         if( (rifx->condition ^ invert_condition) & 1)
3828                 emitSKPZ;
3829         else
3830                 emitSKPNZ;
3831         
3832         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3833         rifx->generated = 1;
3834 }
3835 #endif
3836
3837 #if 0
3838 /*-----------------------------------------------------------------*/
3839 /* genSkipz                                                        */
3840 /*-----------------------------------------------------------------*/
3841 static void genSkipz(iCode *ifx, int condition)
3842 {
3843         FENTRY;
3844         assert (ifx != NULL);
3845         
3846         if(condition)
3847                 emitSKPNZ;
3848         else
3849                 emitSKPZ;
3850         
3851         if ( IC_TRUE(ifx) )
3852                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3853         else
3854                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3855         
3856         if ( IC_TRUE(ifx) )
3857                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3858         else
3859                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3860         
3861 }
3862 #endif
3863
3864 #if 0
3865 /*-----------------------------------------------------------------*/
3866 /* genSkipCond                                                     */
3867 /*-----------------------------------------------------------------*/
3868 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3869 {
3870         FENTRY;
3871         if(!rifx)
3872                 return;
3873         
3874         if(rifx->condition)
3875                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3876         else
3877                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3878         
3879         
3880         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3881         rifx->generated = 1;
3882 }
3883 #endif
3884
3885 #if 0
3886 /*-----------------------------------------------------------------*/
3887 /* genChkZeroes :- greater or less than comparison                 */
3888 /*     For each byte in a literal that is zero, inclusive or the   */
3889 /*     the corresponding byte in the operand with W                */
3890 /*     returns true if any of the bytes are zero                   */
3891 /*-----------------------------------------------------------------*/
3892 static int genChkZeroes(operand *op, int lit,  int size)
3893 {
3894         
3895         int i;
3896         int flag =1;
3897         
3898         while(size--) {
3899                 i = (lit >> (size*8)) & 0xff;
3900                 
3901                 if(i==0) {
3902                         if(flag) 
3903                                 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3904                         else
3905                                 emitpcode(POC_IORFW, popGet(AOP(op),size));
3906                         flag = 0;
3907                 }
3908         }
3909         
3910         return (flag==0);
3911 }
3912 #endif
3913
3914
3915 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3916 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
3917 #define DEBUGpc           emitpComment
3918
3919 /*-----------------------------------------------------------------*/
3920 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
3921 /*                  aop (if it's NOT a literal) or from lit (if    */
3922 /*                  aop is a literal)                              */
3923 /*-----------------------------------------------------------------*/
3924 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3925   if (aop->type == AOP_LIT) {
3926     emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3927   } else {
3928     emitpcode (POC_MOVFW, popGet (aop, offset));
3929   }
3930 }
3931
3932 /* genCmp performs a left < right comparison, stores
3933  * the outcome in result (if != NULL) and generates
3934  * control flow code for the ifx (if != NULL).
3935  *
3936  * This version leaves in sequences like
3937  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3938  * which should be optmized by the peephole
3939  * optimizer - RN 2005-01-01 */
3940 static void genCmp (operand *left,operand *right,
3941                     operand *result, iCode *ifx, int sign)
3942 {
3943   resolvedIfx rIfx;
3944   int size;
3945   int offs;
3946   symbol *templbl;
3947   operand *dummy;
3948   unsigned long lit;
3949   unsigned long mask;
3950   int performedLt;
3951   int invert_result = 0;
3952
3953   FENTRY;
3954   
3955   assert (AOP_SIZE(left) == AOP_SIZE(right));
3956   assert (left && right);
3957
3958   size = AOP_SIZE(right) - 1;
3959   mask = (0x100UL << (size*8)) - 1;
3960   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3961   performedLt = 1;
3962   templbl = NULL;
3963   lit = 0;
3964   
3965   resolveIfx (&rIfx, ifx);
3966
3967   /**********************************************************************
3968    * handle bits - bit compares are promoted to int compares seemingly! *
3969    **********************************************************************/
3970 #if 0
3971   // THIS IS COMPLETELY UNTESTED!
3972   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3973     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3974     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3975     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3976
3977     emitSETC;
3978     // 1 < {0,1} is false --> clear C by skipping the next instruction
3979     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3980     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3981     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3982     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3983     emitCLRC; // only skipped for left=0 && right=1
3984
3985     goto correct_result_in_carry;
3986   } // if
3987 #endif
3988
3989   /*************************************************
3990    * make sure that left is register (or the like) *
3991    *************************************************/
3992   if (!isAOP_REGlike(left)) {
3993     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3994     assert (isAOP_LIT(left));
3995     assert (isAOP_REGlike(right));
3996     // swap left and right
3997     // left < right <==> right > left <==> (right >= left + 1)
3998     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3999
4000     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4001       // MAXVALUE < right? always false
4002       if (performedLt) emitCLRC; else emitSETC;
4003       goto correct_result_in_carry;
4004     } // if
4005
4006     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4007     // that's why we handled it above.
4008     lit++;
4009
4010     dummy = left;
4011     left = right;
4012     right = dummy;
4013
4014     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4015   } else if (isAOP_LIT(right)) {
4016     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4017   } // if
4018
4019   assert (isAOP_REGlike(left)); // left must be register or the like
4020   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4021
4022   /*************************************************
4023    * special cases go here                         *
4024    *************************************************/
4025
4026   if (isAOP_LIT(right)) {
4027     if (!sign) {
4028       // unsigned comparison to a literal
4029       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4030       if (lit == 0) {
4031         // unsigned left < 0? always false
4032         if (performedLt) emitCLRC; else emitSETC;
4033         goto correct_result_in_carry;
4034       }
4035     } else {
4036       // signed comparison to a literal
4037       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4038       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4039         // signed left < 0x80000000? always false
4040         if (performedLt) emitCLRC; else emitSETC;
4041         goto correct_result_in_carry;
4042       } else if (lit == 0) {
4043         // compare left < 0; set CARRY if SIGNBIT(left) is set
4044         if (performedLt) emitSETC; else emitCLRC;
4045         emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
4046         if (performedLt) emitCLRC; else emitSETC;
4047         goto correct_result_in_carry;
4048       }
4049     } // if (!sign)
4050   } // right is literal
4051
4052   /*************************************************
4053    * perform a general case comparison             *
4054    * make sure we get CARRY==1 <==> left >= right  *
4055    *************************************************/
4056   // compare most significant bytes
4057   //DEBUGpc ("comparing bytes at offset %d", size);
4058   if (!sign) {
4059     // unsigned comparison
4060     pic14_mov2w_regOrLit (AOP(right), lit, size);
4061     emitpcode (POC_SUBFW, popGet (AOP(left), size));
4062   } else {
4063     // signed comparison
4064     // (add 2^n to both operands then perform an unsigned comparison)
4065     if (isAOP_LIT(right)) {
4066       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4067       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4068
4069       if (litbyte == 0x80) {
4070         // left >= 0x80 -- always true, but more bytes to come
4071         mov2w (AOP(left), size);
4072         emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
4073         emitSETC;
4074       } else {
4075         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4076         mov2w (AOP(left), size);
4077         emitpcode (POC_ADDLW, popGetLit (0x80));
4078         emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4079       } // if
4080     } else {
4081       pCodeOp *pctemp = popGetTempReg();
4082       mov2w (AOP(left), size);
4083       emitpcode (POC_ADDLW, popGetLit (0x80));
4084       emitpcode (POC_MOVWF, pctemp);
4085       mov2w (AOP(right), size);
4086       emitpcode (POC_ADDLW, popGetLit (0x80));
4087       emitpcode (POC_SUBFW, pctemp);
4088       popReleaseTempReg(pctemp);
4089     }
4090   } // if (!sign)
4091
4092   // compare remaining bytes (treat as unsigned case from above)
4093   templbl = newiTempLabel ( NULL );
4094   offs = size;
4095   while (offs--) {
4096     //DEBUGpc ("comparing bytes at offset %d", offs);
4097     emitSKPZ;
4098     emitpcode (POC_GOTO, popGetLabel (templbl->key));
4099     pic14_mov2w_regOrLit (AOP(right), lit, offs);
4100     emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4101   } // while (offs)
4102   emitpLabel (templbl->key);
4103   goto result_in_carry;
4104
4105 result_in_carry:
4106   
4107   /****************************************************
4108    * now CARRY contains the result of the comparison: *
4109    * SUBWF sets CARRY iff                             *
4110    * F-W >= 0 <==> F >= W <==> !(F < W)               *
4111    * (F=left, W=right)                                *
4112    ****************************************************/
4113
4114   if (performedLt) {
4115     invert_result = 1;
4116     // value will be used in the following genSkipc()
4117     rIfx.condition ^= 1;
4118   } // if
4119
4120 correct_result_in_carry:
4121
4122   // assign result to variable (if neccessary)
4123   if (result && AOP_TYPE(result) != AOP_CRY) {
4124     //DEBUGpc ("assign result");
4125     size = AOP_SIZE(result);
4126     while (size--) {
4127       emitpcode (POC_CLRF, popGet (AOP(result), size));
4128     } // while
4129     if (invert_result) {
4130       emitSKPC;
4131       emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4132     } else {
4133       emitpcode (POC_RLF, popGet (AOP(result), 0));
4134     }
4135   } // if (result)
4136
4137   // perform conditional jump
4138   if (ifx) {
4139     //DEBUGpc ("generate control flow");
4140     genSkipc (&rIfx);
4141     ifx->generated = 1;
4142   } // if
4143 }
4144
4145
4146 #if 0
4147 /* OLD VERSION -- BUGGY, DO NOT USE */
4148
4149 /*-----------------------------------------------------------------*/
4150 /* genCmp :- greater or less than comparison                       */
4151 /*-----------------------------------------------------------------*/
4152 static void genCmp (operand *left,operand *right,
4153                                         operand *result, iCode *ifx, int sign)
4154 {
4155         int size; //, offset = 0 ;
4156         unsigned long lit = 0L,i = 0;
4157         resolvedIfx rFalseIfx;
4158         //  resolvedIfx rTrueIfx;
4159         symbol *truelbl;
4160
4161         FENTRY;
4162         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4163         /*
4164         if(ifx) {
4165         DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4166         DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4167         }
4168         */
4169         
4170         resolveIfx(&rFalseIfx,ifx);
4171         truelbl  = newiTempLabel(NULL);
4172         size = max(AOP_SIZE(left),AOP_SIZE(right));
4173         
4174         DEBUGpic14_AopType(__LINE__,left,right,result);
4175         
4176 #define _swapp
4177         
4178         /* if literal is on the right then swap with left */
4179         if ((AOP_TYPE(right) == AOP_LIT)) {
4180                 operand *tmp = right ;
4181                 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4182                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4183 #ifdef _swapp
4184                 
4185                 lit = (lit - 1) & mask;
4186                 right = left;
4187                 left = tmp;
4188                 rFalseIfx.condition ^= 1;
4189 #endif
4190                 
4191         } else if ((AOP_TYPE(left) == AOP_LIT)) {
4192                 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4193         }
4194         
4195         
4196         //if(IC_TRUE(ifx) == NULL)
4197         /* if left & right are bit variables */
4198         if (AOP_TYPE(left) == AOP_CRY &&
4199                 AOP_TYPE(right) == AOP_CRY ) {
4200                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4201                 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4202         } else {
4203         /* subtract right from left if at the
4204         end the carry flag is set then we know that
4205                 left is greater than right */
4206                 
4207                 symbol *lbl  = newiTempLabel(NULL);
4208                 
4209 #ifndef _swapp
4210                 if(AOP_TYPE(right) == AOP_LIT) {
4211                         
4212                         //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4213                         
4214                         DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4215                         
4216                         /* special cases */
4217                         
4218                         if(lit == 0) {
4219                                 
4220                                 if(sign != 0) 
4221                                         genSkipCond(&rFalseIfx,left,size-1,7);
4222                                 else 
4223                                         /* no need to compare to 0...*/
4224                                         /* NOTE: this is a de-generate compare that most certainly 
4225                                         *       creates some dead code. */
4226                                         emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4227                                 
4228                                 if(ifx) ifx->generated = 1;
4229                                 return;
4230                                 
4231                         }
4232                         size--;
4233                         
4234                         if(size == 0) {
4235                                 //i = (lit >> (size*8)) & 0xff;
4236                                 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4237                                 
4238                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4239                                 
4240                                 i = ((0-lit) & 0xff);
4241                                 if(sign) {
4242                                         if( i == 0x81) { 
4243                                         /* lit is 0x7f, all signed chars are less than
4244                                                 * this except for 0x7f itself */
4245                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4246                                                 genSkipz2(&rFalseIfx,0);
4247                                         } else {
4248                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4249                                                 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4250                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4251                                         }
4252                                         
4253                                 } else {
4254                                         if(lit == 1) {
4255                                                 genSkipz2(&rFalseIfx,1);
4256                                         } else {
4257                                                 emitpcode(POC_ADDLW, popGetLit(i));
4258                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4259                                         }
4260                                 }
4261                                 
4262                                 if(ifx) ifx->generated = 1;
4263                                 return;
4264                         }
4265                         
4266                         /* chars are out of the way. now do ints and longs */
4267                         
4268                         
4269                         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4270                         
4271                         /* special cases */
4272                         
4273                         if(sign) {
4274                                 
4275                                 if(lit == 0) {
4276                                         genSkipCond(&rFalseIfx,left,size,7);
4277                                         if(ifx) ifx->generated = 1;
4278                                         return;
4279                                 }
4280                                 
4281                                 if(lit <0x100) {
4282                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4283                                         
4284                                         //rFalseIfx.condition ^= 1;
4285                                         //genSkipCond(&rFalseIfx,left,size,7);
4286                                         //rFalseIfx.condition ^= 1;
4287                                         
4288                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4289                                         if(rFalseIfx.condition)
4290                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4291                                         else
4292                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4293                                         
4294                                         emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4295                                         emitpcode(POC_ADDFW, popGet(AOP(left),0));
4296                                         emitpcode(POC_MOVFW, popGet(AOP(left),1));
4297                                         
4298                                         while(size > 1)
4299                                                 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4300                                         
4301                                         if(rFalseIfx.condition) {
4302                                                 emitSKPZ;
4303                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4304                                                 
4305                                         } else {
4306                                                 emitSKPNZ;
4307                                         }
4308                                         
4309                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4310                                         emitpLabel(truelbl->key);
4311                                         if(ifx) ifx->generated = 1;
4312                                         return;
4313                                         
4314                                 }
4315                                 
4316                                 if(size == 1) {
4317                                         
4318                                         if( (lit & 0xff) == 0) {
4319                                                 /* lower byte is zero */
4320                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4321                                                 i = ((lit >> 8) & 0xff) ^0x80;
4322                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4323                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4324                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4325                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4326                                                 
4327                                                 
4328                                                 if(ifx) ifx->generated = 1;
4329                                                 return;
4330                                                 
4331                                         }
4332                                 } else {
4333                                         /* Special cases for signed longs */
4334                                         if( (lit & 0xffffff) == 0) {
4335                                                 /* lower byte is zero */
4336                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4337                                                 i = ((lit >> 8*3) & 0xff) ^0x80;
4338                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4339                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4340                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4341                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4342                                                 
4343                                                 
4344                                                 if(ifx) ifx->generated = 1;
4345                                                 return;
4346                                                 
4347                                         }
4348                                         
4349                                 }
4350                                 
4351                                 
4352                                 if(lit & (0x80 << (size*8))) {
4353                                         /* lit is negative */
4354                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4355                                         
4356                                         //genSkipCond(&rFalseIfx,left,size,7);
4357                                         
4358                                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4359                                         
4360                                         if(rFalseIfx.condition)
4361                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4362                                         else
4363                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4364                                         
4365                                         
4366                                 } else {
4367                                         /* lit is positive */
4368                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4369                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4370                                         if(rFalseIfx.condition)
4371                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4372                                         else
4373                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4374                                         
4375                                 }
4376                                 
4377                                 /* There are no more special cases, so perform a general compare */
4378                                 
4379                                 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4380                                 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4381                                 
4382                                 while(size--) {
4383                                         
4384                                         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4385                                         emitSKPNZ;
4386                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4387                                 }
4388                                 //rFalseIfx.condition ^= 1;
4389                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4390                                 
4391                                 emitpLabel(truelbl->key);
4392                                 
4393                                 if(ifx) ifx->generated = 1;
4394                                 return;
4395                                 
4396                                 
4397                         }
4398
4399
4400                         /* sign is out of the way. So now do an unsigned compare */
4401                         DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4402
4403
4404                         /* General case - compare to an unsigned literal on the right.*/
4405
4406                         i = (lit >> (size*8)) & 0xff;
4407                         emitpcode(POC_MOVLW, popGetLit(i));
4408                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4409                         while(size--) {
4410                                 i = (lit >> (size*8)) & 0xff;
4411                                 
4412                                 if(i) {
4413                                         emitpcode(POC_MOVLW, popGetLit(i));
4414                                         emitSKPNZ;
4415                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4416                                 } else {
4417                                 /* this byte of the lit is zero, 
4418                                         *if it's not the last then OR in the variable */
4419                                         if(size)
4420                                                 emitpcode(POC_IORFW, popGet(AOP(left),size));
4421                                 }
4422                         }
4423
4424
4425                 emitpLabel(lbl->key);
4426                 //if(emitFinalCheck)
4427                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4428                 if(sign)
4429                         emitpLabel(truelbl->key);
4430
4431                 if(ifx) ifx->generated = 1;
4432                 return;
4433
4434
4435                 }
4436 #endif  // _swapp
4437
4438                 if(AOP_TYPE(left) == AOP_LIT) {
4439                         //symbol *lbl = newiTempLabel(NULL);
4440                         
4441                         //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4442                         
4443                         
4444                         DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4445                         
4446                         /* Special cases */
4447                         if((lit == 0) && (sign == 0)){
4448                                 
4449                                 size--;
4450                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4451                                 while(size) 
4452                                         emitpcode(POC_IORFW, popGet(AOP(right),--size));
4453                                 
4454                                 genSkipz2(&rFalseIfx,0);
4455                                 if(ifx) ifx->generated = 1;
4456                                 return;
4457                         }
4458                         
4459                         if(size==1) {
4460                                 /* Special cases */
4461                                 lit &= 0xff;
4462                                 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4463                                         /* degenerate compare can never be true */
4464                                         if(rFalseIfx.condition == 0)
4465                                                 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4466                                         
4467                                         if(ifx) ifx->generated = 1;
4468                                         return;
4469                                 }
4470                                 
4471                                 if(sign) {
4472                                         /* signed comparisons to a literal byte */
4473                                         
4474                                         int lp1 = (lit+1) & 0xff;
4475                                         
4476                                         DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4477                                         switch (lp1) {
4478                                         case 0:
4479                                                 rFalseIfx.condition ^= 1;
4480                                                 genSkipCond(&rFalseIfx,right,0,7);
4481                                                 break;
4482                                         case 0x7f:
4483                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4484                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4485                                                 genSkipz2(&rFalseIfx,1);
4486                                                 break;
4487                                         default:
4488                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4489                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4490                                                 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4491                                                 rFalseIfx.condition ^= 1;
4492                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4493                                                 break;
4494                                         }
4495                                         if(ifx) ifx->generated = 1;
4496                                 } else {
4497                                         /* unsigned comparisons to a literal byte */
4498                                         
4499                                         switch(lit & 0xff ) {
4500                                         case 0:
4501                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4502                                                 genSkipz2(&rFalseIfx,0);
4503                                                 if(ifx) ifx->generated = 1;
4504                                                 break;
4505                                         case 0x7f:
4506                                                 genSkipCond(&rFalseIfx,right,0,7);
4507                                                 if(ifx) ifx->generated = 1;
4508                                                 break;
4509                                                 
4510                                         default:
4511                                                 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4512                                                 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4513                                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4514                                                 rFalseIfx.condition ^= 1;
4515                                                 if (AOP_TYPE(result) == AOP_CRY) {
4516                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4517                                                         if(ifx) ifx->generated = 1;
4518                                                 } else {
4519                                                         DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4520                                                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4521                                                         emitpcode(POC_RLF, popGet(AOP(result),0));
4522                                                         emitpcode(POC_MOVLW, popGetLit(0x01));
4523                                                         emitpcode(POC_XORWF, popGet(AOP(result),0));
4524                                                 }       
4525                                                 break;
4526                                         }
4527                                 }
4528                                 
4529                                 //goto check_carry;
4530                                 return;
4531                                 
4532                         } else {
4533                                 
4534                                 /* Size is greater than 1 */
4535                                 
4536                                 if(sign) {
4537                                         int lp1 = lit+1;
4538                                         
4539                                         size--;
4540                                         
4541                                         if(lp1 == 0) {
4542                                                 /* this means lit = 0xffffffff, or -1 */
4543                                                 
4544                                                 
4545                                                 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4546                                                 rFalseIfx.condition ^= 1;
4547                                                 genSkipCond(&rFalseIfx,right,size,7);
4548                                                 if(ifx) ifx->generated = 1;
4549                                                 return;
4550                                         }
4551                                         
4552                                         if(lit == 0) {
4553                                                 int s = size;
4554                                                 
4555                                                 if(rFalseIfx.condition) {
4556                                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4557                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4558                                                 }
4559                                                 
4560                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4561                                                 while(size--)
4562                                                         emitpcode(POC_IORFW, popGet(AOP(right),size));
4563                                                 
4564                                                 
4565                                                 emitSKPZ;
4566                                                 if(rFalseIfx.condition) {
4567                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4568                                                         emitpLabel(truelbl->key);
4569                                                 }else {
4570                                                         rFalseIfx.condition ^= 1;
4571                                                         genSkipCond(&rFalseIfx,right,s,7);
4572                                                 }
4573                                                 
4574                                                 if(ifx) ifx->generated = 1;
4575                                                 return;
4576                                         }
4577                                         
4578                                         if((size == 1) &&  (0 == (lp1&0xff))) {
4579                                                 /* lower byte of signed word is zero */
4580                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4581                                                 i = ((lp1 >> 8) & 0xff) ^0x80;
4582                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4583                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4584                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4585                                                 rFalseIfx.condition ^= 1;
4586                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4587                                                 
4588                                                 
4589                                                 if(ifx) ifx->generated = 1;
4590                                                 return;
4591                                         }
4592                                         
4593                                         if(lit & (0x80 << (size*8))) {
4594                                                 /* Lit is less than zero */
4595                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4596                                                 //rFalseIfx.condition ^= 1;
4597                                                 //genSkipCond(&rFalseIfx,left,size,7);
4598                                                 //rFalseIfx.condition ^= 1;
4599                                                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4600                                                 //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4601                                                 
4602                                                 if(rFalseIfx.condition)
4603                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4604                                                 else
4605                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4606                                                 
4607                                                 
4608                                         } else {
4609                                                 /* Lit is greater than or equal to zero */
4610                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4611                                                 //rFalseIfx.condition ^= 1;
4612                                                 //genSkipCond(&rFalseIfx,right,size,7);
4613                                                 //rFalseIfx.condition ^= 1;
4614                                                 
4615                                                 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4616                                                 //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4617                                                 
4618                                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4619                                                 if(rFalseIfx.condition)
4620                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4621                                                 else
4622                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4623                                                 
4624                                         }
4625                                         
4626                                         
4627                                         emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4628                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4629                                         
4630                                         while(size--) {
4631                                                 
4632                                                 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4633                                                 emitSKPNZ;
4634                                                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4635                                         }
4636                                         rFalseIfx.condition ^= 1;
4637                                         //rFalseIfx.condition = 1;
4638                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4639                                         
4640                                         emitpLabel(truelbl->key);
4641                                         
4642                                         if(ifx) ifx->generated = 1;
4643                                         return;
4644                                         // end of if (sign)
4645                                 } else {
4646                                         
4647                                         /* compare word or long to an unsigned literal on the right.*/
4648                                         
4649                                         
4650                                         size--;
4651                                         if(lit < 0xff) {
4652                                                 DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4653                                                 switch (lit) {
4654                                                 case 0:
4655                                                         break; /* handled above */
4656                                                 /*
4657                                                 case 0xff:
4658                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4659                                                         while(size--)
4660                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4661                                                         genSkipz2(&rFalseIfx,0);
4662                                                         break;
4663                                                 */
4664                                                 default:
4665                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4666                                                         while(--size)
4667                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4668                                                         
4669                                                         emitSKPZ;
4670                                                         if(rFalseIfx.condition)
4671                                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4672                                                         else
4673                                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4674                                                         
4675                                                         
4676                                                         emitpcode(POC_MOVLW, popGetLit(lit+1));
4677                                                         emitpcode(POC_SUBFW, popGet(AOP(right),0));
4678                                                         
4679                                                         rFalseIfx.condition ^= 1;
4680                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4681                                                 }
4682                                                 
4683                                                 emitpLabel(truelbl->key);
4684                                                 
4685                                                 if(ifx) ifx->generated = 1;
4686                                                 return;
4687                                         }
4688                                         
4689                                         
4690                                         lit++;
4691                                         DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4692                                         i = (lit >> (size*8)) & 0xff;
4693                                         
4694                                         emitpcode(POC_MOVLW, popGetLit(i));
4695                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4696                                         
4697                                         while(size--) {
4698                                                 i = (lit >> (size*8)) & 0xff;
4699                                                 
4700                                                 if(i) {
4701                                                         emitpcode(POC_MOVLW, popGetLit(i));
4702                                                         emitSKPNZ;
4703                                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4704                                                 } else {
4705                                                 /* this byte of the lit is zero, 
4706                                                         *if it's not the last then OR in the variable */
4707                                                         if(size)
4708                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4709                                                 }
4710                                         }
4711                                         
4712                                         
4713                                         emitpLabel(lbl->key);
4714                                         
4715                                         rFalseIfx.condition ^= 1;
4716                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4717                                 }
4718                                 
4719                                 if(sign)
4720                                         emitpLabel(truelbl->key);
4721                                 if(ifx) ifx->generated = 1;
4722                                 return;
4723                         }
4724                 }
4725                 /* Compare two variables */
4726                 
4727                 DEBUGpic14_emitcode(";sign","%d",sign);
4728                 
4729                 size--;
4730                 if(sign) {
4731                         /* Sigh. thus sucks... */
4732                         if(size) {
4733                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4734                                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4735                                 emitpcode(POC_MOVLW, popGetLit(0x80));
4736                                 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4737                                 emitpcode(POC_XORFW, popGet(AOP(right),size));
4738                                 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4739                         } else {
4740                                 /* Signed char comparison */
4741                                 /* Special thanks to Nikolai Golovchenko for this snippet */
4742                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4743                                 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4744                                 emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4745                                 emitpcode(POC_XORFW, popGet(AOP(left),0));
4746                                 emitpcode(POC_XORFW, popGet(AOP(right),0));
4747                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4748                                 
4749                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4750                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4751                                 
4752                                 if(ifx) ifx->generated = 1;
4753                                 return;
4754                         }
4755                         
4756                 } else {
4757                         
4758                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4759                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4760                 }
4761                 
4762                 
4763                 /* The rest of the bytes of a multi-byte compare */
4764                 while (size) {
4765                         
4766                         emitSKPZ;
4767                         emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4768                         size--;
4769                         
4770                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4771                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4772                         
4773                         
4774                 }
4775                 
4776                 emitpLabel(lbl->key);
4777                 
4778                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4779                 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4780                         (AOP_TYPE(result) == AOP_REG)) {
4781                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4782                         emitpcode(POC_RLF, popGet(AOP(result),0));
4783                 } else {
4784                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4785                 }       
4786                 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4787                 if(ifx) ifx->generated = 1;
4788                 
4789                 return;
4790                 
4791         }
4792         
4793         // check_carry:
4794         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4795                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4796                 pic14_outBitC(result);
4797         } else {
4798                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4799                 /* if the result is used in the next
4800                 ifx conditional branch then generate
4801                 code a little differently */
4802                 if (ifx )
4803                         genIfxJump (ifx,"c");
4804                 else
4805                         pic14_outBitC(result);
4806                 /* leave the result in acc */
4807         }
4808         
4809 }
4810 #endif
4811
4812 /*-----------------------------------------------------------------*/
4813 /* genCmpGt :- greater than comparison                             */
4814 /*-----------------------------------------------------------------*/
4815 static void genCmpGt (iCode *ic, iCode *ifx)
4816 {
4817         operand *left, *right, *result;
4818         sym_link *letype , *retype;
4819         int sign ;
4820         
4821         FENTRY;
4822         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4823         left = IC_LEFT(ic);
4824         right= IC_RIGHT(ic);
4825         result = IC_RESULT(ic);
4826         
4827         letype = getSpec(operandType(left));
4828         retype =getSpec(operandType(right));
4829         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4830         /* assign the amsops */
4831         aopOp (left,ic,FALSE);
4832         aopOp (right,ic,FALSE);
4833         aopOp (result,ic,TRUE);
4834         
4835         genCmp(right, left, result, ifx, sign);
4836         
4837         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4838         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4839         freeAsmop(result,NULL,ic,TRUE); 
4840 }
4841
4842 /*-----------------------------------------------------------------*/
4843 /* genCmpLt - less than comparisons                                */
4844 /*-----------------------------------------------------------------*/
4845 static void genCmpLt (iCode *ic, iCode *ifx)
4846 {
4847         operand *left, *right, *result;
4848         sym_link *letype , *retype;
4849         int sign ;
4850         
4851         FENTRY;
4852         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4853         left = IC_LEFT(ic);
4854         right= IC_RIGHT(ic);
4855         result = IC_RESULT(ic);
4856         
4857         letype = getSpec(operandType(left));
4858         retype =getSpec(operandType(right));
4859         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4860         
4861         /* assign the amsops */
4862         aopOp (left,ic,FALSE);
4863         aopOp (right,ic,FALSE);
4864         aopOp (result,ic,TRUE);
4865         
4866         genCmp(left, right, result, ifx, sign);
4867         
4868         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4869         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4870         freeAsmop(result,NULL,ic,TRUE); 
4871 }
4872
4873 #if 0
4874 /*-----------------------------------------------------------------*/
4875 /* genc16bit2lit - compare a 16 bit value to a literal             */
4876 /*-----------------------------------------------------------------*/
4877 static void genc16bit2lit(operand *op, int lit, int offset)
4878 {
4879         int i;
4880         
4881         FENTRY;
4882         DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4883         if( (lit&0xff) == 0) 
4884                 i=1;
4885         else
4886                 i=0;
4887         
4888         switch( BYTEofLONG(lit,i)) { 
4889         case 0:
4890                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4891                 break;
4892         case 1:
4893                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4894                 break;
4895         case 0xff:
4896                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4897                 break;
4898         default:
4899                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4900                 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4901         }
4902         
4903         i ^= 1;
4904         
4905         switch( BYTEofLONG(lit,i)) { 
4906         case 0:
4907                 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4908                 break;
4909         case 1:
4910                 emitSKPNZ;
4911                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4912                 break;
4913         case 0xff:
4914                 emitSKPNZ;
4915                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4916                 break;
4917         default:
4918                 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4919                 emitSKPNZ;
4920                 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4921                 
4922         }
4923         
4924 }
4925 #endif
4926
4927 #if 0
4928 /*-----------------------------------------------------------------*/
4929 /* gencjneshort - compare and jump if not equal                    */
4930 /*-----------------------------------------------------------------*/
4931 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4932 {
4933         int size = min(AOP_SIZE(left),AOP_SIZE(right));
4934         int offset = 0;
4935         //resolvedIfx rIfx;
4936         symbol *lbl;
4937         
4938         //unsigned long lit = 0L;
4939         FENTRY;
4940         if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4941           emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4942           return;
4943         }
4944         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4945         DEBUGpic14_AopType(__LINE__,left,right,result);
4946         
4947         assert (!pic14_sameRegs (AOP(left), AOP(result)));
4948         assert (!pic14_sameRegs (AOP(right), AOP(result)));
4949         if (AOP_SIZE(result)) {
4950           for (offset = 0; offset < AOP_SIZE(result); offset++)
4951             emitpcode (POC_CLRF, popGet (AOP(result), offset));
4952         }
4953         
4954         assert (AOP_SIZE(left) == AOP_SIZE(right));
4955         //resolveIfx(&rIfx,ifx);
4956         lbl = newiTempLabel (NULL);
4957         while (size--)
4958         {
4959           mov2w (AOP(right),size);
4960           emitpcode (POC_XORFW, popGet (AOP(left), size));
4961           if (size)
4962           {
4963             emitSKPZ;
4964             emitpcode (POC_GOTO, popGetLabel (lbl->key));
4965           }
4966         } // while
4967         emitpLabel (lbl->key);
4968         if (AOP_SIZE(result)) {
4969           emitSKPNZ;
4970           emitpcode (POC_INCF, popGet (AOP(result), 0));
4971         } else {
4972           assert (ifx);
4973           genSkipz (ifx, NULL != IC_TRUE(ifx));
4974           ifx->generated = 1;
4975         }
4976         return;
4977 #if 0   
4978         if(result)
4979         {
4980                 DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4981                 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4982                 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4983                 for (offset=0; offset < AOP_SIZE(result); offset++)
4984                 {
4985                         emitpcode (POC_CLRF, popGet (AOP(result), offset));
4986                 } // for offset
4987         }
4988         
4989         
4990         /* if the left side is a literal or 
4991         if the right is in a pointer register and left 
4992         is not */
4993         if ((AOP_TYPE(left) == AOP_LIT) || 
4994                 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4995                 operand *t = right;
4996                 right = left;
4997                 left = t;
4998         }
4999         if(AOP_TYPE(right) == AOP_LIT)
5000                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5001         
5002         /* if the right side is a literal then anything goes */
5003         if (AOP_TYPE(right) == AOP_LIT &&
5004                 AOP_TYPE(left) != AOP_DIR ) {
5005                 switch(size) {
5006                 case 2:
5007                         genc16bit2lit(left, lit, 0);
5008                         emitSKPNZ;
5009                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
5010                         break;
5011                 default:
5012                         offset = 0;
5013                         while (size--) {
5014                                 if(lit & 0xff) {
5015                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5016                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5017                                 } else {
5018                                         emitpcode(POC_MOVF,popGet(AOP(left),offset));
5019                                 }
5020                                 
5021                                 emitSKPNZ;
5022                                 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5023                                 offset++;
5024                                 lit >>= 8;
5025                         }
5026                         break;
5027                 }
5028         }
5029         
5030         /* if the right side is in a register or in direct space or
5031         if the left is a pointer register & right is not */    
5032         else if (AOP_TYPE(right) == AOP_REG ||
5033                 AOP_TYPE(right) == AOP_DIR || 
5034                 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5035                 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5036                 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5037                 int lbl_key = lbl->key;
5038                 
5039                 if(!result) {
5040                         DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5041                         fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5042                                 __FUNCTION__,__LINE__);
5043                         return;
5044                 }
5045                 
5046                 /*     switch(size) { */
5047                 /*     case 2: */
5048                 /*       genc16bit2lit(left, lit, 0); */
5049                 /*       emitSKPNZ; */
5050                 /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
5051                 /*       break; */
5052                 /*     default: */
5053                 offset = 0;
5054                 while (size--) {
5055                         int emit_skip=1;
5056                         if((AOP_TYPE(left) == AOP_DIR) && 
5057                                 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5058                                 
5059                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5060                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5061                                 
5062                         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5063                                 
5064                                 switch (lit & 0xff) {
5065                                 case 0:
5066                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5067                                         break;
5068                                 case 1:
5069                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5070                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5071                                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
5072                                         emit_skip=0;
5073                                         break;
5074                                 case 0xff:
5075                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5076                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5077                                         //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5078                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5079                                         emit_skip=0;
5080                                         break;
5081                                 default:
5082                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5083                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5084                                 }
5085                                 lit >>= 8;
5086                                 
5087                         } else {
5088                                 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5089                         }
5090                         if(emit_skip) {
5091                                 if(AOP_TYPE(result) == AOP_CRY) {
5092                                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5093                                         if(rIfx.condition)
5094                                                 emitSKPNZ;
5095                                         else
5096                                                 emitSKPZ;
5097                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5098                                 } else {
5099                                         /* fix me. probably need to check result size too */
5100                                         //emitpcode(POC_CLRF,popGet(AOP(result),0));
5101                                         if(rIfx.condition)
5102                                                 emitSKPZ;
5103                                         else
5104                                                 emitSKPNZ;
5105                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5106                                 }
5107                                 if(ifx)
5108                                         ifx->generated=1;
5109                         }
5110                         emit_skip++;
5111                         offset++;
5112                 }
5113                 /*       break; */
5114                 /*     } */
5115         } else if(AOP_TYPE(right) == AOP_REG &&
5116                 AOP_TYPE(left) != AOP_DIR){
5117
5118                 offset = 0;
5119                 while(size--) {
5120                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5121                         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5122                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5123                         if(rIfx.condition)
5124                                 emitSKPNZ;
5125                         else
5126                                 emitSKPZ;
5127                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5128                         offset++;
5129                 }
5130                 
5131         }else{
5132                 /* right is a pointer reg need both a & b */
5133                 offset = 0;
5134                 while(size--) {
5135                         char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5136                         if(strcmp(l,"b"))
5137                                 pic14_emitcode("mov","b,%s",l);
5138                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5139                         pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5140                         offset++;
5141                 }
5142         }
5143         
5144         emitpcode(POC_INCF,popGet(AOP(result),0));
5145         if(!rIfx.condition)
5146                 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5147         
5148         emitpLabel(lbl->key);
5149         
5150         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5151         
5152         if(ifx)
5153                 ifx->generated = 1;
5154 #endif
5155 }
5156 #endif
5157
5158 #if 0
5159 /*-----------------------------------------------------------------*/
5160 /* gencjne - compare and jump if not equal                         */
5161 /*-----------------------------------------------------------------*/
5162 static void gencjne(operand *left, operand *right, iCode *ifx)
5163 {
5164         symbol *tlbl  = newiTempLabel(NULL);
5165         
5166         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5167         gencjneshort(left, right, lbl);
5168         
5169         pic14_emitcode("mov","a,%s",one);
5170         pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5171         pic14_emitcode("","%05d_DS_:",lbl->key+100);
5172         pic14_emitcode("clr","a");
5173         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5174         
5175         emitpLabel(lbl->key);
5176         emitpLabel(tlbl->key);
5177         
5178 }
5179 #endif
5180
5181 /*-----------------------------------------------------------------*/
5182 /* genCmpEq - generates code for equal to                          */
5183 /*-----------------------------------------------------------------*/
5184 static void genCmpEq (iCode *ic, iCode *ifx)
5185 {
5186   operand *left, *right, *result;
5187   int size;
5188   symbol *false_label;
5189
5190   FENTRY;
5191   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5192
5193   if(ifx)
5194     DEBUGpic14_emitcode ("; ifx is non-null","");
5195   else
5196     DEBUGpic14_emitcode ("; ifx is null","");
5197
5198   aopOp((left=IC_LEFT(ic)),ic,FALSE);
5199   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5200   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5201
5202   DEBUGpic14_AopType(__LINE__,left,right,result);
5203
5204   /* if literal, move literal to right */ 
5205   if (op_isLitLike (IC_LEFT(ic))) {
5206     operand *tmp = right ;
5207     right = left;
5208     left = tmp;
5209   }
5210
5211   false_label = NULL;
5212   if (ifx && !IC_TRUE(ifx))
5213   {
5214     assert (IC_FALSE(ifx));
5215     false_label = IC_FALSE(ifx);
5216   }
5217
5218   size = min(AOP_SIZE(left),AOP_SIZE(right));
5219   assert(!pic14_sameRegs(AOP(result),AOP(left)));
5220   assert(!pic14_sameRegs(AOP(result),AOP(right)));
5221
5222   /* assume left != right */
5223   {
5224     int i;
5225     for (i=0; i < AOP_SIZE(result); i++)
5226     {
5227       emitpcode(POC_CLRF, popGet(AOP(result),i));
5228     }
5229   }
5230
5231   if (AOP_TYPE(right) == AOP_LIT)
5232   {
5233     unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5234     int i;
5235     size = AOP_SIZE(left);
5236     assert(!op_isLitLike(left));
5237
5238     switch (lit)
5239     {
5240       case 0:
5241         mov2w(AOP(left), 0);
5242         for (i=1; i < size; i++)
5243           emitpcode(POC_IORFW,popGet(AOP(left),i));
5244         /* now Z is set iff `left == right' */
5245         emitSKPZ;
5246         if (!false_label) false_label = newiTempLabel(NULL);
5247         emitpcode(POC_GOTO, popGetLabel(false_label->key));
5248         break;
5249
5250       default:
5251         for (i=0; i < size; i++)
5252         {
5253           mov2w(AOP(left),i);
5254           emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5255           /* now Z is cleared if `left != right' */
5256           emitSKPZ;
5257           if (!false_label) false_label = newiTempLabel(NULL);
5258           emitpcode(POC_GOTO, popGetLabel(false_label->key));
5259         } // for i
5260         break;
5261     } // switch (lit)
5262   }
5263   else
5264   {
5265     /* right is no literal */
5266     int i;
5267
5268     for (i=0; i < size; i++)
5269     {
5270       mov2w(AOP(right),i);
5271       emitpcode(POC_XORFW,popGet(AOP(left),i));
5272       /* now Z is cleared if `left != right' */
5273       emitSKPZ;
5274       if (!false_label) false_label = newiTempLabel(NULL);
5275       emitpcode(POC_GOTO, popGetLabel(false_label->key));
5276     } // for i
5277   }
5278
5279   /* if we reach here, left == right */
5280
5281   if (AOP_SIZE(result) > 0)
5282   {
5283     emitpcode(POC_INCF, popGet(AOP(result),0));
5284   }
5285
5286   if (ifx && IC_TRUE(ifx))
5287   {
5288     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5289   }
5290
5291   if (false_label && (!ifx || IC_TRUE(ifx)))
5292     emitpLabel(false_label->key);
5293
5294   if (ifx) ifx->generated = 1;
5295
5296   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5297   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5298   freeAsmop(result,NULL,ic,TRUE);
5299 }
5300
5301 /*-----------------------------------------------------------------*/
5302 /* ifxForOp - returns the icode containing the ifx for operand     */
5303 /*-----------------------------------------------------------------*/
5304 static iCode *ifxForOp ( operand *op, iCode *ic )
5305 {
5306         FENTRY;
5307         /* if true symbol then needs to be assigned */
5308         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5309         if (IS_TRUE_SYMOP(op))
5310                 return NULL ;
5311         
5312         /* if this has register type condition and
5313         the next instruction is ifx with the same operand
5314         and live to of the operand is upto the ifx only then */
5315         if (ic->next &&
5316                 ic->next->op == IFX &&
5317                 IC_COND(ic->next)->key == op->key &&
5318                 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5319                 return ic->next;
5320         
5321         if (ic->next &&
5322                 ic->next->op == IFX &&
5323                 IC_COND(ic->next)->key == op->key) {
5324                 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5325                 return ic->next;
5326         }
5327         
5328         DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5329         if (ic->next &&
5330                 ic->next->op == IFX)
5331                 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5332         
5333         if (ic->next &&
5334                 ic->next->op == IFX &&
5335                 IC_COND(ic->next)->key == op->key) {
5336                 DEBUGpic14_emitcode ("; "," key is okay");
5337                 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5338                         OP_SYMBOL(op)->liveTo,
5339                         ic->next->seq);
5340         }
5341         
5342         
5343         return NULL;
5344 }
5345 /*-----------------------------------------------------------------*/
5346 /* genAndOp - for && operation                                     */
5347 /*-----------------------------------------------------------------*/
5348 static void genAndOp (iCode *ic)
5349 {
5350         operand *left,*right, *result;
5351         /*     symbol *tlbl; */
5352         
5353         FENTRY;
5354         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5355         /* note here that && operations that are in an
5356         if statement are taken away by backPatchLabels
5357         only those used in arthmetic operations remain */
5358         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5359         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5360         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5361         
5362         DEBUGpic14_AopType(__LINE__,left,right,result);
5363         
5364         emitpcode(POC_MOVFW,popGet(AOP(left),0));
5365         emitpcode(POC_ANDFW,popGet(AOP(right),0));
5366         emitpcode(POC_MOVWF,popGet(AOP(result),0));
5367         
5368         /* if both are bit variables */
5369         /*     if (AOP_TYPE(left) == AOP_CRY && */
5370         /*         AOP_TYPE(right) == AOP_CRY ) { */
5371         /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5372         /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5373         /*         pic14_outBitC(result); */
5374         /*     } else { */
5375         /*         tlbl = newiTempLabel(NULL); */
5376         /*         pic14_toBoolean(left);     */
5377         /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5378         /*         pic14_toBoolean(right); */
5379         /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5380         /*         pic14_outBitAcc(result); */
5381         /*     } */
5382         
5383         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5384         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5385         freeAsmop(result,NULL,ic,TRUE);
5386 }
5387
5388
5389 /*-----------------------------------------------------------------*/
5390 /* genOrOp - for || operation                                      */
5391 /*-----------------------------------------------------------------*/
5392 /*
5393 tsd pic port -
5394 modified this code, but it doesn't appear to ever get called
5395 */
5396
5397 static void genOrOp (iCode *ic)
5398 {
5399         operand *left,*right, *result;
5400         symbol *tlbl;
5401         int i;
5402         
5403         /* note here that || operations that are in an
5404         if statement are taken away by backPatchLabels
5405         only those used in arthmetic operations remain */
5406         FENTRY;
5407         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5408         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5409         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5410         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5411         
5412         DEBUGpic14_AopType(__LINE__,left,right,result);
5413
5414         for (i=0; i < AOP_SIZE(result); i++)
5415         {
5416                 emitpcode(POC_CLRF, popGet(AOP(result), i));
5417         } // for i
5418
5419         tlbl = newiTempLabel(NULL);
5420         pic14_toBoolean(left);
5421         emitSKPZ;
5422         emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5423         pic14_toBoolean(right);
5424         emitpLabel(tlbl->key);
5425         /* here Z is clear IFF `left || right' */
5426         emitSKPZ;
5427         emitpcode(POC_INCF, popGet(AOP(result), 0));
5428         
5429         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5430         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5431         freeAsmop(result,NULL,ic,TRUE);            
5432 }
5433
5434 /*-----------------------------------------------------------------*/
5435 /* isLiteralBit - test if lit == 2^n                               */
5436 /*-----------------------------------------------------------------*/
5437 static int isLiteralBit(unsigned long lit)
5438 {
5439         unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5440                 0x100L,0x200L,0x400L,0x800L,
5441                 0x1000L,0x2000L,0x4000L,0x8000L,
5442                 0x10000L,0x20000L,0x40000L,0x80000L,
5443                 0x100000L,0x200000L,0x400000L,0x800000L,
5444                 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5445                 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5446         int idx;
5447         
5448         FENTRY;
5449         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5450         for(idx = 0; idx < 32; idx++)
5451                 if(lit == pw[idx])
5452                         return idx+1;
5453                 return 0;
5454 }
5455
5456 /*-----------------------------------------------------------------*/
5457 /* continueIfTrue -                                                */
5458 /*-----------------------------------------------------------------*/
5459 static void continueIfTrue (iCode *ic)
5460 {
5461         FENTRY;
5462         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5463         if(IC_TRUE(ic))
5464         {
5465                 // Why +100?!?
5466                 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5467                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5468         }
5469         ic->generated = 1;
5470 }
5471
5472 /*-----------------------------------------------------------------*/
5473 /* jmpIfTrue -                                                     */
5474 /*-----------------------------------------------------------------*/
5475 static void jumpIfTrue (iCode *ic)
5476 {
5477         FENTRY;
5478         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5479         if(!IC_TRUE(ic))
5480         {
5481                 // Why +100?!?
5482                 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5483                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5484         }
5485         ic->generated = 1;
5486 }
5487
5488 /*-----------------------------------------------------------------*/
5489 /* jmpTrueOrFalse -                                                */
5490 /*-----------------------------------------------------------------*/
5491 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5492 {
5493         FENTRY;
5494         // ugly but optimized by peephole
5495         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5496         if(IC_TRUE(ic)){
5497                 symbol *nlbl = newiTempLabel(NULL);
5498                 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5499                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5500                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5501                 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5502         }
5503         else{
5504                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5505                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5506         }
5507         ic->generated = 1;
5508 }
5509
5510 /*-----------------------------------------------------------------*/
5511 /* genAnd  - code for and                                          */
5512 /*-----------------------------------------------------------------*/
5513 static void genAnd (iCode *ic, iCode *ifx)
5514 {
5515         operand *left, *right, *result;
5516         int size, offset=0;  
5517         unsigned long lit = 0L;
5518         int bytelit = 0;
5519         resolvedIfx rIfx;
5520         
5521         FENTRY;
5522         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5523         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5524         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5525         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5526         
5527         resolveIfx(&rIfx,ifx);
5528         
5529         /* if left is a literal & right is not then exchange them */
5530         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5531                 AOP_NEEDSACC(left)) {
5532                 operand *tmp = right ;
5533                 right = left;
5534                 left = tmp;
5535         }
5536         
5537         /* if result = right then exchange them */
5538         if(pic14_sameRegs(AOP(result),AOP(right))){
5539                 operand *tmp = right ;
5540                 right = left;
5541                 left = tmp;
5542         }
5543         
5544         /* if right is bit then exchange them */
5545         if (AOP_TYPE(right) == AOP_CRY &&
5546                 AOP_TYPE(left) != AOP_CRY){
5547                 operand *tmp = right ;
5548                 right = left;
5549                 left = tmp;
5550         }
5551         if(AOP_TYPE(right) == AOP_LIT)
5552                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5553         
5554         size = AOP_SIZE(result);
5555         
5556         DEBUGpic14_AopType(__LINE__,left,right,result);
5557         
5558         // if(bit & yy)
5559         // result = bit & yy;
5560         if (AOP_TYPE(left) == AOP_CRY){
5561                 // c = bit & literal;
5562                 if(AOP_TYPE(right) == AOP_LIT){
5563                         if(lit & 1) {
5564                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5565                                         // no change
5566                                         goto release;
5567                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5568                         } else {
5569                                 // bit(result) = 0;
5570                                 if(size && (AOP_TYPE(result) == AOP_CRY)){
5571                                         pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5572                                         goto release;
5573                                 }
5574                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5575                                         jumpIfTrue(ifx);
5576                                         goto release;
5577                                 }
5578                                 pic14_emitcode("clr","c");
5579                         }
5580                 } else {
5581                         if (AOP_TYPE(right) == AOP_CRY){
5582                                 // c = bit & bit;
5583                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5584                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5585                         } else {
5586                                 // c = bit & val;
5587                                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5588                                 // c = lsb
5589                                 pic14_emitcode("rrc","a");
5590                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5591                         }
5592                 }
5593                 // bit = c
5594                 // val = c
5595                 if(size)
5596                         pic14_outBitC(result);
5597                 // if(bit & ...)
5598                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5599                         genIfxJump(ifx, "c");           
5600                 goto release ;
5601         }
5602         
5603         // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5604         // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5605         if((AOP_TYPE(right) == AOP_LIT) &&
5606                 (AOP_TYPE(result) == AOP_CRY) &&
5607                 (AOP_TYPE(left) != AOP_CRY)){
5608                 int posbit = isLiteralBit(lit);
5609                 /* left &  2^n */
5610                 if(posbit){
5611                         posbit--;
5612                         //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5613                         // bit = left & 2^n
5614                         if(size)
5615                                 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5616                         // if(left &  2^n)
5617                         else{
5618                                 if(ifx){
5619                                         int offset = 0;
5620                                         while (posbit > 7) {
5621                                                 posbit -= 8;
5622                                                 offset++;
5623                                         }
5624                                         emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5625                                                 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5626                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5627                                         
5628                                         ifx->generated = 1;
5629                                 }
5630                                 goto release;
5631                         }
5632                 } else {
5633                         symbol *tlbl = newiTempLabel(NULL);
5634                         int sizel = AOP_SIZE(left);
5635                         if(size)
5636                                 pic14_emitcode("setb","c");
5637                         while(sizel--){
5638                                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5639                                         mov2w( AOP(left), offset);
5640                                         // byte ==  2^n ?
5641                                         if((posbit = isLiteralBit(bytelit)) != 0) {
5642                                                 emitpcode(rIfx.condition ? POC_BTFSC : POC_BTFSS, // XXX: or the other way round?
5643                                                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit - 1, 0));
5644                                                 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5645                                         }
5646                                         else{
5647                                                 emitpcode(POC_ANDLW, newpCodeOpLit(bytelit & 0x0ff));
5648                                                 if (rIfx.condition) emitSKPZ;
5649                                                 else emitSKPNZ;
5650                                                 
5651                                                 if(bytelit != 0x0FFL)
5652                                                 {
5653                                                         pic14_emitcode("anl","a,%s",
5654                                                         aopGet(AOP(right),offset,FALSE,TRUE));
5655                                                 }
5656                                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5657                                         }
5658
5659                                         emitpcode(POC_GOTO, popGetLabel(rIfx.lbl->key));
5660                                         ifx->generated = 1;
5661                                                 
5662                                 }
5663                                 offset++;
5664                         }
5665                         // bit = left & literal
5666                         if(size){
5667                                 pic14_emitcode("clr","c");
5668                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5669                         }
5670                         // if(left & literal)
5671                         else{
5672                                 if(ifx)
5673                                         jmpTrueOrFalse(ifx, tlbl);
5674                                 goto release ;
5675                         }
5676                 }
5677                 pic14_outBitC(result);
5678                 goto release ;
5679         }
5680         
5681         /* if left is same as result */
5682         if(pic14_sameRegs(AOP(result),AOP(left))){
5683                 int know_W = -1;
5684                 for(;size--; offset++,lit>>=8) {
5685                         if(AOP_TYPE(right) == AOP_LIT){
5686                                 switch(lit & 0xff) {
5687                                 case 0x00:
5688                                         /*  and'ing with 0 has clears the result */
5689                                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
5690                                         break;
5691                                 case 0xff:
5692                                         /* and'ing with 0xff is a nop when the result and left are the same */
5693                                         break;
5694                                         
5695                                 default:
5696                                         {
5697                                                 int p = my_powof2( (~lit) & 0xff );
5698                                                 if(p>=0) {
5699                                                         /* only one bit is set in the literal, so use a bcf instruction */
5700                                                         emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5701                                                         
5702                                                 } else {
5703                                                         if(know_W != (int)(lit&0xff))
5704                                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5705                                                         know_W = lit &0xff;
5706                                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5707                                                 }
5708                                         }    
5709                                 }
5710                         } else {
5711                                 if (AOP_TYPE(left) == AOP_ACC) {
5712                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5713                                 } else {        
5714                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5715                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5716                                         
5717                                 }
5718                         }
5719                 }
5720                 
5721         } else {
5722                 // left & result in different registers
5723                 if(AOP_TYPE(result) == AOP_CRY){
5724                         // result = bit
5725                         // if(size), result in bit
5726                         // if(!size && ifx), conditional oper: if(left & right)
5727                         symbol *tlbl = newiTempLabel(NULL);
5728                         int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5729                         if(size)
5730                                 pic14_emitcode("setb","c");
5731                         while(sizer--){
5732                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5733                                 pic14_emitcode("anl","a,%s",
5734                                         aopGet(AOP(left),offset,FALSE,FALSE));
5735                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5736                                 offset++;
5737                         }
5738                         if(size){
5739                                 CLRC;
5740                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5741                                 pic14_outBitC(result);
5742                         } else if(ifx)
5743                                 jmpTrueOrFalse(ifx, tlbl);
5744                 } else {
5745                         for(;(size--);offset++) {
5746                                 // normal case
5747                                 // result = left & right
5748                                 if(AOP_TYPE(right) == AOP_LIT){
5749                                         int t = (lit >> (offset*8)) & 0x0FFL;
5750                                         switch(t) { 
5751                                         case 0x00:
5752                                                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5753                                                 break;
5754                                         case 0xff:
5755                                                 if(AOP_TYPE(left) != AOP_ACC) {
5756                                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5757                                                 }
5758                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5759                                                 break;
5760                                         default:
5761                                                 if(AOP_TYPE(left) == AOP_ACC) {
5762                                                         emitpcode(POC_ANDLW, popGetLit(t));
5763                                                 } else {
5764                                                         emitpcode(POC_MOVLW, popGetLit(t));
5765                                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5766                                                 }
5767                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5768                                         }
5769                                         continue;
5770                                 }
5771                                 
5772                                 if (AOP_TYPE(left) == AOP_ACC) {
5773                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5774                                 } else {
5775                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5776                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5777                                 }
5778                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5779                         }
5780                 }
5781         }
5782         
5783 release :
5784         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5785         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5786         freeAsmop(result,NULL,ic,TRUE);     
5787 }
5788
5789 /*-----------------------------------------------------------------*/
5790 /* genOr  - code for or                                            */
5791 /*-----------------------------------------------------------------*/
5792 static void genOr (iCode *ic, iCode *ifx)
5793 {
5794         operand *left, *right, *result;
5795         int size, offset=0;
5796         unsigned long lit = 0L;
5797         
5798         FENTRY;
5799         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5800         
5801         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5802         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5803         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5804         
5805         DEBUGpic14_AopType(__LINE__,left,right,result);
5806         
5807         /* if left is a literal & right is not then exchange them */
5808         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5809                 AOP_NEEDSACC(left)) {
5810                 operand *tmp = right ;
5811                 right = left;
5812                 left = tmp;
5813         }
5814         
5815         /* if result = right then exchange them */
5816         if(pic14_sameRegs(AOP(result),AOP(right))){
5817                 operand *tmp = right ;
5818                 right = left;
5819                 left = tmp;
5820         }
5821         
5822         /* if right is bit then exchange them */
5823         if (AOP_TYPE(right) == AOP_CRY &&
5824                 AOP_TYPE(left) != AOP_CRY){
5825                 operand *tmp = right ;
5826                 right = left;
5827                 left = tmp;
5828         }
5829         
5830         DEBUGpic14_AopType(__LINE__,left,right,result);
5831         
5832         if(AOP_TYPE(right) == AOP_LIT)
5833                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5834         
5835         size = AOP_SIZE(result);
5836         
5837         // if(bit | yy)
5838         // xx = bit | yy;
5839         if (AOP_TYPE(left) == AOP_CRY){
5840                 if(AOP_TYPE(right) == AOP_LIT){
5841                         // c = bit & literal;
5842                         if(lit){
5843                                 // lit != 0 => result = 1
5844                                 if(AOP_TYPE(result) == AOP_CRY){
5845                                         if(size)
5846                                                 emitpcode(POC_BSF, popGet(AOP(result),0));
5847                                         //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5848                                         //   AOP(result)->aopu.aop_dir,
5849                                         //   AOP(result)->aopu.aop_dir);
5850                                         else if(ifx)
5851                                                 continueIfTrue(ifx);
5852                                         goto release;
5853                                 }
5854                         } else {
5855                                 // lit == 0 => result = left
5856                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5857                                         goto release;
5858                                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5859                         }
5860                 } else {
5861                         if (AOP_TYPE(right) == AOP_CRY){
5862                                 if(pic14_sameRegs(AOP(result),AOP(left))){
5863                                         // c = bit | bit;
5864                                         emitpcode(POC_BCF,   popGet(AOP(result),0));
5865                                         emitpcode(POC_BTFSC, popGet(AOP(right),0));
5866                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5867                                         
5868                                         pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5869                                                 AOP(result)->aopu.aop_dir,
5870                                                 AOP(result)->aopu.aop_dir);
5871                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5872                                                 AOP(right)->aopu.aop_dir,
5873                                                 AOP(right)->aopu.aop_dir);
5874                                         pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5875                                                 AOP(result)->aopu.aop_dir,
5876                                                 AOP(result)->aopu.aop_dir);
5877                                 } else {
5878                                         if( AOP_TYPE(result) == AOP_ACC) {
5879                                                 emitpcode(POC_MOVLW, popGetLit(0));
5880                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5881                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5882                                                 emitpcode(POC_MOVLW, popGetLit(1));
5883                                                 
5884                                         } else {
5885                                                 
5886                                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5887                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5888                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5889                                                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5890                                                 
5891                                                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5892                                                         AOP(result)->aopu.aop_dir,
5893                                                         AOP(result)->aopu.aop_dir);
5894                                                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5895                                                         AOP(right)->aopu.aop_dir,
5896                                                         AOP(right)->aopu.aop_dir);
5897                                                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5898                                                         AOP(left)->aopu.aop_dir,
5899                                                         AOP(left)->aopu.aop_dir);
5900                                                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5901                                                         AOP(result)->aopu.aop_dir,
5902                                                         AOP(result)->aopu.aop_dir);
5903                                         }
5904                                 }
5905                         } else {
5906                                 // c = bit | val;
5907                                 symbol *tlbl = newiTempLabel(NULL);
5908                                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5909                                 
5910                                 
5911                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5912                                 if( AOP_TYPE(right) == AOP_ACC) {
5913                                         emitpcode(POC_IORLW, popGetLit(0));
5914                                         emitSKPNZ;
5915                                         emitpcode(POC_BTFSC, popGet(AOP(left),0));
5916                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5917                                 }
5918                                 
5919                                 
5920                                 
5921                                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5922                                         pic14_emitcode(";XXX setb","c");
5923                                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5924                                         AOP(left)->aopu.aop_dir,tlbl->key+100);
5925                                 pic14_toBoolean(right);
5926                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5927                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5928                                         jmpTrueOrFalse(ifx, tlbl);
5929                                         goto release;
5930                                 } else {
5931                                         CLRC;
5932                                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5933                                 }
5934                         }
5935                 }
5936                 // bit = c
5937                 // val = c
5938                 if(size)
5939                         pic14_outBitC(result);
5940                 // if(bit | ...)
5941                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5942                         genIfxJump(ifx, "c");           
5943                 goto release ;
5944         }
5945
5946         // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5947         // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5948         if((AOP_TYPE(right) == AOP_LIT) &&
5949           (AOP_TYPE(result) == AOP_CRY) &&
5950           (AOP_TYPE(left) != AOP_CRY)){
5951                 if(lit){
5952                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5953                         // result = 1
5954                         if(size)
5955                                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5956                         else 
5957                                 continueIfTrue(ifx);
5958                         goto release;
5959                 } else {
5960                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5961                         // lit = 0, result = boolean(left)
5962                         if(size)
5963                                 pic14_emitcode(";XXX setb","c");
5964                         pic14_toBoolean(right);
5965                         if(size){
5966                                 symbol *tlbl = newiTempLabel(NULL);
5967                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5968                                 CLRC;
5969                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5970                         } else {
5971                                 genIfxJump (ifx,"a");
5972                                 goto release;
5973                         }
5974                 }
5975                 pic14_outBitC(result);
5976                 goto release ;
5977         }
5978
5979         /* if left is same as result */
5980         if(pic14_sameRegs(AOP(result),AOP(left))){
5981                 int know_W = -1;
5982                 for(;size--; offset++,lit>>=8) {
5983                         if(AOP_TYPE(right) == AOP_LIT){
5984                                 if((lit & 0xff) == 0)
5985                                         /*  or'ing with 0 has no effect */
5986                                         continue;
5987                                 else {
5988                                         int p = my_powof2(lit & 0xff);
5989                                         if(p>=0) {
5990                                                 /* only one bit is set in the literal, so use a bsf instruction */
5991                                                 emitpcode(POC_BSF,
5992                                                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5993                                         } else {
5994                                                 if(know_W != (int)(lit & 0xff))
5995                                                         emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5996                                                 know_W = lit & 0xff;
5997                                                 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5998                                         }
5999                                         
6000                                 }
6001                         } else {
6002                                 if (AOP_TYPE(left) == AOP_ACC) {
6003                                         emitpcode(POC_IORFW,  popGet(AOP(right),offset));
6004                                         pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6005                                 } else {        
6006                                         emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
6007                                         emitpcode(POC_IORWF,  popGet(AOP(left),offset));
6008                                         
6009                                         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6010                                         pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
6011                                         
6012                                 }
6013                         }
6014                 }
6015         } else {
6016                 // left & result in different registers
6017                 if(AOP_TYPE(result) == AOP_CRY){
6018                         // result = bit
6019                         // if(size), result in bit
6020                         // if(!size && ifx), conditional oper: if(left | right)
6021                         symbol *tlbl = newiTempLabel(NULL);
6022                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6023                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6024                         
6025                         
6026                         if(size)
6027                                 pic14_emitcode(";XXX setb","c");
6028                         while(sizer--){
6029                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6030                                 pic14_emitcode(";XXX orl","a,%s",
6031                                         aopGet(AOP(left),offset,FALSE,FALSE));
6032                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6033                                 offset++;
6034                         }
6035                         if(size){
6036                                 CLRC;
6037                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6038                                 pic14_outBitC(result);
6039                         } else if(ifx)
6040                                 jmpTrueOrFalse(ifx, tlbl);
6041                 } else for(;(size--);offset++){
6042                         // normal case
6043                         // result = left | right
6044                         if(AOP_TYPE(right) == AOP_LIT){
6045                                 int t = (lit >> (offset*8)) & 0x0FFL;
6046                                 switch(t) { 
6047                                 case 0x00:
6048                                         if (AOP_TYPE(left) != AOP_ACC) {
6049                                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
6050                                         }
6051                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6052                                         
6053                                         break;
6054                                 default:
6055                                         if (AOP_TYPE(left) == AOP_ACC) {
6056                                                 emitpcode(POC_IORLW,  popGetLit(t));
6057                                         } else {
6058                                                 emitpcode(POC_MOVLW,  popGetLit(t));
6059                                                 emitpcode(POC_IORFW,  popGet(AOP(left),offset));
6060                                         }
6061                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));        
6062                                 }
6063                                 continue;
6064                         }
6065                         
6066                         // faster than result <- left, anl result,right
6067                         // and better if result is SFR
6068                         if (AOP_TYPE(left) == AOP_ACC) {
6069                                 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6070                         } else {
6071                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6072                                 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6073                         }
6074                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6075                 }
6076         }
6077
6078 release :
6079         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6080         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6081         freeAsmop(result,NULL,ic,TRUE);     
6082 }
6083
6084 /*-----------------------------------------------------------------*/
6085 /* genXor - code for xclusive or                                   */
6086 /*-----------------------------------------------------------------*/
6087 static void genXor (iCode *ic, iCode *ifx)
6088 {
6089         operand *left, *right, *result;
6090         int size, offset=0;
6091         unsigned long lit = 0L;
6092         
6093         FENTRY;
6094         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6095         
6096         aopOp((left = IC_LEFT(ic)),ic,FALSE);
6097         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6098         aopOp((result=IC_RESULT(ic)),ic,TRUE);
6099         
6100         /* if left is a literal & right is not ||
6101         if left needs acc & right does not */
6102         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6103                 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6104                 operand *tmp = right ;
6105                 right = left;
6106                 left = tmp;
6107         }
6108         
6109         /* if result = right then exchange them */
6110         if(pic14_sameRegs(AOP(result),AOP(right))){
6111                 operand *tmp = right ;
6112                 right = left;
6113                 left = tmp;
6114         }
6115         
6116         /* if right is bit then exchange them */
6117         if (AOP_TYPE(right) == AOP_CRY &&
6118                 AOP_TYPE(left) != AOP_CRY){
6119                 operand *tmp = right ;
6120                 right = left;
6121                 left = tmp;
6122         }
6123         if(AOP_TYPE(right) == AOP_LIT)
6124                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6125         
6126         size = AOP_SIZE(result);
6127         
6128         // if(bit ^ yy)
6129         // xx = bit ^ yy;
6130         if (AOP_TYPE(left) == AOP_CRY){
6131                 if(AOP_TYPE(right) == AOP_LIT){
6132                         // c = bit & literal;
6133                         if(lit>>1){
6134                                 // lit>>1  != 0 => result = 1
6135                                 if(AOP_TYPE(result) == AOP_CRY){
6136                                         if(size)
6137                                         {emitpcode(POC_BSF,  popGet(AOP(result),offset));
6138                                         pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6139                                         else if(ifx)
6140                                                 continueIfTrue(ifx);
6141                                         goto release;
6142                                 }
6143                                 pic14_emitcode("setb","c");
6144                         } else{
6145                                 // lit == (0 or 1)
6146                                 if(lit == 0){
6147                                         // lit == 0, result = left
6148                                         if(size && pic14_sameRegs(AOP(result),AOP(left)))
6149                                                 goto release;
6150                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6151                                 } else{
6152                                         // lit == 1, result = not(left)
6153                                         if(size && pic14_sameRegs(AOP(result),AOP(left))){
6154                                                 emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
6155                                                 emitpcode(POC_XORWF,  popGet(AOP(result),offset));
6156                                                 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6157                                                 goto release;
6158                                         } else {
6159                                                 assert ( !"incomplete genXor" );
6160                                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6161                                                 pic14_emitcode("cpl","c");
6162                                         }
6163                                 }
6164                         }
6165                         
6166                 } else {
6167                         // right != literal
6168                         symbol *tlbl = newiTempLabel(NULL);
6169                         if (AOP_TYPE(right) == AOP_CRY){
6170                                 // c = bit ^ bit;
6171                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6172                         }
6173                         else{
6174                                 int sizer = AOP_SIZE(right);
6175                                 // c = bit ^ val
6176                                 // if val>>1 != 0, result = 1
6177                                 pic14_emitcode("setb","c");
6178                                 while(sizer){
6179                                         MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6180                                         if(sizer == 1)
6181                                                 // test the msb of the lsb
6182                                                 pic14_emitcode("anl","a,#0xfe");
6183                                         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6184                                         sizer--;
6185                                 }
6186                                 // val = (0,1)
6187                                 pic14_emitcode("rrc","a");
6188                         }
6189                         pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6190                         pic14_emitcode("cpl","c");
6191                         pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6192                 }
6193                 // bit = c
6194                 // val = c
6195                 if(size)
6196                         pic14_outBitC(result);
6197                 // if(bit | ...)
6198                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6199                         genIfxJump(ifx, "c");           
6200                 goto release ;
6201         }
6202         
6203         if(pic14_sameRegs(AOP(result),AOP(left))){
6204                 /* if left is same as result */
6205                 for(;size--; offset++) {
6206                         if(AOP_TYPE(right) == AOP_LIT){
6207                                 int t  = (lit >> (offset*8)) & 0x0FFL;
6208                                 if(t == 0x00L)
6209                                         continue;
6210                                 else
6211                                         if (IS_AOP_PREG(left)) {
6212                                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6213                                                 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6214                                                 aopPut(AOP(result),"a",offset);
6215                                         } else {
6216                                                 emitpcode(POC_MOVLW, popGetLit(t));
6217                                                 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6218                                                 pic14_emitcode("xrl","%s,%s",
6219                                                         aopGet(AOP(left),offset,FALSE,TRUE),
6220                                                         aopGet(AOP(right),offset,FALSE,FALSE));
6221                                         }
6222                         } else {
6223                                 if (AOP_TYPE(left) == AOP_ACC)
6224                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6225                                 else {
6226                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6227                                         emitpcode(POC_XORWF,popGet(AOP(left),offset));
6228                                         /*
6229                                         if (IS_AOP_PREG(left)) {
6230                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6231                                         aopPut(AOP(result),"a",offset);
6232                                         } else
6233                                         pic14_emitcode("xrl","%s,a",
6234                                         aopGet(AOP(left),offset,FALSE,TRUE));
6235                                         */
6236                                 }
6237                         }
6238                 }
6239         } else {
6240                 // left & result in different registers
6241                 if(AOP_TYPE(result) == AOP_CRY){
6242                         // result = bit
6243                         // if(size), result in bit
6244                         // if(!size && ifx), conditional oper: if(left ^ right)
6245                         symbol *tlbl = newiTempLabel(NULL);
6246                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6247                         if(size)
6248                                 pic14_emitcode("setb","c");
6249                         while(sizer--){
6250                                 if((AOP_TYPE(right) == AOP_LIT) &&
6251                                         (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6252                                         MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6253                                 } else {
6254                                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6255                                         pic14_emitcode("xrl","a,%s",
6256                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6257                                 }
6258                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6259                                 offset++;
6260                         }
6261                         if(size){
6262                                 CLRC;
6263                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6264                                 pic14_outBitC(result);
6265                         } else if(ifx)
6266                                 jmpTrueOrFalse(ifx, tlbl);
6267                 } else for(;(size--);offset++){
6268                         // normal case
6269                         // result = left & right
6270                         if(AOP_TYPE(right) == AOP_LIT){
6271                                 int t = (lit >> (offset*8)) & 0x0FFL;
6272                                 switch(t) { 
6273                                 case 0x00:
6274                                         if (AOP_TYPE(left) != AOP_ACC) {
6275                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6276                                         }
6277                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6278                                         pic14_emitcode("movf","%s,w",
6279                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6280                                         pic14_emitcode("movwf","%s",
6281                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6282                                         break;
6283                                 case 0xff:
6284                                         if (AOP_TYPE(left) == AOP_ACC) {
6285                                                 emitpcode(POC_XORLW, popGetLit(t));
6286                                         } else {
6287                                                 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6288                                         }
6289                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6290                                         break;
6291                                 default:
6292                                         if (AOP_TYPE(left) == AOP_ACC) {
6293                                                 emitpcode(POC_XORLW, popGetLit(t));
6294                                         } else {
6295                                                 emitpcode(POC_MOVLW, popGetLit(t));
6296                                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6297                                         }
6298                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6299                                         pic14_emitcode("movlw","0x%x",t);
6300                                         pic14_emitcode("xorwf","%s,w",
6301                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6302                                         pic14_emitcode("movwf","%s",
6303                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6304                                         
6305                                 }
6306                                 continue;
6307                         }
6308                         
6309                         // faster than result <- left, anl result,right
6310                         // and better if result is SFR
6311                         if (AOP_TYPE(left) == AOP_ACC) {
6312                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6313                         } else {
6314                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6315                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6316                         }
6317                         if ( AOP_TYPE(result) != AOP_ACC){
6318                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6319                         }
6320                 }
6321         }
6322         
6323 release :
6324         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6325         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6326         freeAsmop(result,NULL,ic,TRUE);     
6327 }
6328
6329 /*-----------------------------------------------------------------*/
6330 /* genInline - write the inline code out                           */
6331 /*-----------------------------------------------------------------*/
6332 static void genInline (iCode *ic)
6333 {
6334   char *buffer, *bp, *bp1;
6335
6336   FENTRY;
6337   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6338
6339   _G.inLine += (!options.asmpeep);
6340
6341   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6342   strcpy(buffer,IC_INLINE(ic));
6343
6344   /* emit each line as a code */
6345   while (*bp) {
6346     if (*bp == '\n') {
6347       *bp++ = '\0';
6348       
6349       if(*bp1)
6350         addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6351       bp1 = bp;
6352     } else {
6353       if (*bp == ':') {
6354         bp++;
6355         *bp = '\0';
6356         bp++;
6357
6358         /* print label, use this special format with NULL directive
6359          * to denote that the argument should not be indented with tab */
6360         addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6361
6362         bp1 = bp;
6363       } else
6364         bp++;
6365     }
6366   }
6367   if ((bp1 != bp) && *bp1)
6368     addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6369
6370   Safe_free(buffer);
6371
6372   _G.inLine -= (!options.asmpeep);
6373 }
6374
6375 /*-----------------------------------------------------------------*/
6376 /* genRRC - rotate right with carry                                */
6377 /*-----------------------------------------------------------------*/
6378 static void genRRC (iCode *ic)
6379 {
6380         operand *left , *result ;
6381         int size, offset = 0, same;
6382         
6383         FENTRY;
6384         /* rotate right with carry */
6385         left = IC_LEFT(ic);
6386         result=IC_RESULT(ic);
6387         aopOp (left,ic,FALSE);
6388         aopOp (result,ic,FALSE);
6389         
6390         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6391         
6392         same = pic14_sameRegs(AOP(result),AOP(left));
6393         
6394         size = AOP_SIZE(result);    
6395         
6396         /* get the lsb and put it into the carry */
6397         emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6398         
6399         offset = 0 ;
6400         
6401         while(size--) {
6402                 
6403                 if(same) {
6404                         emitpcode(POC_RRF, popGet(AOP(left),offset));
6405                 } else {
6406                         emitpcode(POC_RRFW, popGet(AOP(left),offset));
6407                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6408                 }
6409                 
6410                 offset++;
6411         }
6412         
6413         freeAsmop(left,NULL,ic,TRUE);
6414         freeAsmop(result,NULL,ic,TRUE);
6415 }
6416
6417 /*-----------------------------------------------------------------*/
6418 /* genRLC - generate code for rotate left with carry               */
6419 /*-----------------------------------------------------------------*/
6420 static void genRLC (iCode *ic)
6421 {    
6422         operand *left , *result ;
6423         int size, offset = 0;
6424         int same;
6425         
6426         FENTRY;
6427         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6428         /* rotate right with carry */
6429         left = IC_LEFT(ic);
6430         result=IC_RESULT(ic);
6431         aopOp (left,ic,FALSE);
6432         aopOp (result,ic,FALSE);
6433         
6434         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6435         
6436         same = pic14_sameRegs(AOP(result),AOP(left));
6437         
6438         /* move it to the result */
6439         size = AOP_SIZE(result);    
6440         
6441         /* get the msb and put it into the carry */
6442         emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6443         
6444         offset = 0 ;
6445         
6446         while(size--) {
6447                 
6448                 if(same) {
6449                         emitpcode(POC_RLF, popGet(AOP(left),offset));
6450                 } else {
6451                         emitpcode(POC_RLFW, popGet(AOP(left),offset));
6452                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6453                 }
6454                 
6455                 offset++;
6456         }
6457         
6458         
6459         freeAsmop(left,NULL,ic,TRUE);
6460         freeAsmop(result,NULL,ic,TRUE);
6461 }
6462
6463 /*-----------------------------------------------------------------*/
6464 /* genGetHbit - generates code get highest order bit               */
6465 /*-----------------------------------------------------------------*/
6466 static void genGetHbit (iCode *ic)
6467 {
6468         operand *left, *result;
6469         left = IC_LEFT(ic);
6470         result=IC_RESULT(ic);
6471         aopOp (left,ic,FALSE);
6472         aopOp (result,ic,FALSE);
6473         
6474         FENTRY;
6475         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6476         /* get the highest order byte into a */
6477         MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6478         if(AOP_TYPE(result) == AOP_CRY){
6479                 pic14_emitcode("rlc","a");
6480                 pic14_outBitC(result);
6481         }
6482         else{
6483                 pic14_emitcode("rl","a");
6484                 pic14_emitcode("anl","a,#0x01");
6485                 pic14_outAcc(result);
6486         }
6487         
6488         
6489         freeAsmop(left,NULL,ic,TRUE);
6490         freeAsmop(result,NULL,ic,TRUE);
6491 }
6492
6493 /*-----------------------------------------------------------------*/
6494 /* AccLsh - shift left accumulator by known count                  */
6495 /* MARK: pic14 always rotates through CARRY!                       */
6496 /*-----------------------------------------------------------------*/
6497 static void AccLsh (pCodeOp *pcop,int shCount)
6498 {
6499         FENTRY;
6500         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6501         shCount &= 0x0007;              // shCount : 0..7
6502         switch(shCount){
6503         case 0 :
6504                 return;
6505                 break;
6506         case 1 :
6507                 emitCLRC;
6508                 emitpcode(POC_RLF,pcop);
6509                 return;
6510                 break;
6511         case 2 :
6512                 emitpcode(POC_RLF,pcop);
6513                 emitpcode(POC_RLF,pcop);
6514                 break;
6515         case 3 :
6516                 emitpcode(POC_RLF,pcop);
6517                 emitpcode(POC_RLF,pcop);
6518                 emitpcode(POC_RLF,pcop);
6519                 break;
6520         case 4 :
6521                 emitpcode(POC_SWAPF,pcop);
6522                 break;
6523         case 5 :
6524                 emitpcode(POC_SWAPF,pcop);
6525                 emitpcode(POC_RLF,pcop);
6526                 break;
6527         case 6 :
6528                 emitpcode(POC_SWAPF,pcop);
6529                 emitpcode(POC_RLF,pcop);
6530                 emitpcode(POC_RLF,pcop);
6531                 break;
6532         case 7 :
6533                 emitpcode(POC_RRFW,pcop);
6534                 emitpcode(POC_RRF,pcop);
6535                 break;
6536         }
6537         /* clear invalid bits */
6538         emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6539         emitpcode(POC_ANDWF, pcop);
6540 }
6541
6542 /*-----------------------------------------------------------------*/
6543 /* AccRsh - shift right accumulator by known count                 */
6544 /* MARK: pic14 always rotates through CARRY!                       */
6545 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6546 /*            1: mask out invalid bits (zero-extend)               */
6547 /*            2: sign-extend result (pretty slow)                  */
6548 /*-----------------------------------------------------------------*/
6549 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6550 {
6551         FENTRY;
6552         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6553         shCount &= 0x0007;              // shCount : 0..7
6554         switch(shCount){
6555         case 0 :
6556                 return;
6557                 break;
6558         case 1 :
6559                 /* load sign if needed */
6560                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6561                 else if (mask_mode == 1) emitCLRC;
6562                 emitpcode(POC_RRF,pcop);
6563                 return;
6564                 break;
6565         case 2 :
6566                 /* load sign if needed */
6567                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6568                 emitpcode(POC_RRF,pcop);
6569                 /* load sign if needed */
6570                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6571                 emitpcode(POC_RRF,pcop);
6572                 if (mask_mode == 2) return;
6573                 break;
6574         case 3 :
6575                 /* load sign if needed */
6576                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6577                 emitpcode(POC_RRF,pcop);
6578                 /* load sign if needed */
6579                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6580                 emitpcode(POC_RRF,pcop);
6581                 /* load sign if needed */
6582                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6583                 emitpcode(POC_RRF,pcop);
6584                 if (mask_mode == 2) return;
6585                 break;
6586         case 4 :
6587                 emitpcode(POC_SWAPF,pcop);
6588                 break;
6589         case 5 :
6590                 emitpcode(POC_SWAPF,pcop);
6591                 emitpcode(POC_RRF,pcop);
6592                 break;
6593         case 6 :
6594                 emitpcode(POC_SWAPF,pcop);
6595                 emitpcode(POC_RRF,pcop);
6596                 emitpcode(POC_RRF,pcop);
6597                 break;
6598         case 7 :
6599                 if (mask_mode == 2)
6600                 {
6601                         /* load sign */
6602                         emitpcode(POC_RLFW,pcop);
6603                         emitpcode(POC_CLRF,pcop);
6604                         emitSKPNC;
6605                         emitpcode(POC_COMF,pcop);
6606                         return;
6607                 } else {
6608                         emitpcode(POC_RLFW,pcop);
6609                         emitpcode(POC_RLF,pcop);
6610                 }
6611                 break;
6612         }
6613
6614         if (mask_mode == 0)
6615         {
6616                 /* leave invalid bits undefined */
6617                 return;
6618         }
6619         
6620         /* clear invalid bits -- zero-extend */
6621         emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6622         emitpcode(POC_ANDWF, pcop);
6623
6624         if (mask_mode == 2) {
6625           /* sign-extend */
6626           emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6627           emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6628           emitpcode(POC_IORWF, pcop);
6629         }
6630 }
6631
6632 #if 0
6633 /*-----------------------------------------------------------------*/
6634 /* AccSRsh - signed right shift accumulator by known count                 */
6635 /*-----------------------------------------------------------------*/
6636 static void AccSRsh (int shCount)
6637 {
6638         symbol *tlbl ;
6639         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6640         if(shCount != 0){
6641                 if(shCount == 1){
6642                         pic14_emitcode("mov","c,acc.7");
6643                         pic14_emitcode("rrc","a");
6644                 } else if(shCount == 2){
6645                         pic14_emitcode("mov","c,acc.7");
6646                         pic14_emitcode("rrc","a");
6647                         pic14_emitcode("mov","c,acc.7");
6648                         pic14_emitcode("rrc","a");
6649                 } else {
6650                         tlbl = newiTempLabel(NULL);
6651                         /* rotate right accumulator */
6652                         AccRol(8 - shCount);
6653                         /* and kill the higher order bits */
6654                         pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6655                         pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6656                         pic14_emitcode("orl","a,#0x%02x",
6657                                 (unsigned char)~SRMask[shCount]);
6658                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6659                 }
6660         }
6661 }
6662
6663 /*-----------------------------------------------------------------*/
6664 /* shiftR1Left2Result - shift right one byte from left to result   */
6665 /*-----------------------------------------------------------------*/
6666 static void shiftR1Left2ResultSigned (operand *left, int offl,
6667                                                                           operand *result, int offr,
6668                                                                           int shCount)
6669 {
6670         int same;
6671         
6672         FENTRY;
6673         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6674         
6675         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6676         
6677         switch(shCount) {
6678         case 1:
6679                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6680                 if(same) 
6681                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6682                 else {
6683                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6684                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6685                 }
6686                 
6687                 break;
6688         case 2:
6689                 
6690                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6691                 if(same) 
6692                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6693                 else {
6694                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6695                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6696                 }
6697                 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6698                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6699                 
6700                 break;
6701                 
6702         case 3:
6703                 if(same)
6704                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6705                 else {
6706                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6707                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6708                 }
6709                 
6710                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6711                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6712                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6713                 
6714                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6715                 emitpcode(POC_IORLW, popGetLit(0xe0));
6716                 
6717                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6718                 break;
6719                 
6720         case 4:
6721                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6722                 emitpcode(POC_ANDLW,  popGetLit(0x0f));
6723                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6724                 emitpcode(POC_IORLW,  popGetLit(0xf0));
6725                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6726                 break;
6727         case 5:
6728                 if(same) {
6729                         emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6730                 } else {
6731                         emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6732                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6733                 }
6734                 emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6735                 emitpcode(POC_ANDLW,  popGetLit(0x07));
6736                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6737                 emitpcode(POC_IORLW,  popGetLit(0xf8));
6738                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6739                 break;
6740                 
6741         case 6:
6742                 if(same) {
6743                         emitpcode(POC_MOVLW, popGetLit(0x00));
6744                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6745                         emitpcode(POC_MOVLW, popGetLit(0xfe));
6746                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6747                         emitpcode(POC_IORLW, popGetLit(0x01));
6748                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6749                 } else {
6750                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6751                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6752                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6753                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6754                         emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6755                 }
6756                 break;
6757                 
6758         case 7:
6759                 if(same) {
6760                         emitpcode(POC_MOVLW, popGetLit(0x00));
6761                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6762                         emitpcode(POC_MOVLW, popGetLit(0xff));
6763                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6764                 } else {
6765                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6766                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6767                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6768                 }
6769                 
6770         default:
6771                 break;
6772         }
6773 }
6774
6775 /*-----------------------------------------------------------------*/
6776 /* shiftR1Left2Result - shift right one byte from left to result   */
6777 /*-----------------------------------------------------------------*/
6778 static void shiftR1Left2Result (operand *left, int offl,
6779                                                                 operand *result, int offr,
6780                                                                 int shCount, int sign)
6781 {
6782         int same;
6783         
6784         FENTRY;
6785         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6786         
6787         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6788         
6789         /* Copy the msb into the carry if signed. */
6790         if(sign) {
6791                 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6792                 return;
6793         }
6794         
6795         
6796         
6797         switch(shCount) {
6798         case 1:
6799                 emitCLRC;
6800                 if(same) 
6801                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6802                 else {
6803                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6804                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6805                 }
6806                 break;
6807         case 2:
6808                 emitCLRC;
6809                 if(same) {
6810                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6811                 } else {
6812                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6813                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6814                 }
6815                 emitCLRC;
6816                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6817                 
6818                 break;
6819         case 3:
6820                 if(same)
6821                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6822                 else {
6823                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6824                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6825                 }
6826                 
6827                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6828                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6829                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6830                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6831                 break;
6832                 
6833         case 4:
6834                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6835                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6836                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6837                 break;
6838                 
6839         case 5:
6840                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6841                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6842                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6843                 emitCLRC;
6844                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6845                 
6846                 break;
6847         case 6:
6848                 
6849                 emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6850                 emitpcode(POC_ANDLW, popGetLit(0x80));
6851                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6852                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6853                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6854                 break;
6855                 
6856         case 7:
6857                 
6858                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6859                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6860                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6861                 
6862                 break;
6863                 
6864         default:
6865                 break;
6866         }
6867 }
6868
6869 /*-----------------------------------------------------------------*/
6870 /* shiftL1Left2Result - shift left one byte from left to result    */
6871 /*-----------------------------------------------------------------*/
6872 static void shiftL1Left2Result (operand *left, int offl,
6873                                                                 operand *result, int offr, int shCount)
6874 {
6875         int same;
6876         
6877         //    char *l;
6878         FENTRY;
6879         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6880         
6881         same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6882         DEBUGpic14_emitcode ("; ***","same =  %d",same);
6883         //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6884         //    MOVA(l);
6885         /* shift left accumulator */
6886         //AccLsh(shCount); // don't comment out just yet...
6887         //    aopPut(AOP(result),"a",offr);
6888         
6889         switch(shCount) {
6890         case 1:
6891                 /* Shift left 1 bit position */
6892                 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6893                 if(same) {
6894                         emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6895                 } else {
6896                         emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6897                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6898                 }
6899                 break;
6900         case 2:
6901                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6902                 emitpcode(POC_ANDLW,popGetLit(0x7e));
6903                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6904                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6905                 break;
6906         case 3:
6907                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6908                 emitpcode(POC_ANDLW,popGetLit(0x3e));
6909                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6910                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6911                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6912                 break;
6913         case 4:
6914                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6915                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6916                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6917                 break;
6918         case 5:
6919                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6920                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6921                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6922                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6923                 break;
6924         case 6:
6925                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6926                 emitpcode(POC_ANDLW, popGetLit(0x30));
6927                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6928                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6929                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6930                 break;
6931         case 7:
6932                 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6933                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6934                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6935                 break;
6936                 
6937         default:
6938                 DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6939         }
6940         
6941 }
6942 #endif
6943
6944 /*-----------------------------------------------------------------*/
6945 /* movLeft2Result - move byte from left to result                  */
6946 /*-----------------------------------------------------------------*/
6947 static void movLeft2Result (operand *left, int offl,
6948                                                         operand *result, int offr)
6949 {
6950         char *l;
6951         FENTRY;
6952         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6953         if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6954                 l = aopGet(AOP(left),offl,FALSE,FALSE);
6955                 
6956                 if (*l == '@' && (IS_AOP_PREG(result))) {
6957                         pic14_emitcode("mov","a,%s",l);
6958                         aopPut(AOP(result),"a",offr);
6959                 } else {
6960                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6961                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6962                 }
6963         }
6964 }
6965
6966 /*-----------------------------------------------------------------*/
6967 /* shiftLeft_Left2ResultLit - shift left by known count            */
6968 /*-----------------------------------------------------------------*/
6969
6970 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6971 {
6972         int size, same, offr, i;
6973
6974         size = AOP_SIZE(left);
6975         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6976         
6977         same = pic14_sameRegs (AOP(left), AOP(result));
6978         
6979         offr = shCount / 8;
6980         shCount = shCount & 0x07;
6981
6982         size -= offr;
6983
6984         switch (shCount)
6985         {
6986         case 0: /* takes 0 or 2N cycles (for offr==0) */
6987                 if (!same || offr) {
6988                         for (i=size-1; i >= 0; i--)
6989                                 movLeft2Result (left, i, result, offr + i);
6990                 } // if
6991                 break;
6992                 
6993         case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6994                 if (same && offr) {
6995                         shiftLeft_Left2ResultLit (left, result, 8 * offr);
6996                         shiftLeft_Left2ResultLit (result, result, shCount);
6997                         return; /* prevent clearing result again */
6998                 } else {
6999                         emitCLRC;
7000                         for (i=0; i < size; i++) {
7001                                 if (same && !offr) {
7002                                         emitpcode (POC_RLF, popGet (AOP(left), i));
7003                                 } else {
7004                                         emitpcode (POC_RLFW, popGet (AOP(left), i));
7005                                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7006                                 } // if
7007                         } // for
7008                 } // if (offr)
7009                 break;
7010                 
7011         case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
7012                 /* works in-place/with offr as well */
7013                 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
7014                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7015                 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
7016
7017                 for (i = size - 2; i >= 0; i--)
7018                 {
7019                         emitpcode (POC_SWAPFW, popGet (AOP(left), i));
7020                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7021                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7022                         emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
7023                         emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
7024                 } // for i
7025                 break;
7026                 
7027         case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7028                 /* works in-place/with offr as well */
7029                 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7030                 for (i = size-2; i >= 0; i--) {
7031                         emitpcode (POC_RRFW, popGet (AOP(left), i));
7032                         emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7033                 } // for i
7034                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7035                 emitpcode (POC_RRF, popGet (AOP(result), offr));
7036                 break;
7037         
7038         default:
7039                 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7040                 shiftLeft_Left2ResultLit (result, result, 1);
7041                 return; /* prevent clearing result again */
7042                 break;
7043         } // switch
7044
7045         while (0 < offr--)
7046         {
7047                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7048         } // while
7049 }
7050
7051 /*-----------------------------------------------------------------*/
7052 /* shiftRight_Left2ResultLit - shift right by known count          */
7053 /*-----------------------------------------------------------------*/
7054
7055 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7056 {
7057         int size, same, offr, i;
7058
7059         size = AOP_SIZE(left);
7060         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7061         
7062         same = pic14_sameRegs (AOP(left), AOP(result));
7063         
7064         offr = shCount / 8;
7065         shCount = shCount & 0x07;
7066
7067         size -= offr;
7068
7069         if (size)
7070         {
7071                 switch (shCount)
7072                 {
7073                 case 0: /* takes 0 or 2N cycles (for offr==0) */
7074                         if (!same || offr) {
7075                                 for (i=0; i < size; i++)
7076                                         movLeft2Result (left, i + offr, result, i);
7077                         } // if
7078                         break;
7079                         
7080                 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7081                         emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7082                         if (same && offr) {
7083                                 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7084                                 shiftRight_Left2ResultLit (result, result, shCount, sign);
7085                                 return; /* prevent sign-extending result again */
7086                         } else {
7087                                 emitCLRC;
7088                                 if (sign) {
7089                                         emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7090                                         emitSETC;
7091                                 }
7092                                 for (i = size-1; i >= 0; i--) {
7093                                         if (same && !offr) {
7094                                                 emitpcode (POC_RRF, popGet (AOP(left), i));
7095                                         } else {
7096                                                 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7097                                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7098                                         }
7099                                 } // for i
7100                         } // if (offr)
7101                         break;
7102                         
7103                 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7104                         /* works in-place/with offr as well */
7105                         emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7106                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7107                         emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7108
7109                         for (i = 1; i < size; i++)
7110                         {
7111                                 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7112                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7113                                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7114                                 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7115                                 emitpcode (POC_XORWF, popGet (AOP(result), i));
7116                         } // for i
7117
7118                         if (sign)
7119                         {
7120                                 emitpcode (POC_MOVLW, popGetLit (0xF0));
7121                                 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7122                                 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7123                         } // if
7124                         break;
7125                         
7126                 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7127                         /* works in-place/with offr as well */
7128                         emitpcode (POC_RLFW, popGet (AOP(left), offr));
7129                         for (i = 0; i < size-1; i++) {
7130                                 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7131                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7132                         } // for i
7133                         emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7134                         if (!sign) {
7135                                 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7136                         } else {
7137                                 emitSKPNC;
7138                                 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7139                         }
7140                         break;
7141                 
7142                 default:
7143                         shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7144                         shiftRight_Left2ResultLit (result, result, 1, sign);
7145                         return; /* prevent sign extending result again */
7146                         break;
7147                 } // switch
7148         } // if
7149
7150         addSign (result, size, sign);
7151 }
7152
7153 #if 0
7154 /*-----------------------------------------------------------------*/
7155 /* shiftL2Left2Result - shift left two bytes from left to result   */
7156 /*-----------------------------------------------------------------*/
7157 static void shiftL2Left2Result (operand *left, int offl,
7158                                                                 operand *result, int offr, int shCount)
7159 {
7160         FENTRY;
7161         
7162         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7163         
7164         if(pic14_sameRegs(AOP(result), AOP(left))) {
7165                 switch(shCount) {
7166                 case 0:
7167                         break;
7168                 case 1:
7169                 case 2:
7170                 case 3:
7171                         
7172                         emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7173                         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7174                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7175                         
7176                         while(--shCount) {
7177                                 emitCLRC;
7178                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7179                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7180                         }
7181                         
7182                         break;
7183                 case 4:
7184                 case 5:
7185                         emitpcode(POC_MOVLW, popGetLit(0x0f));
7186                         emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7187                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7188                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7189                         emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7190                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7191                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7192                         if(shCount >=5) {
7193                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7194                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7195                         }
7196                         break;
7197                 case 6:
7198                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7199                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7200                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7201                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7202                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7203                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7204                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7205                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7206                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7207                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7208                         break;
7209                 case 7:
7210                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7211                         emitpcode(POC_RRFW, popGet(AOP(result),offr));
7212                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7213                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7214                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7215                 }
7216                 
7217         } else {
7218                 switch(shCount) {
7219                 case 0:
7220                         break;
7221                 case 1:
7222                 case 2:
7223                 case 3:
7224                 /* note, use a mov/add for the shift since the mov has a
7225                         chance of getting optimized out */
7226                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7227                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7228                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7229                         emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
7230                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7231                         
7232                         while(--shCount) {
7233                                 emitCLRC;
7234                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7235                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7236                         }
7237                         break;
7238                         
7239                 case 4:
7240                 case 5:
7241                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7242                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7243                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7244                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7245                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7246                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7247                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7248                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7249                         
7250                         
7251                         if(shCount == 5) {
7252                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7253                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7254                         }
7255                         break;
7256                 case 6:
7257                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7258                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7259                         emitpcode(POC_RRFW, popGet(AOP(result),offl));
7260                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
7261                         
7262                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7263                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7264                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7265                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7266                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7267                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7268                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7269                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7270                         break;
7271                 case 7:
7272                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7273                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7274                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7275                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7276                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7277                 }
7278         }
7279         
7280 }
7281
7282 /*-----------------------------------------------------------------*/
7283 /* shiftR2Left2Result - shift right two bytes from left to result  */
7284 /*-----------------------------------------------------------------*/
7285 static void shiftR2Left2Result (operand *left, int offl,
7286                                                                 operand *result, int offr,
7287                                                                 int shCount, int sign)
7288 {
7289         int same=0;
7290         
7291         FENTRY;
7292         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7293         same = pic14_sameRegs(AOP(result), AOP(left));
7294         
7295         if(same && ((offl + MSB16) == offr)){
7296                 same=1;
7297                 /* don't crash result[offr] */
7298                 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7299                 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7300         }
7301         /* else {
7302         movLeft2Result(left,offl, result, offr);
7303         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7304         }
7305         */
7306         /* a:x >> shCount (x = lsb(result))*/
7307         /*
7308         if(sign)
7309         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7310         else {
7311         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7312         */
7313         switch(shCount) {
7314         case 0:
7315                 break;
7316         case 1:
7317         case 2:
7318         case 3:
7319                 if(sign)
7320                         emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7321                 else
7322                         emitCLRC;
7323                 
7324                 if(same) {
7325                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7326                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7327                 } else {
7328                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7329                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7330                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7331                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7332                 }
7333                 
7334                 while(--shCount) {
7335                         if(sign)
7336                                 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7337                         else
7338                                 emitCLRC;
7339                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7340                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7341                 }
7342                 break;
7343         case 4:
7344         case 5:
7345                 if(same) {
7346                         
7347                         emitpcode(POC_MOVLW, popGetLit(0xf0));
7348                         emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7349                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7350                         
7351                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7352                         emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7353                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7354                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7355                 } else {
7356                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7357                         emitpcode(POC_ANDLW, popGetLit(0x0f));
7358                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7359                         
7360                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7361                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7362                         emitpcode(POC_ANDLW, popGetLit(0xf0));
7363                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7364                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7365                 }
7366                 
7367                 if(shCount >=5) {
7368                         emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7369                         emitpcode(POC_RRF, popGet(AOP(result),offr));
7370                 }
7371                 
7372                 if(sign) {
7373                         emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7374                         emitpcode(POC_BTFSC, 
7375                                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7376                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7377                 }
7378                 
7379                 break;
7380                 
7381         case 6:
7382                 if(same) {
7383                         
7384                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7385                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7386                         
7387                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7388                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7389                         emitpcode(POC_RLFW, popGet(AOP(result),offr));
7390                         emitpcode(POC_ANDLW,popGetLit(0x03));
7391                         if(sign) {
7392                                 emitpcode(POC_BTFSC, 
7393                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7394                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7395                         }
7396                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7397                         emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7398                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7399                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7400                 } else {
7401                         emitpcode(POC_RLFW, popGet(AOP(left),offl));
7402                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7403                         emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7404                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7405                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7406                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7407                         emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7408                         emitpcode(POC_ANDLW,popGetLit(0x03));
7409                         if(sign) {
7410                                 emitpcode(POC_BTFSC, 
7411                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7412                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7413                         }
7414                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7415                         //emitpcode(POC_RLF,  popGet(AOP(result),offr));
7416                         
7417                         
7418                 }
7419                 
7420                 break;
7421         case 7:
7422                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7423                 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7424                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7425                 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7426                 if(sign) {
7427                         emitSKPNC;
7428                         emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7429                 } else 
7430                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7431   }
7432 }
7433
7434 /*-----------------------------------------------------------------*/
7435 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7436 /*-----------------------------------------------------------------*/
7437 static void shiftLLeftOrResult (operand *left, int offl,
7438                                                                 operand *result, int offr, int shCount)
7439 {
7440         FENTRY;
7441         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7442         
7443         /* shift left accumulator */
7444         AccLsh(left,offl,shCount);
7445         /* or with result */
7446         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7447         assert ( !"broken (modifies left, fails for left==result))" );
7448 }
7449
7450 /*-----------------------------------------------------------------*/
7451 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7452 /*-----------------------------------------------------------------*/
7453 static void shiftRLeftOrResult (operand *left, int offl,
7454                                                                 operand *result, int offr, int shCount)
7455 {
7456         FENTRY;
7457         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7458         
7459         /* shift right accumulator */
7460         AccRsh(left,offl,shCount);
7461         /* or with result */
7462         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7463         assert ( !"broken (modifies left, fails for left==result))" );
7464 }
7465
7466 /*-----------------------------------------------------------------*/
7467 /* genlshOne - left shift a one byte quantity by known count       */
7468 /*-----------------------------------------------------------------*/
7469 static void genlshOne (operand *result, operand *left, int shCount)
7470 {       
7471         FENTRY;
7472         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7473         shiftL1Left2Result(left, LSB, result, LSB, shCount);
7474 }
7475
7476 /*-----------------------------------------------------------------*/
7477 /* genlshTwo - left shift two bytes by known amount != 0           */
7478 /*-----------------------------------------------------------------*/
7479 static void genlshTwo (operand *result,operand *left, int shCount)
7480 {
7481         int size;
7482         
7483         FENTRY;
7484         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7485         size = pic14_getDataSize(result);
7486         
7487         /* if shCount >= 8 */
7488         if (shCount >= 8) {
7489                 shCount -= 8 ;
7490                 
7491                 if (size > 1){
7492                         if (shCount)
7493                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7494                         else 
7495                                 movLeft2Result(left, LSB, result, MSB16);
7496                 }
7497                 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7498         }
7499         
7500         /*  1 <= shCount <= 7 */
7501         else {  
7502                 if(size == 1)
7503                         shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7504                 else 
7505                         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7506         }
7507 }
7508
7509 /*-----------------------------------------------------------------*/
7510 /* shiftLLong - shift left one long from left to result            */
7511 /* offl = LSB or MSB16                                             */
7512 /*-----------------------------------------------------------------*/
7513 static void shiftLLong (operand *left, operand *result, int offr )
7514 {
7515         char *l;
7516         int size = AOP_SIZE(result);
7517         
7518         FENTRY;
7519         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7520         if(size >= LSB+offr){
7521                 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7522                 MOVA(l);
7523                 pic14_emitcode("add","a,acc");
7524                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7525                         size >= MSB16+offr && offr != LSB )
7526                         pic14_emitcode("xch","a,%s",
7527                         aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7528                 else      
7529                         aopPut(AOP(result),"a",LSB+offr);
7530         }
7531         
7532         if(size >= MSB16+offr){
7533                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7534                         l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7535                         MOVA(l);
7536                 }
7537                 pic14_emitcode("rlc","a");
7538                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7539                         size >= MSB24+offr && offr != LSB)
7540                         pic14_emitcode("xch","a,%s",
7541                         aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7542                 else      
7543                         aopPut(AOP(result),"a",MSB16+offr);
7544         }
7545         
7546         if(size >= MSB24+offr){
7547                 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7548                         l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7549                         MOVA(l);
7550                 }
7551                 pic14_emitcode("rlc","a");
7552                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7553                         size >= MSB32+offr && offr != LSB )
7554                         pic14_emitcode("xch","a,%s",
7555                         aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7556                 else      
7557                         aopPut(AOP(result),"a",MSB24+offr);
7558         }
7559         
7560         if(size > MSB32+offr){
7561                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7562                         l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7563                         MOVA(l);  
7564                 }
7565                 pic14_emitcode("rlc","a");
7566                 aopPut(AOP(result),"a",MSB32+offr);
7567         }
7568         if(offr != LSB)
7569                 aopPut(AOP(result),zero,LSB);       
7570 }
7571
7572 /*-----------------------------------------------------------------*/
7573 /* genlshFour - shift four byte by a known amount != 0             */
7574 /*-----------------------------------------------------------------*/
7575 static void genlshFour (operand *result, operand *left, int shCount)
7576 {
7577         int size;
7578         
7579         FENTRY;
7580         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7581         size = AOP_SIZE(result);
7582         
7583         /* if shifting more that 3 bytes */
7584         if (shCount >= 24 ) {
7585                 shCount -= 24;
7586                 if (shCount)
7587                 /* lowest order of left goes to the highest
7588                 order of the destination */
7589                 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7590                 else
7591                         movLeft2Result(left, LSB, result, MSB32);
7592                 aopPut(AOP(result),zero,LSB);
7593                 aopPut(AOP(result),zero,MSB16);
7594                 aopPut(AOP(result),zero,MSB32);
7595                 return;
7596         }
7597         
7598         /* more than two bytes */
7599         else if ( shCount >= 16 ) {
7600                 /* lower order two bytes goes to higher order two bytes */
7601                 shCount -= 16;
7602                 /* if some more remaining */
7603                 if (shCount)
7604                         shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7605                 else {
7606                         movLeft2Result(left, MSB16, result, MSB32);
7607                         movLeft2Result(left, LSB, result, MSB24);
7608                 }
7609                 aopPut(AOP(result),zero,MSB16);
7610                 aopPut(AOP(result),zero,LSB);
7611                 return;
7612         }    
7613         
7614         /* if more than 1 byte */
7615         else if ( shCount >= 8 ) {
7616                 /* lower order three bytes goes to higher order  three bytes */
7617                 shCount -= 8;
7618                 if(size == 2){
7619                         if(shCount)
7620                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7621                         else
7622                                 movLeft2Result(left, LSB, result, MSB16);
7623                 }
7624                 else{   /* size = 4 */
7625                         if(shCount == 0){
7626                                 movLeft2Result(left, MSB24, result, MSB32);
7627                                 movLeft2Result(left, MSB16, result, MSB24);
7628                                 movLeft2Result(left, LSB, result, MSB16);
7629                                 aopPut(AOP(result),zero,LSB);
7630                         }
7631                         else if(shCount == 1)
7632                                 shiftLLong(left, result, MSB16);
7633                         else{
7634                                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7635                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7636                                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7637                                 aopPut(AOP(result),zero,LSB);
7638                         }
7639                 }
7640         }
7641         
7642         /* 1 <= shCount <= 7 */
7643         else if(shCount <= 2){
7644                 shiftLLong(left, result, LSB);
7645                 if(shCount == 2)
7646                         shiftLLong(result, result, LSB);
7647         }
7648         /* 3 <= shCount <= 7, optimize */
7649         else{
7650                 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7651                 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7652                 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7653         }
7654 }
7655 #endif
7656
7657 #if 0
7658 /*-----------------------------------------------------------------*/
7659 /* genLeftShiftLiteral - left shifting by known count              */
7660 /*-----------------------------------------------------------------*/
7661 static void genLeftShiftLiteral (operand *left,
7662                                                                  operand *right,
7663                                                                  operand *result,
7664                                                                  iCode *ic)
7665 {    
7666         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7667         //int size;
7668         
7669         FENTRY;
7670         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7671         freeAsmop(right,NULL,ic,TRUE);
7672         
7673         aopOp(left,ic,FALSE);
7674         aopOp(result,ic,FALSE);
7675
7676         size = getSize(operandType(result));
7677         
7678 #if VIEW_SIZE
7679         pic14_emitcode("; shift left ","result %d, left %d",size,
7680                 AOP_SIZE(left));
7681 #endif
7682         
7683         /* I suppose that the left size >= result size */
7684         if(shCount == 0){
7685                 while(size--){
7686                         movLeft2Result(left, size, result, size);
7687                 }
7688         }
7689         
7690         else if(shCount >= (size * 8))
7691                 while(size--)
7692                         aopPut(AOP(result),zero,size);
7693                 else{
7694                         switch (size) {
7695                         case 1:
7696                                 genlshOne (result,left,shCount);
7697                                 break;
7698                                 
7699                         case 2:
7700                         case 3:
7701                                 genlshTwo (result,left,shCount);
7702                                 break;
7703                                 
7704                         case 4:
7705                                 genlshFour (result,left,shCount);
7706                                 break;
7707                         }
7708                 }
7709                 freeAsmop(left,NULL,ic,TRUE);
7710                 freeAsmop(result,NULL,ic,TRUE);
7711 }
7712 #endif
7713
7714 /*-----------------------------------------------------------------*
7715 * genMultiAsm - repeat assembly instruction for size of register.
7716 * if endian == 1, then the high byte (i.e base address + size of 
7717 * register) is used first else the low byte is used first;
7718 *-----------------------------------------------------------------*/
7719 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7720 {
7721         
7722         int offset = 0;
7723         
7724         FENTRY;
7725         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7726         
7727         if(!reg)
7728                 return;
7729         
7730         if(!endian) {
7731                 endian = 1;
7732         } else {
7733                 endian = -1;
7734                 offset = size-1;
7735         }
7736         
7737         while(size--) {
7738                 emitpcode(poc,    popGet(AOP(reg),offset));
7739                 offset += endian;
7740         }
7741         
7742 }
7743
7744 #if 0
7745 /*-----------------------------------------------------------------*/
7746 /* genLeftShift - generates code for left shifting                 */
7747 /*-----------------------------------------------------------------*/
7748 static void genLeftShift (iCode *ic)
7749 {
7750         operand *left,*right, *result;
7751         int size, offset;
7752         unsigned long lit = 0L;
7753         char *l;
7754         symbol *tlbl , *tlbl1;
7755         pCodeOp *pctemp;
7756         
7757         FENTRY;
7758         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7759         
7760         right = IC_RIGHT(ic);
7761         left  = IC_LEFT(ic);
7762         result = IC_RESULT(ic);
7763         
7764         aopOp(right,ic,FALSE);
7765         aopOp(left,ic,FALSE);
7766         aopOp(result,ic,FALSE);
7767         
7768         
7769         /* if the shift count is known then do it 
7770         as efficiently as possible */
7771         if (AOP_TYPE(right) == AOP_LIT) {
7772                 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7773                 return ;
7774         }
7775         
7776         /* shift count is unknown then we have to form 
7777         a loop get the loop count in B : Note: we take
7778         only the lower order byte since shifting
7779         more that 32 bits make no sense anyway, ( the
7780         largest size of an object can be only 32 bits ) */  
7781         
7782         /* this code fails for RIGHT == RESULT */
7783         assert (!pic14_sameRegs (AOP(right), AOP(result)));
7784         
7785         /* now move the left to the result if they are not the
7786         same */
7787         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7788                 AOP_SIZE(result) > 1) {
7789                 
7790                 size = AOP_SIZE(result);
7791                 offset=0;
7792                 while (size--) {
7793                         l = aopGet(AOP(left),offset,FALSE,TRUE);
7794                         if (*l == '@' && (IS_AOP_PREG(result))) {
7795                                 
7796                                 pic14_emitcode("mov","a,%s",l);
7797                                 aopPut(AOP(result),"a",offset);
7798                         } else {
7799                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7800                                 emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7801                                 //aopPut(AOP(result),l,offset);
7802                         }
7803                         offset++;
7804                 }
7805         }
7806         
7807         if(AOP_TYPE(left) == AOP_LIT)
7808                 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7809
7810         size = AOP_SIZE(result);
7811         
7812         /* if it is only one byte then */
7813         if (size == 1) {
7814                 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7815                         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7816                         emitpcode(POC_ANDLW,  popGetLit(0xf0));
7817                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7818                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7819                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7820                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7821                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7822                         emitpcode(POC_RLFW,   popGet(AOP(result),0));
7823                         emitpcode(POC_ANDLW,  popGetLit(0xfe));
7824                         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7825                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7826                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7827                 } else {
7828                         
7829                         tlbl = newiTempLabel(NULL);
7830                         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7831                                 mov2w (AOP(left), 0);
7832                                 emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7833                         }
7834                         
7835                         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7836                         emitpcode(POC_RRF,    popGet(AOP(result),0));
7837                         emitpLabel(tlbl->key);
7838                         emitpcode(POC_RLF,    popGet(AOP(result),0));
7839                         emitpcode(POC_ADDLW,  popGetLit(1));
7840                         emitSKPC;
7841                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7842                 }
7843                 goto release ;
7844         }
7845         
7846         if (pic14_sameRegs(AOP(left),AOP(result))) {
7847                 
7848                 tlbl = newiTempLabel(NULL);
7849                 emitpcode(POC_COMFW,  popGet(AOP(right),0));
7850                 genMultiAsm(POC_RRF, result, size,1);
7851                 emitpLabel(tlbl->key);
7852                 genMultiAsm(POC_RLF, result, size,0);
7853                 emitpcode(POC_ADDLW,  popGetLit(1));
7854                 emitSKPC;
7855                 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7856                 goto release;
7857         }
7858         
7859         //tlbl = newiTempLabel(NULL);
7860         //offset = 0 ;   
7861         //tlbl1 = newiTempLabel(NULL);
7862         
7863         //reAdjustPreg(AOP(result));    
7864         
7865         //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7866         //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7867         //l = aopGet(AOP(result),offset,FALSE,FALSE);
7868         //MOVA(l);
7869         //pic14_emitcode("add","a,acc");         
7870         //aopPut(AOP(result),"a",offset++);
7871         //while (--size) {
7872         //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7873         //  MOVA(l);
7874         //  pic14_emitcode("rlc","a");         
7875         //  aopPut(AOP(result),"a",offset++);
7876         //}
7877         //reAdjustPreg(AOP(result));
7878         
7879         //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7880         //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7881         
7882         
7883         tlbl = newiTempLabel(NULL);
7884         tlbl1= newiTempLabel(NULL);
7885         
7886         size = AOP_SIZE(result);
7887         offset = 1;
7888         
7889         pctemp = popGetTempReg();  /* grab a temporary working register. */
7890         
7891         emitpcode(POC_MOVFW, popGet(AOP(right),0));
7892         
7893         /* offset should be 0, 1 or 3 */
7894         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7895         emitSKPNZ;
7896         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7897         
7898         emitpcode(POC_MOVWF, pctemp);
7899         
7900         
7901         emitpLabel(tlbl->key);
7902         
7903         emitCLRC;
7904         emitpcode(POC_RLF,  popGet(AOP(result),0));
7905         while(--size)
7906                 emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7907         
7908         emitpcode(POC_DECFSZ,  pctemp);
7909         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7910         emitpLabel(tlbl1->key);
7911         
7912         popReleaseTempReg(pctemp);
7913         
7914         
7915 release:
7916         freeAsmop (right,NULL,ic,TRUE);
7917         freeAsmop(left,NULL,ic,TRUE);
7918         freeAsmop(result,NULL,ic,TRUE);
7919 }
7920 #endif
7921
7922 #if 0
7923 /*-----------------------------------------------------------------*/
7924 /* genrshOne - right shift a one byte quantity by known count      */
7925 /*-----------------------------------------------------------------*/
7926 static void genrshOne (operand *result, operand *left,
7927                                            int shCount, int sign)
7928 {
7929         FENTRY;
7930         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7931         shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7932 }
7933
7934 /*-----------------------------------------------------------------*/
7935 /* genrshTwo - right shift two bytes by known amount != 0          */
7936 /*-----------------------------------------------------------------*/
7937 static void genrshTwo (operand *result,operand *left,
7938                                            int shCount, int sign)
7939 {
7940         FENTRY;
7941         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7942         /* if shCount >= 8 */
7943         if (shCount >= 8) {
7944                 shCount -= 8 ;
7945                 if (shCount)
7946                         shiftR1Left2Result(left, MSB16, result, LSB,
7947                         shCount, sign);
7948                 else
7949                         movLeft2Result(left, MSB16, result, LSB);
7950                 
7951                 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7952                 
7953                 if(sign) {
7954                         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7955                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7956                 }
7957         }
7958         
7959         /*  1 <= shCount <= 7 */
7960         else
7961                 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7962 }
7963
7964 /*-----------------------------------------------------------------*/
7965 /* shiftRLong - shift right one long from left to result           */
7966 /* offl = LSB or MSB16                                             */
7967 /*-----------------------------------------------------------------*/
7968 static void shiftRLong (operand *left, int offl,
7969                                                 operand *result, int sign)
7970 {
7971         int size, same;
7972         
7973         FENTRY;
7974         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7975         
7976         size = AOP_SIZE(left);
7977         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7978         
7979         if (sign)
7980                 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7981         else
7982                 emitCLRC;
7983
7984         assert (offl >= 0 && offl < size);
7985
7986         same = pic14_sameRegs (AOP(left), AOP(result));
7987
7988         /* perform the shift */
7989         while (size--)
7990         {
7991                 if (same && !offl) {
7992                         emitpcode (POC_RRF, popGet (AOP(result), size));
7993                 } else {
7994                         emitpcode (POC_RRFW, popGet (AOP(left), size));
7995                         emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7996                 }
7997         } // while
7998
7999         addSign (result, AOP_SIZE(left) - offl, sign);
8000 }
8001
8002 /*-----------------------------------------------------------------*/
8003 /* genrshFour - shift four byte by a known amount != 0             */
8004 /*-----------------------------------------------------------------*/
8005 static void genrshFour (operand *result, operand *left,
8006                                                 int shCount, int sign)
8007 {
8008         FENTRY;
8009         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8010         /* if shifting more that 3 bytes */
8011         if(shCount >= 24 ) {
8012                 shCount -= 24;
8013                 if(shCount)
8014                         shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8015                 else
8016                         movLeft2Result(left, MSB32, result, LSB);
8017                 
8018                 addSign(result, MSB16, sign);
8019         }
8020         else if(shCount >= 16){
8021                 shCount -= 16;
8022                 if(shCount)
8023                         shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8024                 else{
8025                         movLeft2Result(left, MSB24, result, LSB);
8026                         movLeft2Result(left, MSB32, result, MSB16);
8027                 }
8028                 addSign(result, MSB24, sign);
8029         }
8030         else if(shCount >= 8){
8031                 shCount -= 8;
8032                 if(shCount == 1)
8033                         shiftRLong(left, MSB16, result, sign);
8034                 else if(shCount == 0){
8035                         movLeft2Result(left, MSB16, result, LSB);
8036                         movLeft2Result(left, MSB24, result, MSB16);
8037                         movLeft2Result(left, MSB32, result, MSB24);
8038                         addSign(result, MSB32, sign);
8039                 }
8040                 else{
8041                         shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8042                         shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8043                         /* the last shift is signed */
8044                         shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8045                         addSign(result, MSB32, sign);
8046                 }
8047         }
8048         else{   /* 1 <= shCount <= 7 */
8049                 if(shCount <= 2){
8050                         shiftRLong(left, LSB, result, sign);
8051                         if(shCount == 2)
8052                                 shiftRLong(result, LSB, result, sign);
8053                 }
8054                 else{
8055                         shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8056                         shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8057                         shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8058                 }
8059         }
8060 }
8061
8062 /*-----------------------------------------------------------------*/
8063 /* genRightShiftLiteral - right shifting by known count            */
8064 /*-----------------------------------------------------------------*/
8065 static void genRightShiftLiteral (operand *left,
8066                                                                   operand *right,
8067                                                                   operand *result,
8068                                                                   iCode *ic,
8069                                                                   int sign)
8070 {    
8071         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8072         int lsize,res_size;
8073         
8074         FENTRY;
8075         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8076         freeAsmop(right,NULL,ic,TRUE);
8077         
8078         aopOp(left,ic,FALSE);
8079         aopOp(result,ic,FALSE);
8080         
8081 #if VIEW_SIZE
8082         pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8083                 AOP_SIZE(left));
8084 #endif
8085         
8086         lsize = pic14_getDataSize(left);
8087         res_size = pic14_getDataSize(result);
8088         /* test the LEFT size !!! */
8089         
8090         /* I suppose that the left size >= result size */
8091         if(shCount == 0){
8092                 while(res_size--)
8093                         movLeft2Result(left, res_size, result, res_size);
8094         }
8095         
8096         else if(shCount >= (lsize * 8)){
8097                 
8098                 if(res_size == 1) {
8099                         emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8100                         if(sign) {
8101                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8102                                 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8103                         }
8104                 } else {
8105                         
8106                         if(sign) {
8107                                 emitpcode(POC_MOVLW, popGetLit(0));
8108                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8109                                 emitpcode(POC_MOVLW, popGetLit(0xff));
8110                                 while(res_size--)
8111                                         emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8112                                 
8113                         } else {
8114                                 
8115                                 while(res_size--)
8116                                         emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8117                         }
8118                 }
8119         } else {
8120                 
8121                 switch (res_size) {
8122                 case 1:
8123                         genrshOne (result,left,shCount,sign);
8124                         break;
8125                         
8126                 case 2:
8127                         genrshTwo (result,left,shCount,sign);
8128                         break;
8129                         
8130                 case 4:
8131                         genrshFour (result,left,shCount,sign);
8132                         break;
8133                 default :
8134                         break;
8135                 }
8136                 
8137         }
8138
8139         freeAsmop(left,NULL,ic,TRUE);
8140         freeAsmop(result,NULL,ic,TRUE);
8141 }
8142 #endif
8143
8144 #if 0
8145 /*-----------------------------------------------------------------*/
8146 /* genSignedRightShift - right shift of signed number              */
8147 /*-----------------------------------------------------------------*/
8148 static void genSignedRightShift (iCode *ic)
8149 {
8150         operand *right, *left, *result;
8151         int size, offset;
8152         //  char *l;
8153         symbol *tlbl, *tlbl1 ;
8154         pCodeOp *pctemp;
8155         
8156         //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8157         
8158         /* we do it the hard way put the shift count in b
8159         and loop thru preserving the sign */
8160         FENTRY;
8161         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8162         
8163         right = IC_RIGHT(ic);
8164         left  = IC_LEFT(ic);
8165         result = IC_RESULT(ic);
8166         
8167         aopOp(right,ic,FALSE);  
8168         aopOp(left,ic,FALSE);
8169         aopOp(result,ic,FALSE);
8170         
8171         
8172         if ( AOP_TYPE(right) == AOP_LIT) {
8173                 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8174                 //genRightShiftLiteral (left,right,result,ic,1);
8175                 return ;
8176         }
8177         /* shift count is unknown then we have to form 
8178         a loop get the loop count in B : Note: we take
8179         only the lower order byte since shifting
8180         more that 32 bits make no sense anyway, ( the
8181         largest size of an object can be only 32 bits ) */  
8182         
8183         //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8184         //pic14_emitcode("inc","b");
8185         //freeAsmop (right,NULL,ic,TRUE);
8186         //aopOp(left,ic,FALSE);
8187         //aopOp(result,ic,FALSE);
8188         
8189         /* now move the left to the result if they are not the
8190         same */
8191         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
8192                 AOP_SIZE(result) > 1) {
8193                 
8194                 size = AOP_SIZE(result);
8195                 offset=0;
8196                 while (size--) { 
8197                         /*
8198                         l = aopGet(AOP(left),offset,FALSE,TRUE);
8199                         if (*l == '@' && IS_AOP_PREG(result)) {
8200                                 pic14_emitcode("mov","a,%s",l);
8201                                 aopPut(AOP(result),"a",offset);
8202                         } else
8203                         aopPut(AOP(result),l,offset);
8204                         */
8205                         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
8206                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
8207                         
8208                         offset++;
8209                 }
8210         }
8211         
8212         /* mov the highest order bit to OVR */    
8213         tlbl = newiTempLabel(NULL);
8214         tlbl1= newiTempLabel(NULL);
8215         
8216         size = AOP_SIZE(result);
8217         offset = size - 1;
8218         
8219         pctemp = popGetTempReg();  /* grab a temporary working register. */
8220         
8221         emitpcode(POC_MOVFW, popGet(AOP(right),0));
8222         
8223         /* offset should be 0, 1 or 3 */
8224         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8225         emitSKPNZ;
8226         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
8227         
8228         emitpcode(POC_MOVWF, pctemp);
8229         
8230         
8231         emitpLabel(tlbl->key);
8232         
8233         emitpcode(POC_RLFW,  popGet(AOP(result),offset));
8234         emitpcode(POC_RRF,   popGet(AOP(result),offset));
8235         
8236         while(--size) {
8237                 emitpcode(POC_RRF,   popGet(AOP(result),--offset));
8238         }
8239         
8240         emitpcode(POC_DECFSZ,  pctemp);
8241         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8242         emitpLabel(tlbl1->key);
8243         
8244         popReleaseTempReg(pctemp);
8245 #if 0
8246         size = AOP_SIZE(result);
8247         offset = size - 1;
8248         pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8249         pic14_emitcode("rlc","a");
8250         pic14_emitcode("mov","ov,c");
8251         /* if it is only one byte then */
8252         if (size == 1) {
8253                 l = aopGet(AOP(left),0,FALSE,FALSE);
8254                 MOVA(l);
8255                 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8256                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8257                 pic14_emitcode("mov","c,ov");
8258                 pic14_emitcode("rrc","a");
8259                 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8260                 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8261                 aopPut(AOP(result),"a",0);
8262                 goto release ;
8263         }
8264         
8265         reAdjustPreg(AOP(result));
8266         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8267         pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
8268         pic14_emitcode("mov","c,ov");
8269         while (size--) {
8270                 l = aopGet(AOP(result),offset,FALSE,FALSE);
8271                 MOVA(l);
8272                 pic14_emitcode("rrc","a");         
8273                 aopPut(AOP(result),"a",offset--);
8274         }
8275         reAdjustPreg(AOP(result));
8276         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8277         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8278         
8279 release:
8280 #endif
8281         
8282         freeAsmop(left,NULL,ic,TRUE);
8283         freeAsmop(result,NULL,ic,TRUE);
8284         freeAsmop(right,NULL,ic,TRUE);
8285 }
8286 #endif
8287
8288 /*-----------------------------------------------------------------*/
8289 /* loadSignToC - load the operand's sign bit into CARRY            */
8290 /*-----------------------------------------------------------------*/
8291
8292 static void loadSignToC (operand *op)
8293 {
8294         FENTRY;
8295         assert (op && AOP(op) && AOP_SIZE(op));
8296
8297         emitCLRC;
8298         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8299         emitSETC;
8300 }
8301
8302 /*-----------------------------------------------------------------*/
8303 /* genRightShift - generate code for right shifting                */
8304 /*-----------------------------------------------------------------*/
8305 static void genGenericShift (iCode *ic, int shiftRight)
8306 {
8307         operand *right, *left, *result;
8308         sym_link *retype ;
8309         int size;
8310         symbol *tlbl, *tlbl1, *inverselbl;
8311         
8312         FENTRY;
8313         /* if signed then we do it the hard way preserve the
8314         sign bit moving it inwards */
8315         retype = getSpec(operandType(IC_RESULT(ic)));
8316         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8317         
8318         /* signed & unsigned types are treated the same : i.e. the
8319         signed is NOT propagated inwards : quoting from the
8320         ANSI - standard : "for E1 >> E2, is equivalent to division
8321         by 2**E2 if unsigned or if it has a non-negative value,
8322         otherwise the result is implementation defined ", MY definition
8323         is that the sign does not get propagated */
8324         
8325         right = IC_RIGHT(ic);
8326         left  = IC_LEFT(ic);
8327         result = IC_RESULT(ic);
8328         
8329         aopOp(right,ic,FALSE);
8330         aopOp(left,ic,FALSE);
8331         aopOp(result,ic,FALSE);
8332         
8333         /* if the shift count is known then do it 
8334         as efficiently as possible */
8335         if (AOP_TYPE(right) == AOP_LIT) {
8336                 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8337                 if (lit < 0)
8338                 {
8339                         lit = -lit;
8340                         shiftRight = !shiftRight;
8341                 }
8342                 
8343                 if (shiftRight)
8344                         shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8345                 else
8346                         shiftLeft_Left2ResultLit (left, result, lit);
8347                 //genRightShiftLiteral (left,right,result,ic, 0);
8348                 return ;
8349         }
8350         
8351         /* shift count is unknown then we have to form 
8352         a loop get the loop count in B : Note: we take
8353         only the lower order byte since shifting
8354         more that 32 bits make no sense anyway, ( the
8355         largest size of an object can be only 32 bits ) */  
8356
8357         /* we must not overwrite the shift counter */
8358         assert (!pic14_sameRegs(AOP(right),AOP(result)));
8359         
8360         /* now move the left to the result if they are not the
8361         same */
8362         if (!pic14_sameRegs(AOP(left),AOP(result)))
8363         {
8364                 size = min(AOP_SIZE(result), AOP_SIZE(left));
8365                 while (size--) {
8366                         mov2w(AOP(left), size);
8367                         movwf(AOP(result), size);
8368                 }
8369                 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8370         }
8371         
8372         tlbl = newiTempLabel(NULL);
8373         tlbl1= newiTempLabel(NULL);
8374         inverselbl = NULL;
8375         size = AOP_SIZE(result);
8376
8377         mov2w(AOP(right),0);
8378         if (!SPEC_USIGN(operandType(right)))
8379         {
8380                 inverselbl = newiTempLabel(NULL);
8381                 /* signed shift count -- invert shift direction for c<0 */
8382                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8383                 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8384         } // if
8385         emitpcode(POC_SUBLW, popGetLit(0));     /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8386         /* check for `a = b >> c' with `-c == 0' */
8387         emitSKPNZ;
8388         emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8389         emitpLabel(tlbl->key);
8390         /* propagate the sign bit inwards for SIGNED result */
8391         if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8392         genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8393         emitpcode(POC_ADDLW,  popGetLit(1));    /* clears CARRY (unless W==0 afterwards) */
8394         emitSKPC;
8395         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8396
8397         if (!SPEC_USIGN(operandType(right)))
8398         {
8399                 symbol *inv_loop = newiTempLabel(NULL);
8400
8401                 shiftRight = !shiftRight;       /* invert shift direction */
8402                 
8403                 /* we came here from the code above -- we are done */
8404                 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8405                 
8406                 /* emit code for shifting N<0 steps, count is already in W */
8407                 emitpLabel(inverselbl->key);
8408                 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8409                 emitpLabel(inv_loop->key);
8410                 /* propagate the sign bit inwards for SIGNED result */
8411                 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8412                 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8413                 emitpcode(POC_ADDLW, popGetLit(1));
8414                 emitSKPC;
8415                 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8416         } // if
8417         
8418         emitpLabel(tlbl1->key);
8419         
8420         freeAsmop(left,NULL,ic,TRUE);
8421         freeAsmop (right,NULL,ic,TRUE);
8422         freeAsmop(result,NULL,ic,TRUE);
8423 }
8424
8425 static void genRightShift (iCode *ic)
8426 {
8427         genGenericShift(ic, 1);
8428 }
8429
8430 static void genLeftShift (iCode *ic)
8431 {
8432         genGenericShift(ic, 0);
8433 }
8434
8435 /*-----------------------------------------------------------------*/
8436 /* SetIrp - Set IRP bit                                            */
8437 /*-----------------------------------------------------------------*/
8438 void SetIrp(operand *result) {
8439         FENTRY;
8440         if (AOP_TYPE(result) == AOP_LIT) {
8441                 unsigned lit = (unsigned)operandLitValue(result);
8442                 if (lit&0x100)
8443                         emitSETIRP;
8444                 else
8445                         emitCLRIRP;
8446         } else {
8447                 if (PCOP(AOP(result))->type == PO_LITERAL) {
8448                         int addrs = PCOL(AOP(result))->lit;
8449                         if (addrs & 0x100)
8450                                 emitSETIRP;
8451                         else
8452                                 emitCLRIRP;
8453                 } else {
8454                         emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8455                         if(AOP_SIZE(result) > 1) {
8456                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8457                                 emitSETIRP;
8458                         }
8459                 }
8460         }
8461 }
8462
8463 static void
8464 setup_fsr (operand *ptr)
8465 {
8466   mov2w_op(ptr, 0);
8467   emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8468
8469   /* also setup-up IRP */
8470   SetIrp (ptr);
8471 }
8472
8473 /*-----------------------------------------------------------------*/
8474 /* emitPtrByteGet - emits code to get a byte into WREG from an     */
8475 /*                  arbitrary pointer (__code, __data, generic)    */
8476 /*-----------------------------------------------------------------*/
8477 static void
8478 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8479 {
8480     FENTRY;
8481     switch (p_type)
8482     {
8483     case POINTER:
8484     case FPOINTER:
8485       if (!alreadyAddressed) setup_fsr (src);
8486       emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8487       break;
8488     
8489     case CPOINTER:
8490       assert( AOP_SIZE(src) == 2 );
8491       mov2w_op(src, 0);
8492       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8493       mov2w_op(src, 1);
8494       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8495       emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE));   /* GPOINTER tag for __code space */
8496       call_libraryfunc ("__gptrget1");
8497       break;
8498     
8499     case GPOINTER:
8500       assert( AOP_SIZE(src) == 3 );
8501       mov2w_op(src, 0);
8502       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8503       mov2w_op(src, 1);
8504       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8505       mov2w_op(src, 2);
8506       call_libraryfunc ("__gptrget1");
8507       break;
8508     
8509     default:
8510       assert( !"unhandled pointer type" );
8511       break;
8512     }
8513 }
8514
8515 /*-----------------------------------------------------------------*/
8516 /* emitPtrByteSet - emits code to set a byte from src through a    */
8517 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR).       */
8518 /*-----------------------------------------------------------------*/
8519 static void
8520 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8521 {
8522     FENTRY;
8523     switch (p_type)
8524     {
8525     case POINTER:
8526     case FPOINTER:
8527       if (!alreadyAddressed) setup_fsr (dst);
8528       emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8529       break;
8530     
8531     case CPOINTER:
8532       assert( !"trying to assign to __code pointer" );
8533       break;
8534     
8535     case GPOINTER:
8536       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8537       mov2w_op(dst, 0);
8538       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8539       mov2w_op(dst, 1);
8540       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8541       mov2w_op(dst, 2);
8542       call_libraryfunc ("__gptrput1");
8543       break;
8544
8545     default:
8546       assert( !"unhandled pointer type" );
8547       break;
8548     }
8549 }
8550
8551 /*-----------------------------------------------------------------*/
8552 /* genUnpackBits - generates code for unpacking bits               */
8553 /*-----------------------------------------------------------------*/
8554 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8555 {    
8556   int rsize;            /* result size */
8557   sym_link *etype;      /* bitfield type information */
8558   int blen;             /* bitfield length */
8559   int bstr;             /* bitfield starting bit within byte */
8560
8561   FENTRY;
8562   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8563   etype = getSpec(operandType(result));
8564   rsize = getSize (operandType (result));
8565   blen = SPEC_BLEN (etype);
8566   bstr = SPEC_BSTR (etype);
8567
8568   /* single bit field case */
8569   if (blen == 1) {
8570     if (ifx) { /* that is for an if statement */
8571       pCodeOp *pcop;
8572       resolvedIfx rIfx;
8573       resolveIfx(&rIfx,ifx);
8574       if (ptype == -1) /* direct */
8575         pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8576       else
8577         pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8578       emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8579       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8580       ifx->generated=1;
8581     } else {
8582       int i;
8583       assert (!pic14_sameRegs (AOP(result), AOP(left)));
8584       for (i=0; i < AOP_SIZE(result); i++)
8585         emitpcode (POC_CLRF, popGet (AOP(result), i));
8586
8587       switch (ptype)
8588       {
8589       case -1:
8590         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8591         /* adjust result below */
8592         break;
8593         
8594       case POINTER:
8595       case FPOINTER:
8596       case GPOINTER:
8597       case CPOINTER:
8598         emitPtrByteGet (left, ptype, FALSE);
8599         emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8600         emitSKPZ;
8601         /* adjust result below */
8602         break;
8603         
8604       default:
8605         assert( !"unhandled pointer type" );
8606       } // switch
8607
8608       /* move sign-/zero extended bit to result */
8609       if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8610         emitpcode (POC_INCF, popGet (AOP(result), 0));
8611       } else {
8612         emitpcode (POC_DECF, popGet (AOP(result), 0));
8613       }
8614       addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8615     }
8616     return;
8617   }
8618   else if (blen <= 8 && ((blen + bstr) <= 8))
8619   {
8620     /* blen > 1 */
8621     int i;
8622
8623     for (i=0; i < AOP_SIZE(result); i++)
8624       emitpcode (POC_CLRF, popGet (AOP(result), i));
8625
8626     switch (ptype)
8627     {
8628     case -1:
8629       mov2w(AOP(left), 0);
8630       break;
8631       
8632     case POINTER:
8633     case FPOINTER:
8634     case GPOINTER:
8635     case CPOINTER:
8636       emitPtrByteGet (left, ptype, FALSE);
8637       break;
8638       
8639     default:
8640       assert( !"unhandled pointer type" );
8641     } // switch
8642
8643     if (blen < 8)
8644       emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8645     movwf(AOP(result), 0);
8646     AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8647
8648     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8649     {
8650       /* signed bitfield */
8651       assert (bstr + blen > 0);
8652       emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8653       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8654       emitpcode(POC_IORWF, popGet(AOP(result),0));
8655     }
8656     addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8657     return;
8658   }
8659
8660   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8661 }
8662
8663 #if 1
8664 /*-----------------------------------------------------------------*/
8665 /* genDataPointerGet - generates code when ptr offset is known     */
8666 /*-----------------------------------------------------------------*/
8667 static void genDataPointerGet (operand *left, 
8668         operand *result, 
8669         iCode *ic)
8670 {
8671         int size , offset = 0;
8672                 
8673         FENTRY;
8674         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8675         
8676         
8677         /* optimization - most of the time, left and result are the same
8678         * address, but different types. for the pic code, we could omit
8679         * the following
8680         */
8681         aopOp(result,ic,TRUE);
8682         
8683         if (pic14_sameRegs (AOP(left), AOP(result)))
8684                 return;
8685         
8686         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8687         
8688         //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8689         
8690         size = AOP_SIZE(result);
8691         if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8692         
8693         offset = 0;
8694         while (size--) {
8695                 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8696                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8697                 offset++;
8698         }
8699         
8700         freeAsmop(left,NULL,ic,TRUE);
8701         freeAsmop(result,NULL,ic,TRUE);
8702 }
8703 #endif
8704
8705 /*-----------------------------------------------------------------*/
8706 /* genNearPointerGet - pic14_emitcode for near pointer fetch       */
8707 /*-----------------------------------------------------------------*/
8708 static void genNearPointerGet (operand *left, 
8709                                                            operand *result, 
8710                                                            iCode *ic)
8711 {
8712         asmop *aop = NULL;
8713         sym_link *ltype = operandType(left);
8714         sym_link *rtype = operandType(result);
8715         sym_link *retype= getSpec(rtype);      /* bitfield type information */
8716         int direct = 0;
8717
8718         FENTRY;
8719         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8720         
8721         
8722         aopOp(left,ic,FALSE);
8723         
8724         /* if left is rematerialisable and
8725         result is not bit variable type and
8726         the left is pointer to data space i.e
8727         lower 128 bytes of space */
8728         if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8729                 !IS_BITVAR(retype)         &&
8730                 PIC_IS_DATA_PTR(ltype)) {
8731                 genDataPointerGet (left,result,ic);
8732                 return ;
8733         }
8734         
8735         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8736         aopOp (result,ic,FALSE);
8737         
8738         /* Check if can access directly instead of via a pointer */
8739         if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8740                 && AOP_SIZE(result) == 1)
8741         {
8742                 direct = 1;
8743         }
8744
8745         if (IS_BITFIELD(getSpec(operandType(result)))) 
8746         {
8747                 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8748                 goto release;
8749         }
8750         
8751         /* If the pointer value is not in a the FSR then need to put it in */
8752         /* Must set/reset IRP bit for use with FSR. */
8753         if (!direct)
8754           setup_fsr (left);
8755         
8756 //      sym_link *etype;
8757         /* if bitfield then unpack the bits */
8758         {
8759                 /* we have can just get the values */
8760                 int size = AOP_SIZE(result);
8761                 int offset = 0 ;  
8762                 
8763                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8764                 
8765                 while(size--) {
8766                         if (direct)
8767                                 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8768                         else
8769                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8770                         if (AOP_TYPE(result) == AOP_LIT) {
8771                                 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8772                         } else {
8773                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8774                         }
8775                         if (size && !direct)
8776                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8777                         offset++;
8778                 }
8779         }
8780         
8781         /* now some housekeeping stuff */
8782         if (aop) {
8783                 /* we had to allocate for this iCode */
8784                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8785                 freeAsmop(NULL,aop,ic,TRUE);
8786         } else { 
8787                 /* we did not allocate which means left
8788                 already in a pointer register, then
8789                 if size > 0 && this could be used again
8790                 we have to point it back to where it 
8791                 belongs */
8792                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8793                 if (AOP_SIZE(result) > 1 &&
8794                         !OP_SYMBOL(left)->remat &&
8795                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8796                         ic->depth )) {
8797                         int size = AOP_SIZE(result) - 1;
8798                         while (size--)
8799                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8800                 }
8801         }
8802         
8803 release:
8804         /* done */
8805         freeAsmop(left,NULL,ic,TRUE);
8806         freeAsmop(result,NULL,ic,TRUE);
8807
8808 }
8809
8810 #if 0
8811 /*-----------------------------------------------------------------*/
8812 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8813 /*-----------------------------------------------------------------*/
8814 static void genPagedPointerGet (operand *left, 
8815                                                                 operand *result, 
8816                                                                 iCode *ic)
8817 {
8818         asmop *aop = NULL;
8819         regs *preg = NULL ;
8820         char *rname ;
8821         sym_link *rtype, *retype;    
8822         
8823         FENTRY;
8824         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8825         
8826         rtype = operandType(result);
8827         retype= getSpec(rtype);
8828         
8829         aopOp(left,ic,FALSE);
8830         
8831         /* if the value is already in a pointer register
8832         then don't need anything more */
8833         if (!AOP_INPREG(AOP(left))) {
8834                 /* otherwise get a free pointer register */
8835                 aop = newAsmop(0);
8836                 preg = getFreePtr(ic,&aop,FALSE);
8837                 pic14_emitcode("mov","%s,%s",
8838                         preg->name,
8839                         aopGet(AOP(left),0,FALSE,TRUE));
8840                 rname = preg->name ;
8841         } else
8842                 rname = aopGet(AOP(left),0,FALSE,FALSE);
8843         
8844         freeAsmop(left,NULL,ic,TRUE);
8845         aopOp (result,ic,FALSE);
8846         
8847         /* if bitfield then unpack the bits */
8848         if (IS_BITFIELD(retype)) 
8849                 genUnpackBits (result,left,rname,PPOINTER,0);
8850         else {
8851                 /* we have can just get the values */
8852                 int size = AOP_SIZE(result);
8853                 int offset = 0 ;  
8854                 
8855                 while (size--) {
8856                         
8857                         pic14_emitcode("movx","a,@%s",rname);
8858                         aopPut(AOP(result),"a",offset);
8859                         
8860                         offset++ ;
8861                         
8862                         if (size)
8863                                 pic14_emitcode("inc","%s",rname);
8864                 }
8865         }
8866         
8867         /* now some housekeeping stuff */
8868         if (aop) {
8869                 /* we had to allocate for this iCode */
8870                 freeAsmop(NULL,aop,ic,TRUE);
8871         } else { 
8872         /* we did not allocate which means left
8873         already in a pointer register, then
8874         if size > 0 && this could be used again
8875         we have to point it back to where it 
8876                 belongs */
8877                 if (AOP_SIZE(result) > 1 &&
8878                         !OP_SYMBOL(left)->remat &&
8879                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8880                         ic->depth )) {
8881                         int size = AOP_SIZE(result) - 1;
8882                         while (size--)
8883                                 pic14_emitcode("dec","%s",rname);
8884                 }
8885         }
8886         
8887         /* done */
8888         freeAsmop(result,NULL,ic,TRUE);
8889         
8890         
8891 }
8892
8893 /*-----------------------------------------------------------------*/
8894 /* genFarPointerGet - gget value from far space                    */
8895 /*-----------------------------------------------------------------*/
8896 static void genFarPointerGet (operand *left,
8897                                                           operand *result, iCode *ic)
8898 {
8899         int size, offset ;
8900         sym_link *retype = getSpec(operandType(result));
8901         
8902         FENTRY;
8903         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8904         
8905         aopOp(left,ic,FALSE);
8906         
8907         /* if the operand is already in dptr 
8908         then we do nothing else we move the value to dptr */
8909         if (AOP_TYPE(left) != AOP_STR) {
8910                 /* if this is remateriazable */
8911                 if (AOP_TYPE(left) == AOP_IMMD)
8912                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8913                 else { /* we need to get it byte by byte */
8914                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8915                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8916                         if (options.model == MODEL_FLAT24)
8917                         {
8918                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8919                         }
8920                 }
8921         }
8922         /* so dptr know contains the address */
8923         freeAsmop(left,NULL,ic,TRUE);
8924         aopOp(result,ic,FALSE);
8925         
8926         /* if bit then unpack */
8927         if (IS_BITFIELD(retype)) 
8928                 genUnpackBits(result,left,"dptr",FPOINTER,0);
8929         else {
8930                 size = AOP_SIZE(result);
8931                 offset = 0 ;
8932                 
8933                 while (size--) {
8934                         pic14_emitcode("movx","a,@dptr");
8935                         aopPut(AOP(result),"a",offset++);
8936                         if (size)
8937                                 pic14_emitcode("inc","dptr");
8938                 }
8939         }
8940         
8941         freeAsmop(result,NULL,ic,TRUE);
8942 }
8943 #endif
8944
8945 #if 0
8946 /*-----------------------------------------------------------------*/
8947 /* genCodePointerGet - get value from code space                  */
8948 /*-----------------------------------------------------------------*/
8949 static void genCodePointerGet (operand *left,
8950                                                            operand *result, iCode *ic)
8951 {
8952         int size, offset ;
8953         sym_link *retype = getSpec(operandType(result));
8954         
8955         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8956         
8957         aopOp(left,ic,FALSE);
8958         
8959         /* if the operand is already in dptr 
8960         then we do nothing else we move the value to dptr */
8961         if (AOP_TYPE(left) != AOP_STR) {
8962                 /* if this is remateriazable */
8963                 if (AOP_TYPE(left) == AOP_IMMD)
8964                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8965                 else { /* we need to get it byte by byte */
8966                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8967                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8968                         if (options.model == MODEL_FLAT24)
8969                         {
8970                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8971                         }
8972                 }
8973         }
8974         /* so dptr know contains the address */
8975         freeAsmop(left,NULL,ic,TRUE);
8976         aopOp(result,ic,FALSE);
8977         
8978         /* if bit then unpack */
8979         if (IS_BITFIELD(retype)) 
8980                 genUnpackBits(result,left,"dptr",CPOINTER,0);
8981         else {
8982                 size = AOP_SIZE(result);
8983                 offset = 0 ;
8984                 
8985                 while (size--) {
8986                         pic14_emitcode("clr","a");
8987                         pic14_emitcode("movc","a,@a+dptr");
8988                         aopPut(AOP(result),"a",offset++);
8989                         if (size)
8990                                 pic14_emitcode("inc","dptr");
8991                 }
8992         }
8993         
8994         freeAsmop(result,NULL,ic,TRUE);
8995 }
8996 #endif
8997 /*-----------------------------------------------------------------*/
8998 /* genGenPointerGet - gget value from generic pointer space        */
8999 /*-----------------------------------------------------------------*/
9000 static void genGenPointerGet (operand *left,
9001                                                           operand *result, iCode *ic)
9002 {
9003         FENTRY;
9004         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9005         aopOp(left,ic,FALSE);
9006         aopOp(result,ic,FALSE);
9007         
9008         
9009         DEBUGpic14_AopType(__LINE__,left,NULL,result);
9010
9011         if (IS_BITFIELD(getSpec(operandType(result))))
9012         {
9013           genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
9014           return;
9015         }
9016
9017         {
9018           /* emit call to __gptrget */
9019           char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
9020           int size = AOP_SIZE(result);
9021           int idx = 0;
9022
9023           assert (size > 0 && size <= 4);
9024
9025           /* pass arguments */
9026           assert (AOP_SIZE(left) == 3);
9027           mov2w(AOP(left), 0);
9028           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9029           mov2w(AOP(left), 1);
9030           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9031           mov2w(AOP(left), 2);
9032           call_libraryfunc (func[size]);
9033           
9034           /* save result */
9035           movwf (AOP(result), --size);
9036           while (size--) {
9037             emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
9038             movwf (AOP(result), size);
9039           } // while
9040         }
9041         
9042         freeAsmop(left,NULL,ic,TRUE);
9043         freeAsmop(result,NULL,ic,TRUE);
9044         
9045 }
9046
9047 /*-----------------------------------------------------------------*/
9048 /* genConstPointerGet - get value from const generic pointer space */
9049 /*-----------------------------------------------------------------*/
9050 static void genConstPointerGet (operand *left,
9051                                                                 operand *result, iCode *ic)
9052 {
9053         //sym_link *retype = getSpec(operandType(result));
9054         #if 0
9055         symbol *albl, *blbl;//, *clbl;
9056         pCodeOp *pcop;
9057         #endif
9058         PIC_OPCODE poc;
9059         int i, size, lit;
9060         
9061         FENTRY;
9062         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9063         aopOp(left,ic,FALSE);
9064         aopOp(result,ic,FALSE);
9065         
9066         size = AOP_SIZE(result);
9067         
9068         DEBUGpic14_AopType(__LINE__,left,NULL,result);
9069         
9070         DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9071
9072         lit = op_isLitLike (left);
9073         poc = lit ? POC_MOVLW : POC_MOVFW;
9074
9075         if (IS_BITFIELD(getSpec(operandType(result))))
9076         {
9077                 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9078                 goto release;
9079         }
9080
9081         {
9082                 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9083                 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9084                 assert (size > 0 && size <= 4);
9085                 
9086                 mov2w_op(left, 0);
9087                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9088                 mov2w_op(left, 1);
9089                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9090                 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9091                 call_libraryfunc (func[size]);
9092
9093                 movwf(AOP(result),size-1);
9094                 for (i = 1; i < size; i++)
9095                 {
9096                         emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9097                         movwf(AOP(result),size - 1 - i);
9098                 } // for
9099         }
9100         
9101 release:
9102         freeAsmop(left,NULL,ic,TRUE);
9103         freeAsmop(result,NULL,ic,TRUE);
9104         
9105 }
9106 /*-----------------------------------------------------------------*/
9107 /* genPointerGet - generate code for pointer get                   */
9108 /*-----------------------------------------------------------------*/
9109 static void genPointerGet (iCode *ic)
9110 {
9111         operand *left, *result ;
9112         sym_link *type, *etype;
9113         int p_type = -1;
9114         
9115         FENTRY;
9116         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9117         
9118         left = IC_LEFT(ic);
9119         result = IC_RESULT(ic) ;
9120         
9121         /* depending on the type of pointer we need to
9122         move it to the correct pointer register */
9123         type = operandType(left);
9124         etype = getSpec(type);
9125         
9126         if (IS_PTR_CONST(type))
9127                 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9128         
9129         /* if left is of type of pointer then it is simple */
9130         if (IS_PTR(type) && !IS_FUNC(type->next)) 
9131                 p_type = DCL_TYPE(type);
9132         else {
9133                 /* we have to go by the storage class */
9134                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9135                 
9136                 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9137                 
9138                 if (SPEC_OCLS(etype)->codesp ) {
9139                         DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9140                         //p_type = CPOINTER ; 
9141                 }
9142                 else
9143                         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9144                                 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9145                         /*p_type = FPOINTER ;*/ 
9146                         else
9147                                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9148                                         DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9149                                 /*        p_type = PPOINTER; */
9150                                 else
9151                                         if (SPEC_OCLS(etype) == idata )
9152                                                 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9153                                         /*      p_type = IPOINTER; */
9154                                         else
9155                                                 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9156                                         /*      p_type = POINTER ; */
9157         }
9158         
9159         /* now that we have the pointer type we assign
9160         the pointer values */
9161         switch (p_type) {
9162                 
9163         case POINTER: 
9164         case FPOINTER:
9165         //case IPOINTER:
9166                 genNearPointerGet (left,result,ic);
9167                 break;
9168 /*
9169         case PPOINTER:
9170                 genPagedPointerGet(left,result,ic);
9171                 break;
9172                 
9173         case FPOINTER:
9174                 genFarPointerGet (left,result,ic);
9175                 break;
9176 */              
9177         case CPOINTER:
9178                 genConstPointerGet (left,result,ic);
9179                 break;
9180                 
9181         case GPOINTER:
9182                 genGenPointerGet (left,result,ic);
9183                 break;
9184         default:
9185                 assert ( !"unhandled pointer type" );
9186                 break;
9187         }
9188         
9189 }
9190
9191 /*-----------------------------------------------------------------*/
9192 /* genPackBits - generates code for packed bit storage             */
9193 /*-----------------------------------------------------------------*/
9194 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9195 {
9196   int blen;             /* bitfield length */
9197   int bstr;             /* bitfield starting bit within byte */
9198   int litval;           /* source literal value (if AOP_LIT) */
9199   unsigned char mask;   /* bitmask within current byte */
9200
9201   FENTRY;
9202   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9203
9204   blen = SPEC_BLEN (etype);
9205   bstr = SPEC_BSTR (etype);
9206
9207   /* If the bitfield length is less than a byte and does not cross byte boundaries */
9208   if ((blen <= 8) && ((bstr + blen) <= 8))
9209   {
9210     mask = ((unsigned char) (0xFF << (blen + bstr)) |
9211             (unsigned char) (0xFF >> (8 - bstr)));
9212
9213     if (AOP_TYPE (right) == AOP_LIT)
9214     {
9215       /* Case with a bitfield length <8 and literal source */
9216       int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9217       if (blen == 1) {
9218         pCodeOp *pcop;
9219         
9220         switch (p_type)
9221         {
9222         case -1:
9223           if (AOP(result)->type == AOP_PCODE)
9224             pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9225           else
9226             pcop = popGet(AOP(result),0);
9227           emitpcode(lit?POC_BSF:POC_BCF,pcop);
9228           break;
9229         
9230         case POINTER:
9231         case FPOINTER:
9232           setup_fsr (result);
9233           emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9234           break;
9235         
9236         case CPOINTER:
9237           assert( !"trying to assign to bitfield via pointer to __code space" );
9238           break;
9239         
9240         case GPOINTER:
9241           emitPtrByteGet(result, p_type, FALSE);
9242           if (lit) {
9243             emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9244           } else {
9245             emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9246           }
9247           emitPtrByteSet(result, p_type, TRUE);
9248           break;
9249         
9250         default:
9251           assert( !"unhandled pointer type" );
9252           break;
9253         } // switch (p_type)
9254       } else {
9255         /* blen > 1 */
9256         litval = lit << bstr;
9257         litval &= (~mask) & 0x00ff;
9258         
9259         switch (p_type)
9260         {
9261         case -1:
9262           mov2w (AOP(result), 0);
9263           if ((litval|mask) != 0x00ff)
9264             emitpcode(POC_ANDLW, popGetLit (mask));
9265           if (litval != 0x00)
9266             emitpcode(POC_IORLW, popGetLit (litval));
9267           movwf (AOP(result), 0);
9268           break;
9269         
9270         case POINTER:
9271         case FPOINTER:
9272         case GPOINTER:
9273           emitPtrByteGet(result, p_type, FALSE);
9274           if ((litval|mask) != 0x00ff)
9275             emitpcode(POC_ANDLW, popGetLit (mask));
9276           if (litval != 0x00)
9277             emitpcode(POC_IORLW, popGetLit (litval));
9278           emitPtrByteSet(result, p_type, TRUE);
9279           break;
9280         
9281         case CPOINTER:
9282           assert( !"trying to assign to bitfield via pointer to __code space" );
9283           break;
9284         
9285         default:
9286           assert( !"unhandled pointer type" );
9287           break;
9288         } // switch
9289       } // if (blen > 1)
9290     }
9291     else
9292     {
9293       /* right is no literal */
9294       if (blen==1) {
9295         switch (p_type)
9296         {
9297         case -1:
9298           /* Note more efficient code, of pre clearing bit then only setting it if required,
9299            * can only be done if it is known that the result is not a SFR */
9300           emitpcode(POC_RRFW,popGet(AOP(right),0));
9301           emitSKPC;
9302           emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9303           emitSKPNC;
9304           emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9305           break;
9306         
9307         case POINTER:
9308         case FPOINTER:
9309         case GPOINTER:
9310           emitPtrByteGet (result, p_type, FALSE);
9311           emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9312           emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9313           emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9314           emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9315           emitPtrByteSet (result, p_type, TRUE);
9316           break;
9317         
9318         case CPOINTER:
9319           assert( !"trying to assign to bitfield via pointer to __code space" );
9320           break;
9321         
9322         default:
9323           assert( !"unhandled pointer type" );
9324           break;
9325         } // switch
9326         return;
9327       } else {
9328         /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9329         pCodeOp *temp = popGetTempReg ();
9330
9331         mov2w (AOP(right), 0);
9332         if (blen < 8) {
9333           emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9334         }
9335         emitpcode(POC_MOVWF, temp);
9336         if (bstr) {
9337           AccLsh (temp, bstr);
9338         }
9339         
9340         switch (p_type)
9341         {
9342         case -1:
9343           mov2w (AOP(result), 0);
9344           emitpcode(POC_ANDLW, popGetLit (mask));
9345           emitpcode(POC_IORFW, temp);
9346           movwf (AOP(result), 0);
9347           break;
9348         
9349         case POINTER:
9350         case FPOINTER:
9351         case GPOINTER:
9352           emitPtrByteGet (result, p_type, FALSE);
9353           emitpcode(POC_ANDLW, popGetLit (mask));
9354           emitpcode(POC_IORFW, temp);
9355           emitPtrByteSet (result, p_type, TRUE);
9356           break;
9357         
9358         case CPOINTER:
9359           assert( !"trying to assign to bitfield via pointer to __code space" );
9360           break;
9361         
9362         default:
9363           assert( !"unhandled pointer type" );
9364           break;
9365         } // switch
9366
9367         popReleaseTempReg (temp);
9368       } // if (blen > 1)
9369     } // if (AOP(right)->type != AOP_LIT)
9370     return;
9371   } // if (blen <= 8 && ((blen + bstr) <= 8))
9372
9373   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9374 }
9375
9376 /*-----------------------------------------------------------------*/
9377 /* genDataPointerSet - remat pointer to data space                 */
9378 /*-----------------------------------------------------------------*/
9379 static void genDataPointerSet(operand *right,
9380         operand *result,
9381         iCode *ic)
9382 {
9383         int size, offset = 0 ;
9384         int ressize;
9385         
9386         FENTRY;
9387         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9388         aopOp(right,ic,FALSE);
9389         aopOp(result,ic,FALSE);
9390         
9391         assert (IS_SYMOP(result));
9392         assert (IS_PTR(OP_SYM_TYPE(result)));
9393         
9394         if (AOP_TYPE(right) == AOP_LIT)
9395           size = 4;
9396         else
9397           size = AOP_SIZE(right);
9398         ressize = getSize(OP_SYM_ETYPE(result));
9399         if (size > ressize) size = ressize;
9400         //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9401         
9402         //assert( !"what's going on here?" );
9403
9404         /*
9405         if ( AOP_TYPE(result) == AOP_PCODE) {
9406         fprintf(stderr,"genDataPointerSet   %s, %d\n",
9407         AOP(result)->aopu.pcop->name,
9408         PCOI(AOP(result)->aopu.pcop)->offset);
9409         }
9410         */
9411         
9412         // tsd, was l+1 - the underline `_' prefix was being stripped
9413         while (size--) {
9414                 emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
9415                 
9416                 if (AOP_TYPE(right) == AOP_LIT) {
9417                         unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
9418                         //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9419                         if(lit&0xff) {
9420                                 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9421                                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9422                         } else {
9423                                 emitpcode(POC_CLRF, popGet(AOP(result), offset));
9424                         }
9425                 } else {
9426                         //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9427                         emitpcode(POC_MOVFW, popGet(AOP(right), offset));
9428                         emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9429                 }
9430                 
9431                 offset++;
9432         }
9433         
9434         freeAsmop(right,NULL,ic,TRUE);
9435         freeAsmop(result,NULL,ic,TRUE);
9436 }
9437
9438 /*-----------------------------------------------------------------*/
9439 /* genNearPointerSet - pic14_emitcode for near pointer put         */
9440 /*-----------------------------------------------------------------*/
9441 static void genNearPointerSet (operand *right,
9442                                                            operand *result, 
9443                                                            iCode *ic)
9444 {
9445         asmop *aop = NULL;
9446         sym_link *ptype = operandType(result);
9447         sym_link *retype = getSpec(operandType(right));
9448         sym_link *letype = getSpec(ptype);
9449         int direct = 0;
9450         
9451         
9452         FENTRY;
9453         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9454         aopOp(result,ic,FALSE);
9455         
9456 #if 1
9457         /* if the result is rematerializable &
9458         in data space & not a bit variable */
9459         //if (AOP_TYPE(result) == AOP_IMMD &&
9460         if (AOP_TYPE(result) == AOP_PCODE &&
9461                 PIC_IS_DATA_PTR(ptype) &&
9462                 !IS_BITVAR (retype) &&
9463                 !IS_BITVAR (letype)) {
9464                 genDataPointerSet (right,result,ic);
9465                 freeAsmop(result,NULL,ic,TRUE);
9466                 return;
9467         }
9468 #endif
9469
9470         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9471         aopOp(right,ic,FALSE);
9472         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9473         
9474         /* Check if can access directly instead of via a pointer */
9475         if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9476                 direct = 1;
9477         }
9478         
9479         if (IS_BITFIELD (letype))
9480         {
9481           genPackBits (letype, result, right, direct?-1:POINTER);
9482           return;
9483         }
9484         
9485         /* If the pointer value is not in a the FSR then need to put it in */
9486         /* Must set/reset IRP bit for use with FSR. */
9487         /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9488         if (!direct)
9489                 setup_fsr (result);
9490
9491         {
9492                 /* we have can just get the values */
9493                 int size = AOP_SIZE(right);
9494                 int offset = 0 ;    
9495                 
9496                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9497                 while (size--) {
9498                         char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9499                         if (*l == '@' ) {
9500                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9501                         } else {
9502                                 if (AOP_TYPE(right) == AOP_LIT) {
9503                                         emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9504                                 } else {
9505                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9506                                 }
9507                                 if (direct)
9508                                         emitpcode(POC_MOVWF,popGet(AOP(result),0));
9509                                 else
9510                                         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9511                         }
9512                         if (size && !direct)
9513                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9514                         offset++;
9515                 }
9516         }
9517         
9518         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9519         /* now some housekeeping stuff */
9520         if (aop) {
9521                 /* we had to allocate for this iCode */
9522                 freeAsmop(NULL,aop,ic,TRUE);
9523         } else { 
9524                 /* we did not allocate which means left
9525                 already in a pointer register, then
9526                 if size > 0 && this could be used again
9527                 we have to point it back to where it 
9528                 belongs */
9529                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9530                 if (AOP_SIZE(right) > 1 &&
9531                         !OP_SYMBOL(result)->remat &&
9532                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9533                         ic->depth )) {
9534                         int size = AOP_SIZE(right) - 1;
9535                         while (size--)
9536                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9537                 }
9538         }
9539         
9540         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9541         /* done */
9542
9543         freeAsmop(right,NULL,ic,TRUE);
9544         freeAsmop(result,NULL,ic,TRUE);
9545 }
9546
9547 #if 0
9548 /*-----------------------------------------------------------------*/
9549 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
9550 /*-----------------------------------------------------------------*/
9551 static void genPagedPointerSet (operand *right,
9552                                                                 operand *result, 
9553                                                                 iCode *ic)
9554 {
9555         asmop *aop = NULL;
9556         regs *preg = NULL ;
9557         char *rname , *l;
9558         sym_link *retype;
9559         
9560         FENTRY;
9561         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9562         
9563         retype= getSpec(operandType(right));
9564         
9565         aopOp(result,ic,FALSE);
9566         
9567         /* if the value is already in a pointer register
9568         then don't need anything more */
9569         if (!AOP_INPREG(AOP(result))) {
9570                 /* otherwise get a free pointer register */
9571                 aop = newAsmop(0);
9572                 preg = getFreePtr(ic,&aop,FALSE);
9573                 pic14_emitcode("mov","%s,%s",
9574                         preg->name,
9575                         aopGet(AOP(result),0,FALSE,TRUE));
9576                 rname = preg->name ;
9577         } else
9578                 rname = aopGet(AOP(result),0,FALSE,FALSE);
9579         
9580         freeAsmop(result,NULL,ic,TRUE);
9581         aopOp (right,ic,FALSE);
9582         
9583         /* if bitfield then unpack the bits */
9584         if (IS_BITFIELD(retype)) 
9585                 genPackBits (retype,result,right,rname,PPOINTER);
9586         else {
9587                 /* we have can just get the values */
9588                 int size = AOP_SIZE(right);
9589                 int offset = 0 ;  
9590                 
9591                 while (size--) {
9592                         l = aopGet(AOP(right),offset,FALSE,TRUE);
9593                         
9594                         MOVA(l);
9595                         pic14_emitcode("movx","@%s,a",rname);
9596                         
9597                         if (size)
9598                                 pic14_emitcode("inc","%s",rname);
9599                         
9600                         offset++;
9601                 }
9602         }
9603         
9604         /* now some housekeeping stuff */
9605         if (aop) {
9606                 /* we had to allocate for this iCode */
9607                 freeAsmop(NULL,aop,ic,TRUE);
9608         } else { 
9609         /* we did not allocate which means left
9610         already in a pointer register, then
9611         if size > 0 && this could be used again
9612         we have to point it back to where it 
9613                 belongs */
9614                 if (AOP_SIZE(right) > 1 &&
9615                         !OP_SYMBOL(result)->remat &&
9616                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9617                         ic->depth )) {
9618                         int size = AOP_SIZE(right) - 1;
9619                         while (size--)
9620                                 pic14_emitcode("dec","%s",rname);
9621                 }
9622         }
9623         
9624         /* done */
9625         freeAsmop(right,NULL,ic,TRUE);
9626         
9627         
9628 }
9629
9630 /*-----------------------------------------------------------------*/
9631 /* genFarPointerSet - set value from far space                     */
9632 /*-----------------------------------------------------------------*/
9633 static void genFarPointerSet (operand *right,
9634                                                           operand *result, iCode *ic)
9635 {
9636         int size, offset ;
9637         sym_link *retype = getSpec(operandType(right));
9638         
9639         FENTRY;
9640         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9641         aopOp(result,ic,FALSE);
9642         
9643         /* if the operand is already in dptr 
9644         then we do nothing else we move the value to dptr */
9645         if (AOP_TYPE(result) != AOP_STR) {
9646                 /* if this is remateriazable */
9647                 if (AOP_TYPE(result) == AOP_IMMD)
9648                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9649                 else { /* we need to get it byte by byte */
9650                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9651                         pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9652                         if (options.model == MODEL_FLAT24)
9653                         {
9654                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9655                         }
9656                 }
9657         }
9658         /* so dptr know contains the address */
9659         freeAsmop(result,NULL,ic,TRUE);
9660         aopOp(right,ic,FALSE);
9661         
9662         /* if bit then unpack */
9663         if (IS_BITFIELD(retype)) 
9664                 genPackBits(retype,result,right,"dptr",FPOINTER);
9665         else {
9666                 size = AOP_SIZE(right);
9667                 offset = 0 ;
9668                 
9669                 while (size--) {
9670                         char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9671                         MOVA(l);
9672                         pic14_emitcode("movx","@dptr,a");
9673                         if (size)
9674                                 pic14_emitcode("inc","dptr");
9675                 }
9676         }
9677         
9678         freeAsmop(right,NULL,ic,TRUE);
9679 }
9680 #endif
9681
9682 /*-----------------------------------------------------------------*/
9683 /* genGenPointerSet - set value from generic pointer space         */
9684 /*-----------------------------------------------------------------*/
9685 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9686 {
9687         sym_link *retype = getSpec(operandType(result));
9688         
9689         FENTRY;
9690         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9691         aopOp(right,ic,FALSE);
9692         aopOp(result,ic,FALSE);
9693
9694         
9695         DEBUGpic14_AopType(__LINE__,right,NULL,result);
9696
9697         if (IS_BITFIELD(retype))
9698         {
9699           genPackBits (retype, result, right, GPOINTER);
9700           return;
9701         }
9702
9703         {
9704           /* emit call to __gptrput */
9705           char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9706           int size = AOP_SIZE(right);
9707           int idx = 0;
9708
9709           assert (size == getSize(OP_SYM_ETYPE(result)));
9710           assert (size > 0 && size <= 4);
9711
9712           /* pass arguments */
9713           /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9714           {
9715             int off = size;
9716             idx = 2;
9717             while (off--)
9718             {
9719               mov2w_op (right, off);
9720               emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9721             }
9722             idx = 0;
9723           }
9724           /* - address */
9725           assert (AOP_SIZE(result) == 3);
9726           mov2w(AOP(result), 0);
9727           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9728           mov2w(AOP(result), 1);
9729           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9730           mov2w(AOP(result), 2);
9731           call_libraryfunc (func[size]);
9732         }
9733         
9734         freeAsmop(right,NULL,ic,TRUE);
9735         freeAsmop(result,NULL,ic,TRUE);
9736 }
9737
9738 /*-----------------------------------------------------------------*/
9739 /* genPointerSet - stores the value into a pointer location        */
9740 /*-----------------------------------------------------------------*/
9741 static void genPointerSet (iCode *ic)
9742 {    
9743         operand *right, *result ;
9744         sym_link *type, *etype;
9745         int p_type;
9746         
9747         FENTRY;
9748         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9749         
9750         right = IC_RIGHT(ic);
9751         result = IC_RESULT(ic) ;
9752         
9753         /* depending on the type of pointer we need to
9754         move it to the correct pointer register */
9755         type = operandType(result);
9756         etype = getSpec(type);
9757         /* if left is of type of pointer then it is simple */
9758         if (IS_PTR(type) && !IS_FUNC(type->next)) {
9759                 p_type = DCL_TYPE(type);
9760         }
9761         else {
9762                 /* we have to go by the storage class */
9763                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9764                 
9765                 /*  if (SPEC_OCLS(etype)->codesp ) { */
9766                 /*      p_type = CPOINTER ;  */
9767                 /*  } */
9768                 /*  else */
9769                 /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9770                 /*    p_type = FPOINTER ; */
9771                 /*      else */
9772                 /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9773                 /*        p_type = PPOINTER ; */
9774                 /*    else */
9775                 /*        if (SPEC_OCLS(etype) == idata ) */
9776                 /*      p_type = IPOINTER ; */
9777                 /*        else */
9778                 /*      p_type = POINTER ; */
9779         }
9780         
9781         /* now that we have the pointer type we assign
9782         the pointer values */
9783         switch (p_type) {
9784                 
9785         case POINTER:
9786         case FPOINTER:
9787         //case IPOINTER:
9788                 genNearPointerSet (right,result,ic);
9789                 break;
9790 /*
9791         case PPOINTER:
9792                 genPagedPointerSet (right,result,ic);
9793                 break;
9794                 
9795         case FPOINTER:
9796                 genFarPointerSet (right,result,ic);
9797                 break;
9798 */
9799         case GPOINTER:
9800                 genGenPointerSet (right,result,ic);
9801                 break;
9802                 
9803         default:
9804                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9805                         "genPointerSet: illegal pointer type");
9806         }
9807 }
9808
9809 /*-----------------------------------------------------------------*/
9810 /* genIfx - generate code for Ifx statement                        */
9811 /*-----------------------------------------------------------------*/
9812 static void genIfx (iCode *ic, iCode *popIc)
9813 {
9814         operand *cond = IC_COND(ic);
9815         int isbit =0;
9816         
9817         FENTRY;
9818         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9819         
9820         aopOp(cond,ic,FALSE);
9821         
9822         /* get the value into acc */
9823         if (AOP_TYPE(cond) != AOP_CRY)
9824                 pic14_toBoolean(cond);
9825         else
9826                 isbit = 1;
9827         
9828         /* if there was something to be popped then do it */
9829         if (popIc)
9830                 genIpop(popIc);
9831         
9832         if (isbit)
9833         {
9834                 /* This assumes that CARRY is set iff cond is true */
9835                 if (IC_TRUE(ic))
9836                 {
9837                         assert (!IC_FALSE(ic));
9838                         emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9839                         //emitSKPNC;
9840                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9841                 } else {
9842                         assert (IC_FALSE(ic));
9843                         emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9844                         //emitSKPC;
9845                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9846                 }
9847                 if (0)
9848                 {
9849                         static int hasWarned = 0;
9850                         if (!hasWarned)
9851                         {
9852                                 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9853                                 hasWarned = 1;
9854                         }
9855                 }
9856         }
9857         else
9858         {
9859                 /* now Z is set iff !cond */
9860                 if (IC_TRUE(ic))
9861                 {
9862                         assert (!IC_FALSE(ic));
9863                         emitSKPZ;
9864                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9865                 } else {
9866                         emitSKPNZ;
9867                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9868                 }
9869         }
9870         
9871         ic->generated = 1;
9872         
9873         /* the result is now in the accumulator */
9874         freeAsmop(cond,NULL,ic,TRUE);
9875 }
9876
9877 /*-----------------------------------------------------------------*/
9878 /* genAddrOf - generates code for address of                       */
9879 /*-----------------------------------------------------------------*/
9880 static void genAddrOf (iCode *ic)
9881 {
9882         operand *right, *result, *left;
9883         int size, offset ;
9884         
9885         FENTRY;
9886         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9887         
9888         
9889         //aopOp(IC_RESULT(ic),ic,FALSE);
9890         
9891         aopOp((left=IC_LEFT(ic)),ic,FALSE);
9892         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9893         aopOp((result=IC_RESULT(ic)),ic,TRUE);
9894         
9895         DEBUGpic14_AopType(__LINE__,left,right,result);
9896         assert (IS_SYMOP (left));
9897         
9898         /* sanity check: generic pointers to code space are not yet supported,
9899          * pionters to codespace must not be assigned addresses of __data values. */
9900  #if 0
9901         fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9902         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)));
9903         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)));
9904         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)));
9905         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)));
9906 #endif
9907
9908         if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9909           fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9910                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9911                 OP_SYMBOL(left)->name);
9912         } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9913           fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9914                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9915                 OP_SYMBOL(left)->name);
9916         }
9917         
9918         size = AOP_SIZE(IC_RESULT(ic));
9919         if (IS_GENPTR(OP_SYM_TYPE(result))) {
9920                 /* strip tag */
9921                 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9922         }
9923         offset = 0;
9924         
9925         while (size--) {
9926                 /* fixing bug #863624, reported from (errolv) */
9927                 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9928                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9929                 
9930 #if 0
9931                 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9932                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9933 #endif
9934                 offset++;
9935         }
9936
9937         if (IS_GENPTR(OP_SYM_TYPE(result)))
9938         {
9939                 /* provide correct tag */
9940                 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9941                 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9942                 movwf (AOP(result), 2);
9943         }
9944         
9945         freeAsmop(left,NULL,ic,FALSE);
9946         freeAsmop(result,NULL,ic,TRUE);
9947         
9948 }
9949
9950 #if 0
9951 /*-----------------------------------------------------------------*/
9952 /* genFarFarAssign - assignment when both are in far space         */
9953 /*-----------------------------------------------------------------*/
9954 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9955 {
9956         int size = AOP_SIZE(right);
9957         int offset = 0;
9958         char *l ;
9959         /* first push the right side on to the stack */
9960         while (size--) {
9961                 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9962                 MOVA(l);
9963                 pic14_emitcode ("push","acc");
9964         }
9965         
9966         freeAsmop(right,NULL,ic,FALSE);
9967         /* now assign DPTR to result */
9968         aopOp(result,ic,FALSE);
9969         size = AOP_SIZE(result);
9970         while (size--) {
9971                 pic14_emitcode ("pop","acc");
9972                 aopPut(AOP(result),"a",--offset);
9973         }
9974         freeAsmop(result,NULL,ic,FALSE);
9975         
9976 }
9977 #endif
9978
9979 /*-----------------------------------------------------------------*/
9980 /* genAssign - generate code for assignment                        */
9981 /*-----------------------------------------------------------------*/
9982 static void genAssign (iCode *ic)
9983 {
9984         operand *result, *right;
9985         int size, offset,know_W;
9986         unsigned long lit = 0L;
9987         
9988         result = IC_RESULT(ic);
9989         right  = IC_RIGHT(ic) ;
9990         
9991         FENTRY;
9992         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9993         
9994         /* if they are the same */
9995         if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9996                 return ;
9997         
9998         aopOp(right,ic,FALSE);
9999         aopOp(result,ic,TRUE);
10000         
10001         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10002         
10003         /* if they are the same registers */
10004         if (pic14_sameRegs(AOP(right),AOP(result)))
10005                 goto release;
10006
10007         /* special case: assign from __code */
10008         if (!IS_ITEMP(right)                            /* --> iTemps never reside in __code */
10009                 && IS_SYMOP (right)                     /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
10010                 && !IS_FUNC(OP_SYM_TYPE(right))         /* --> we would want its address instead of the first instruction */
10011                 && !IS_CODEPTR(OP_SYM_TYPE(right))      /* --> get symbols address instread */
10012                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
10013         {
10014           emitpComment ("genAssign from CODESPACE");
10015           genConstPointerGet (right, result, ic);
10016           goto release;
10017         }
10018         
10019         /* just for symmetry reasons... */
10020         if (!IS_ITEMP(result)
10021                 && IS_SYMOP (result)
10022                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
10023         {
10024           assert ( !"cannot write to CODESPACE" );
10025         }
10026
10027         /* if the result is a bit */
10028         if (AOP_TYPE(result) == AOP_CRY) {
10029                 
10030         /* if the right size is a literal then
10031                 we know what the value is */
10032                 if (AOP_TYPE(right) == AOP_LIT) {
10033                         
10034                         emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10035                                 popGet(AOP(result),0));
10036                         
10037                         if (((int) operandLitValue(right))) 
10038                                 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10039                                 AOP(result)->aopu.aop_dir,
10040                                 AOP(result)->aopu.aop_dir);
10041                         else
10042                                 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10043                                 AOP(result)->aopu.aop_dir,
10044                                 AOP(result)->aopu.aop_dir);
10045                         goto release;
10046                 }
10047                 
10048                 /* the right is also a bit variable */
10049                 if (AOP_TYPE(right) == AOP_CRY) {
10050                         emitpcode(POC_BCF,    popGet(AOP(result),0));
10051                         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10052                         emitpcode(POC_BSF,    popGet(AOP(result),0));
10053                         
10054                         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10055                                 AOP(result)->aopu.aop_dir,
10056                                 AOP(result)->aopu.aop_dir);
10057                         pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10058                                 AOP(right)->aopu.aop_dir,
10059                                 AOP(right)->aopu.aop_dir);
10060                         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10061                                 AOP(result)->aopu.aop_dir,
10062                                 AOP(result)->aopu.aop_dir);
10063                         goto release ;
10064                 }
10065                 
10066                 /* we need to or */
10067                 emitpcode(POC_BCF,    popGet(AOP(result),0));
10068                 pic14_toBoolean(right);
10069                 emitSKPZ;
10070                 emitpcode(POC_BSF,    popGet(AOP(result),0));
10071                 //aopPut(AOP(result),"a",0);
10072                 goto release ;
10073         }
10074         
10075         /* bit variables done */
10076         /* general case */
10077         size = AOP_SIZE(result);
10078         offset = 0 ;
10079         if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10080                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10081                 if(aopIdx(AOP(result),0) == 4) {
10082                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10083                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10084                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10085                         goto release;
10086                 } else
10087                         DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10088         }
10089         
10090         know_W=-1;
10091         while (size--) {
10092         
10093                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10094                 if(AOP_TYPE(right) == AOP_LIT) {
10095                         lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
10096                         if(lit&0xff) {
10097                                 if(know_W != (int)(lit&0xff))
10098                                         emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10099                                 know_W = lit&0xff;
10100                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10101                         } else
10102                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10103                         
10104                 } else if (AOP_TYPE(right) == AOP_CRY) {
10105                         emitpcode(POC_CLRF, popGet(AOP(result),offset));
10106                         if(offset == 0) {
10107                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10108                                 emitpcode(POC_INCF, popGet(AOP(result),0));
10109                         }
10110                 } else {
10111                         mov2w_op (right, offset);
10112                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10113                 }
10114                 
10115                 offset++;
10116         }
10117         
10118         
10119 release:
10120         freeAsmop (right,NULL,ic,FALSE);
10121         freeAsmop (result,NULL,ic,TRUE);
10122 }   
10123
10124 /*-----------------------------------------------------------------*/
10125 /* genJumpTab - genrates code for jump table                       */
10126 /*-----------------------------------------------------------------*/
10127 static void genJumpTab (iCode *ic)
10128 {
10129         symbol *jtab;
10130         char *l;
10131         
10132         FENTRY;
10133         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10134         
10135         aopOp(IC_JTCOND(ic),ic,FALSE);
10136         /* get the condition into accumulator */
10137         l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10138         MOVA(l);
10139         /* multiply by three */
10140         pic14_emitcode("add","a,acc");
10141         pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10142         
10143         jtab = newiTempLabel(NULL);
10144         pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10145         pic14_emitcode("jmp","@a+dptr");
10146         pic14_emitcode("","%05d_DS_:",jtab->key+100);
10147         
10148         emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10149         emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10150         emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10151         emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10152         emitSKPNC;
10153         emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10154         emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10155         emitpLabel(jtab->key);
10156         
10157         freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10158         
10159         /* now generate the jump labels */
10160         for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10161         jtab = setNextItem(IC_JTLABELS(ic))) {
10162                 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10163                 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10164                 
10165         }
10166         
10167 }
10168
10169 /*-----------------------------------------------------------------*/
10170 /* genMixedOperation - gen code for operators between mixed types  */
10171 /*-----------------------------------------------------------------*/
10172 /*
10173 TSD - Written for the PIC port - but this unfortunately is buggy.
10174 This routine is good in that it is able to efficiently promote 
10175 types to different (larger) sizes. Unfortunately, the temporary
10176 variables that are optimized out by this routine are sometimes
10177 used in other places. So until I know how to really parse the 
10178 iCode tree, I'm going to not be using this routine :(.
10179 */
10180 static int genMixedOperation (iCode *ic)
10181 {
10182         FENTRY;
10183 #if 0
10184         operand *result = IC_RESULT(ic);
10185         sym_link *ctype = operandType(IC_LEFT(ic));
10186         operand *right = IC_RIGHT(ic);
10187         int ret = 0;
10188         int big,small;
10189         int offset;
10190         
10191         iCode *nextic;
10192         operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10193         
10194         pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10195         
10196         nextic = ic->next;
10197         if(!nextic)
10198                 return 0;
10199         
10200         nextright = IC_RIGHT(nextic);
10201         nextleft  = IC_LEFT(nextic);
10202         nextresult = IC_RESULT(nextic);
10203         
10204         aopOp(right,ic,FALSE);
10205         aopOp(result,ic,FALSE);
10206         aopOp(nextright,  nextic, FALSE);
10207         aopOp(nextleft,   nextic, FALSE);
10208         aopOp(nextresult, nextic, FALSE);
10209         
10210         if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10211                 
10212                 operand *t = right;
10213                 right = nextright;
10214                 nextright = t; 
10215                 
10216                 pic14_emitcode(";remove right +","");
10217                 
10218         } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10219         /*
10220         operand *t = right;
10221         right = nextleft;
10222         nextleft = t; 
10223                 */
10224                 pic14_emitcode(";remove left +","");
10225         } else
10226                 return 0;
10227         
10228         big = AOP_SIZE(nextleft);
10229         small = AOP_SIZE(nextright);
10230         
10231         switch(nextic->op) {
10232                 
10233         case '+':
10234                 pic14_emitcode(";optimize a +","");
10235                 /* if unsigned or not an integral type */
10236                 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10237                         pic14_emitcode(";add a bit to something","");
10238                 } else {
10239                         
10240                         pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10241                         
10242                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10243                                 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10244                                 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10245                         } else
10246                                 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10247                         
10248                         offset = 0;
10249                         while(--big) {
10250                                 
10251                                 offset++;
10252                                 
10253                                 if(--small) {
10254                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10255                                                 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10256                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10257                                         }
10258                                         
10259                                         pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10260                                         emitSKPNC;
10261                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10262                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10263                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10264                                         pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10265                                         pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10266                                         
10267                                 } else {
10268                                         pic14_emitcode("rlf","known_zero,w");
10269                                         
10270                                         /*
10271                                         if right is signed
10272                                         btfsc  right,7
10273                                         addlw ff
10274                                         */
10275                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10276                                                 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10277                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10278                                         } else {
10279                                                 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10280                                         }
10281                                 }
10282                         }
10283                         ret = 1;
10284                 }
10285         }
10286         ret = 1;
10287         
10288 release:
10289         freeAsmop(right,NULL,ic,TRUE);
10290         freeAsmop(result,NULL,ic,TRUE);
10291         freeAsmop(nextright,NULL,ic,TRUE);
10292         freeAsmop(nextleft,NULL,ic,TRUE);
10293         if(ret)
10294                 nextic->generated = 1;
10295         
10296         return ret;
10297 #else
10298         return 0;
10299 #endif
10300 }
10301 /*-----------------------------------------------------------------*/
10302 /* genCast - gen code for casting                                  */
10303 /*-----------------------------------------------------------------*/
10304 static void genCast (iCode *ic)
10305 {
10306         operand *result = IC_RESULT(ic);
10307         sym_link *restype = operandType(result);
10308         sym_link *rtype = operandType(IC_RIGHT(ic));
10309         operand *right = IC_RIGHT(ic);
10310         int size, offset ;
10311         
10312         FENTRY;
10313         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10314         /* if they are equivalent then do nothing */
10315         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10316                 return ;
10317         
10318         aopOp(right,ic,FALSE) ;
10319         aopOp(result,ic,FALSE);
10320         
10321         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10322         
10323         /* if the result is a bit */
10324         if (AOP_TYPE(result) == AOP_CRY) {
10325                 assert(!"assigning to bit variables is not supported");
10326         }
10327         
10328         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10329                 int offset = 1;
10330                 size = AOP_SIZE(result);
10331                 
10332                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10333                 
10334                 emitpcode(POC_CLRF,   popGet(AOP(result),0));
10335                 emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10336                 emitpcode(POC_INCF,   popGet(AOP(result),0));
10337                 
10338                 while (size--)
10339                         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
10340                 
10341                 goto release;
10342         }
10343         
10344         if (IS_PTR(restype))
10345         {
10346           operand *result = IC_RESULT(ic);
10347           //operand *left = IC_LEFT(ic);
10348           operand *right = IC_RIGHT(ic);
10349           int tag = 0xff;
10350           
10351           /* copy common part */
10352           int max, size = AOP_SIZE(result);
10353           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10354           DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10355
10356           /* warn if we discard generic opinter tag */
10357           if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10358           {
10359             //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10360           } // if
10361
10362           max = size;
10363           while (size--)
10364           {
10365             mov2w_op (right, size);
10366             movwf (AOP(result), size);
10367           } // while
10368
10369           /* upcast into generic pointer type? */
10370           if (IS_GENPTR(restype)
10371                 && (size < AOP_SIZE(result))
10372                 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10373           {
10374             //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10375             if (IS_PTR(rtype))
10376             {
10377               switch (DCL_TYPE(rtype))
10378               {
10379               case POINTER:     /* __data */
10380               case FPOINTER:    /* __data */
10381                 assert (AOP_SIZE(right) == 2);
10382                 tag = GPTRTAG_DATA;
10383                 break;
10384
10385               case CPOINTER:    /* __code */
10386                 assert (AOP_SIZE(right) == 2);
10387                 tag = GPTRTAG_CODE;
10388                 break;
10389                 
10390               case GPOINTER:    /* unknown destination, __data or __code */
10391                 /* assume __data space (address of immediate) */
10392                 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10393                 if (AOP(right)->code)
10394                   tag = GPTRTAG_CODE;
10395                 else
10396                   tag = GPTRTAG_DATA;
10397                 break;
10398                 
10399               default:
10400                 assert (!"unhandled pointer type");
10401               } // switch
10402             } else {
10403               /* convert other values into pointers to __data space */
10404               tag = GPTRTAG_DATA;
10405             }
10406
10407             assert (AOP_SIZE(result) == 3);
10408             if (tag == 0) {
10409               emitpcode(POC_CLRF, popGet(AOP(result), 2));
10410             } else {
10411               emitpcode(POC_MOVLW, popGetLit(tag));
10412               movwf(AOP(result), 2);
10413             }
10414           } else {
10415             addSign(result, max, 0);
10416           } // if
10417           goto release;
10418         }
10419         
10420         /* if they are the same size : or less */
10421         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10422                 
10423                 /* if they are in the same place */
10424                 if (pic14_sameRegs(AOP(right),AOP(result)))
10425                         goto release;
10426                 
10427                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10428                 if (IS_PTR_CONST(rtype))
10429                         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10430                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10431                         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10432                 
10433                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10434                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10435                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
10436                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10437                         emitpcode(POC_MOVWF, popGet(AOP(result),1));
10438                         if(AOP_SIZE(result) <2)
10439                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10440                         
10441                 } else {
10442                         
10443                         /* if they in different places then copy */
10444                         size = AOP_SIZE(result);
10445                         offset = 0 ;
10446                         while (size--) {
10447                                 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10448                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10449                                 
10450                                 //aopPut(AOP(result),
10451                                 // aopGet(AOP(right),offset,FALSE,FALSE),
10452                                 // offset);
10453                                 
10454                                 offset++;
10455                         }
10456                 }
10457                 goto release;
10458         }
10459         
10460         /* so we now know that the size of destination is greater
10461         than the size of the source.
10462         Now, if the next iCode is an operator then we might be
10463         able to optimize the operation without performing a cast.
10464         */
10465         if(0 && genMixedOperation(ic)) {
10466                 /* XXX: cannot optimize: must copy regs! */
10467                 goto release;
10468         }
10469         
10470         /* we move to result for the size of source */
10471         size = AOP_SIZE(right);
10472         offset = 0 ;
10473         while (size--) {
10474                 emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
10475                 emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
10476                 offset++;
10477         }
10478
10479         addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10480
10481 release:
10482         freeAsmop(right,NULL,ic,TRUE);
10483         freeAsmop(result,NULL,ic,TRUE);
10484         
10485 }
10486
10487 /*-----------------------------------------------------------------*/
10488 /* genDjnz - generate decrement & jump if not zero instrucion      */
10489 /*-----------------------------------------------------------------*/
10490 static int genDjnz (iCode *ic, iCode *ifx)
10491 {
10492         symbol *lbl, *lbl1;
10493         FENTRY;
10494         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10495         
10496         if (!ifx)
10497                 return 0;
10498         
10499                 /* if the if condition has a false label
10500         then we cannot save */
10501         if (IC_FALSE(ifx))
10502                 return 0;
10503         
10504                 /* if the minus is not of the form 
10505         a = a - 1 */
10506         if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10507                 !IS_OP_LITERAL(IC_RIGHT(ic)))
10508                 return 0;
10509         
10510         if (operandLitValue(IC_RIGHT(ic)) != 1)
10511                 return 0;
10512         
10513                 /* if the size of this greater than one then no
10514         saving */
10515         if (getSize(operandType(IC_RESULT(ic))) > 1)
10516                 return 0;
10517         
10518         /* otherwise we can save BIG */
10519         lbl = newiTempLabel(NULL);
10520         lbl1= newiTempLabel(NULL);
10521         
10522         aopOp(IC_RESULT(ic),ic,FALSE);
10523         
10524         if (IS_AOP_PREG(IC_RESULT(ic))) {
10525                 pic14_emitcode("dec","%s",
10526                         aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10527                 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10528                 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10529         } else {  
10530                 
10531                 
10532                 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10533                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10534                 
10535                 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10536                 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10537                 
10538         }
10539         /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10540         /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10541         /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10542         /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10543         
10544         
10545         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10546         ifx->generated = 1;
10547         return 1;
10548 }
10549
10550 /*-----------------------------------------------------------------*/
10551 /* genReceive - generate code for a receive iCode                  */
10552 /*-----------------------------------------------------------------*/
10553 static void genReceive (iCode *ic)
10554 {
10555         FENTRY;
10556         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10557         
10558         if (isOperandInFarSpace(IC_RESULT(ic)) &&
10559                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10560                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10561                 
10562                 int size = getSize(operandType(IC_RESULT(ic)));
10563                 int offset =  fReturnSizePic - size;
10564                 while (size--) {
10565                         pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10566                                 fReturn[fReturnSizePic - offset - 1] : "acc"));
10567                         offset++;
10568                 }
10569                 aopOp(IC_RESULT(ic),ic,FALSE);
10570                 size = AOP_SIZE(IC_RESULT(ic));
10571                 offset = 0;
10572                 while (size--) {
10573                         pic14_emitcode ("pop","acc");
10574                         aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10575                 }
10576                 
10577         } else {
10578                 _G.accInUse++;
10579                 aopOp(IC_RESULT(ic),ic,FALSE);
10580                 _G.accInUse--;
10581                 GpsuedoStkPtr = ic->parmBytes; // address used arg on stack
10582                 assignResultValue(IC_RESULT(ic));
10583         }
10584         
10585         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10586 }
10587
10588 /*-----------------------------------------------------------------*/
10589 /* genDummyRead - generate code for dummy read of volatiles        */
10590 /*-----------------------------------------------------------------*/
10591 static void
10592 genDummyRead (iCode * ic)
10593 {
10594         FENTRY;
10595         pic14_emitcode ("; genDummyRead","");
10596         pic14_emitcode ("; not implemented","");
10597         
10598         ic = ic;
10599 }
10600
10601 /*-----------------------------------------------------------------*/
10602 /* genpic14Code - generate code for pic14 based controllers        */
10603 /*-----------------------------------------------------------------*/
10604 /*
10605 * At this point, ralloc.c has gone through the iCode and attempted
10606 * to optimize in a way suitable for a PIC. Now we've got to generate
10607 * PIC instructions that correspond to the iCode.
10608 *
10609 * Once the instructions are generated, we'll pass through both the
10610 * peep hole optimizer and the pCode optimizer.
10611 *-----------------------------------------------------------------*/
10612
10613 void genpic14Code (iCode *lic)
10614 {
10615         iCode *ic;
10616         int cln = 0;
10617         const char *cline;
10618         
10619         FENTRY;
10620         lineHead = lineCurr = NULL;
10621         
10622         pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10623         addpBlock(pb);
10624         
10625         /* if debug information required */
10626         if (options.debug && currFunc) { 
10627                 if (currFunc) {
10628                         debugFile->writeFunction (currFunc, lic);
10629                 }
10630         }
10631         
10632         
10633         for (ic = lic ; ic ; ic = ic->next ) {
10634                 
10635                 //DEBUGpic14_emitcode(";ic","");
10636                 //fprintf (stderr, "in ic loop\n");
10637                 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10638                 //ic->lineno, printCLine(ic->filename, ic->lineno));
10639                 
10640                 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10641                   cln = ic->lineno;
10642                   //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10643                   cline = printCLine (ic->filename, ic->lineno);
10644                   if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10645                   addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10646                   //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10647                 }
10648                 
10649                 if (options.iCodeInAsm) {
10650                   char *iLine = printILine(ic);
10651                   emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10652                   dbuf_free(iLine);
10653                 }
10654                 /* if the result is marked as
10655                 spilt and rematerializable or code for
10656                 this has already been generated then
10657                 do nothing */
10658                 if (resultRemat(ic) || ic->generated ) 
10659                         continue ;
10660                 
10661                 /* depending on the operation */
10662                 switch (ic->op) {
10663                 case '!' :
10664                         genNot(ic);
10665                         break;
10666                         
10667                 case '~' :
10668                         genCpl(ic);
10669                         break;
10670                         
10671                 case UNARYMINUS:
10672                         genUminus (ic);
10673                         break;
10674                         
10675                 case IPUSH:
10676                         genIpush (ic);
10677                         break;
10678                         
10679                 case IPOP:
10680                         /* IPOP happens only when trying to restore a 
10681                         spilt live range, if there is an ifx statement
10682                         following this pop then the if statement might
10683                         be using some of the registers being popped which
10684                         would destory the contents of the register so
10685                         we need to check for this condition and handle it */
10686                         if (ic->next            && 
10687                                 ic->next->op == IFX &&
10688                                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10689                                 genIfx (ic->next,ic);
10690                         else
10691                                 genIpop (ic);
10692                         break; 
10693                         
10694                 case CALL:
10695                         genCall (ic);
10696                         break;
10697                         
10698                 case PCALL:
10699                         genPcall (ic);
10700                         break;
10701                         
10702                 case FUNCTION:
10703                         genFunction (ic);
10704                         break;
10705                         
10706                 case ENDFUNCTION:
10707                         genEndFunction (ic);
10708                         break;
10709                         
10710                 case RETURN:
10711                         genRet (ic);
10712                         break;
10713                         
10714                 case LABEL:
10715                         genLabel (ic);
10716                         break;
10717                         
10718                 case GOTO:
10719                         genGoto (ic);
10720                         break;
10721                         
10722                 case '+' :
10723                         genPlus (ic) ;
10724                         break;
10725                         
10726                 case '-' :
10727                         if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10728                                 genMinus (ic);
10729                         break;
10730                         
10731                 case '*' :
10732                         genMult (ic);
10733                         break;
10734                         
10735                 case '/' :
10736                         genDiv (ic) ;
10737                         break;
10738                         
10739                 case '%' :
10740                         genMod (ic);
10741                         break;
10742                         
10743                 case '>' :
10744                         genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));         
10745                         break;
10746                         
10747                 case '<' :
10748                         genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10749                         break;
10750                         
10751                 case LE_OP:
10752                 case GE_OP:
10753                 case NE_OP:
10754                         
10755                         /* note these two are xlated by algebraic equivalence
10756                         during parsing SDCC.y */
10757                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10758                                 "got '>=' or '<=' shouldn't have come here");
10759                         break;  
10760                         
10761                 case EQ_OP:
10762                         genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10763                         break;      
10764                         
10765                 case AND_OP:
10766                         genAndOp (ic);
10767                         break;
10768                         
10769                 case OR_OP:
10770                         genOrOp (ic);
10771                         break;
10772                         
10773                 case '^' :
10774                         genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10775                         break;
10776                         
10777                 case '|' :
10778                         genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10779                         break;
10780                         
10781                 case BITWISEAND:
10782                         genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10783                         break;
10784                         
10785                 case INLINEASM:
10786                         genInline (ic);
10787                         break;
10788                         
10789                 case RRC:
10790                         genRRC (ic);
10791                         break;
10792                         
10793                 case RLC:
10794                         genRLC (ic);
10795                         break;
10796                         
10797                 case GETHBIT:
10798                         genGetHbit (ic);
10799                         break;
10800                         
10801                 case LEFT_OP:
10802                         genLeftShift (ic);
10803                         break;
10804                         
10805                 case RIGHT_OP:
10806                         genRightShift (ic);
10807                         break;
10808                         
10809                 case GET_VALUE_AT_ADDRESS:
10810                         genPointerGet(ic);
10811                         break;
10812                         
10813                 case '=' :
10814                         if (POINTER_SET(ic))
10815                                 genPointerSet(ic);
10816                         else
10817                                 genAssign(ic);
10818                         break;
10819                         
10820                 case IFX:
10821                         genIfx (ic,NULL);
10822                         break;
10823                         
10824                 case ADDRESS_OF:
10825                         genAddrOf (ic);
10826                         break;
10827                         
10828                 case JUMPTABLE:
10829                         genJumpTab (ic);
10830                         break;
10831                         
10832                 case CAST:
10833                         genCast (ic);
10834                         break;
10835                         
10836                 case RECEIVE:
10837                         genReceive(ic);
10838                         break;
10839                         
10840                 case SEND:
10841                         addSet(&_G.sendSet,ic);
10842                         break;
10843                         
10844                 case DUMMY_READ_VOLATILE:
10845                         genDummyRead (ic);
10846                         break;
10847                         
10848                 default :
10849                         fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10850                         ic = ic;
10851                         break;
10852                 }
10853         }
10854
10855         
10856         /* now we are ready to call the
10857         peep hole optimizer */
10858         if (!options.nopeep) {
10859                 peepHole (&lineHead);
10860         }
10861         /* now do the actual printing */
10862         printLine (lineHead,codeOutBuf);
10863         
10864 #ifdef PCODE_DEBUG
10865         DFPRINTF((stderr,"printing pBlock\n\n"));
10866         printpBlock(stdout,pb);
10867 #endif
10868         
10869         return;
10870 }
10871
10872 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10873  * (meaning: representing its own address) or not (referencing its contents).
10874  * This can only be decided based on the operand's type. */
10875 int
10876 aop_isLitLike (asmop *aop)
10877 {
10878   assert (aop);
10879   if (aop->type == AOP_LIT) return 1;
10880 if (aop->type == AOP_IMMD) return 1;
10881   if ((aop->type == AOP_PCODE) &&
10882                 ((aop->aopu.pcop->type == PO_LITERAL)))
10883   {
10884     /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10885      * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10886     return 1;
10887   }
10888   return 0;
10889 }
10890
10891 int
10892 op_isLitLike (operand *op)
10893 {
10894   assert (op);
10895   if (aop_isLitLike (AOP(op))) return 1;
10896   if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10897   if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;
10898   return 0;
10899 }