* src/pic/gen.c,
[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 /* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
48 #define PIC_IS_DATA_PTR(x)      (IS_DATA_PTR(x) || IS_FARPTR(x))
49 #define PIC_IS_FARPTR(x)        (PIC_IS_DATA_PTR(x))
50
51 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
52 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
53 void genMult8X8_8 (operand *, operand *,operand *);
54 extern void printpBlock(FILE *of, pBlock *pb);
55
56 static int labelOffset=0;
57 extern int debug_verbose;
58 extern int pic14_hasInterrupt;
59 //static int optimized_for_speed = 0;
60
61 /* max_key keeps track of the largest label number used in 
62 a function. This is then used to adjust the label offset
63 for the next function.
64 */
65 static int max_key=0;
66 static int GpsuedoStkPtr=0;
67 static int pic14_inISR = 0;
68
69 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
70 extern char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
71 const char *AopType(short type);
72
73 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
74
75 /* this is the down and dirty file with all kinds of 
76 kludgy & hacky stuff. This is what it is all about
77 CODE GENERATION for a specific MCU . some of the
78 routines may be reusable, will have to see */
79
80 static char *zero = "0x00";
81 static char *one  = "0x01";
82 static char *spname = "sp";
83
84 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
85 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
86 static char **fReturn = fReturnpic14;
87
88 //static char *accUse[] = {"a","b"};
89
90 //static short rbank = -1;
91
92 static struct {
93         short r0Pushed;
94         short r1Pushed;
95         short accInUse;
96         short inLine;
97         short debugLine;
98         short nRegsSaved;
99         set *sendSet;
100 } _G;
101
102 /* Resolved ifx structure. This structure stores information
103 about an iCode ifx that makes it easier to generate code.
104 */
105 typedef struct resolvedIfx {
106         symbol *lbl;     /* pointer to a label */
107         int condition;   /* true or false ifx */
108         int generated;   /* set true when the code associated with the ifx
109                           * is generated */
110 } resolvedIfx;
111
112 extern int pic14_ptrRegReq ;
113 extern int pic14_nRegs;
114 extern struct dbuf_s *codeOutBuf;
115 static void saverbank (int, iCode *,bool);
116
117 static lineNode *lineHead = NULL;
118 static lineNode *lineCurr = NULL;
119
120 #if 0
121 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
122 0xE0, 0xC0, 0x80, 0x00};
123 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
124 0x07, 0x03, 0x01, 0x00};
125 #endif
126
127 static  pBlock *pb;
128
129 /*-----------------------------------------------------------------*/
130 /*      my_powof2(n) - If `n' is an integaer power of 2, then the          */
131 /*                                 exponent of 2 is returned, otherwise -1 is      */
132 /*                                 returned.                                                                       */
133 /* note that this is similar to the function `powof2' in SDCCsymt  */
134 /* if(n == 2^y)                                                                                                    */
135 /*       return y;                                                                                                         */
136 /* return -1;                                                                                                      */
137 /*-----------------------------------------------------------------*/
138 static int my_powof2 (unsigned long num)
139 {
140         if(num) {
141                 if( (num & (num-1)) == 0) {
142                         int nshifts = -1;
143                         while(num) {
144                                 num>>=1;
145                                 nshifts++;
146                         }
147                         return nshifts;
148                 }
149         }
150         
151         return -1;
152 }
153
154 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
155 {
156         
157         DEBUGpic14_emitcode ("; ","line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
158                 line_no,
159                 ((result) ? AopType(AOP_TYPE(result)) : "-"),
160                 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
161                 ((result) ? AOP_SIZE(result) : 0),
162                 ((left)   ? AopType(AOP_TYPE(left)) : "-"),
163                 ((left)   ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
164                 ((left)   ? AOP_SIZE(left) : 0),
165                 ((right)  ? AopType(AOP_TYPE(right)) : "-"),
166                 ((right)  ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
167                 ((right)  ? AOP_SIZE(right) : 0));
168         
169 }
170
171 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
172 {
173         
174         DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
175                 line_no,
176                 ((result) ? AopType(AOP_TYPE(result)) : "-"),
177                 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
178                 ((left)   ? AopType(AOP_TYPE(left)) : "-"),
179                 ((left)   ? (SPEC_USIGN(operandType(left))       ? 'u' : 's') : '-'),
180                 ((right)  ? AopType(AOP_TYPE(right)) : "-"),
181                 ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
182         
183 }
184
185 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
186 {
187         va_list ap;
188         char lb[INITIAL_INLINEASM];  
189         unsigned char *lbp = (unsigned char *)lb;
190         
191         if(!debug_verbose && !options.debug)
192                 return;
193         
194         va_start(ap,fmt);   
195         
196         if (inst && *inst) {
197                 if (fmt && *fmt)
198                         sprintf(lb,"%s\t",inst);
199                 else
200                         sprintf(lb,"%s",inst);
201                 vsprintf(lb+(strlen(lb)),fmt,ap);
202         }  else
203                 vsprintf(lb,fmt,ap);
204         
205         while (isspace(*lbp)) lbp++;
206         
207         if (lbp && *lbp) 
208                 lineCurr = (lineCurr ?
209                 connectLine(lineCurr,newLineNode(lb)) :
210         (lineHead = newLineNode(lb)));
211         lineCurr->isInline = _G.inLine;
212         lineCurr->isDebug  = _G.debugLine;
213         
214         addpCode2pBlock(pb,newpCodeCharP(lb));
215         
216         va_end(ap);
217 }
218
219 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
220 {
221 #if defined (HAVE_VSNPRINTF)
222   vsnprintf (buf, size, fmt, ap);
223 #elif defined (HAVE_VSPRINTF)
224   vsprintf (buf, size, fmt, ap);
225   if (strlen (buf) >= size)
226   {
227     fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
228   }
229 #elif defined (HAVE_SNPRINTF)
230   snprintf (buf, size, "vs(n)printf required");
231 #elif defined (HAVE_SRINTF)
232   sprintf (buf, "vs(n)printf required");
233   if (strlen (buf) >= size)
234   {
235     fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
236   }
237 #else
238   assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
239 #endif
240 }
241
242 void emitpComment (const char *fmt, ...)
243 {
244   va_list va;
245   char buffer[4096];
246   
247   va_start (va, fmt);
248   if (pb) {
249     Safe_vsnprintf (buffer, 4096, fmt, va);
250     //fprintf (stderr, "%s\n" ,buffer);
251     addpCode2pBlock (pb, newpCodeCharP (buffer));
252 #if 0
253   } else {
254     Safe_vsnprintf (buffer, 4096, fmt, va);
255     fprintf (stderr, "No current pBlock -- discarding comment [%s]\n", buffer);
256 #endif
257   }
258   va_end (va);
259 }
260
261 void emitpLabel(int key)
262 {
263         addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
264 }
265
266 /* gen.h defines a macro emitpcode that should be used to call emitpcode
267  * as this allows for easy debugging (ever asked the question: where was
268  * this instruction geenrated? Here is the answer... */
269 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
270 {
271         if(pcop)
272                 addpCode2pBlock(pb,newpCode(poc,pcop));
273         else {
274                 static int has_warned = 0;
275                 
276                 DEBUGpic14_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
277                 if (!has_warned) {
278                         has_warned = 1;
279                         fprintf( stderr, "WARNING: encountered NULL pcop--this is probably a compiler bug...\n" );
280                 }
281         }
282 }
283
284 void emitpcodeNULLop(PIC_OPCODE poc)
285 {
286         
287         addpCode2pBlock(pb,newpCode(poc,NULL));
288         
289 }
290
291
292 /*-----------------------------------------------------------------*/
293 /* pic14_emitcode - writes the code into a file : for now it is simple    */
294 /*-----------------------------------------------------------------*/
295 void pic14_emitcode (char *inst,char *fmt, ...)
296 {
297         va_list ap;
298         char lb[INITIAL_INLINEASM];  
299         char *lbp = lb;
300         
301         va_start(ap,fmt);   
302         
303         if (inst && *inst) {
304                 if (fmt && *fmt)
305                         sprintf(lb,"%s\t",inst);
306                 else
307                         sprintf(lb,"%s",inst);
308                 vsprintf(lb+(strlen(lb)),fmt,ap);
309         }  else
310                 vsprintf(lb,fmt,ap);
311         
312         while (isspace(*lbp)) lbp++;
313         
314         if (lbp && *lbp) 
315                 lineCurr = (lineCurr ?
316                 connectLine(lineCurr,newLineNode(lb)) :
317         (lineHead = newLineNode(lb)));
318         lineCurr->isInline = _G.inLine;
319         lineCurr->isDebug  = _G.debugLine;
320         lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
321         
322         if(debug_verbose)
323                 addpCode2pBlock(pb,newpCodeCharP(lb));
324         
325         va_end(ap);
326 }
327
328 /*-----------------------------------------------------------------*/
329 /* pic14_emitDebuggerSymbol - associate the current code location  */
330 /*       with a debugger symbol                                                                            */
331 /*-----------------------------------------------------------------*/
332 void
333 pic14_emitDebuggerSymbol (char * debugSym)
334 {
335         _G.debugLine = 1;
336         pic14_emitcode ("", ";%s ==.", debugSym);
337         _G.debugLine = 0;
338 }
339
340 #if 0
341 /*-----------------------------------------------------------------*/
342 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
343 /*-----------------------------------------------------------------*/
344 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
345 {
346         bool r0iu = FALSE , r1iu = FALSE;
347         bool r0ou = FALSE , r1ou = FALSE;
348         
349         /* the logic: if r0 & r1 used in the instruction
350         then we are in trouble otherwise */
351         
352         /* first check if r0 & r1 are used by this
353         instruction, in which case we are in trouble */
354         if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
355                 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
356         {
357                 goto endOfWorld;          
358         }
359         
360         r0ou = bitVectBitValue(ic->rMask,R0_IDX);
361         r1ou = bitVectBitValue(ic->rMask,R1_IDX);
362         
363         /* if no usage of r0 then return it */
364         if (!r0iu && !r0ou) {
365                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
366                 (*aopp)->type = AOP_R0;
367                 
368                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
369         }
370         
371         /* if no usage of r1 then return it */
372         if (!r1iu && !r1ou) {
373                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
374                 (*aopp)->type = AOP_R1;
375                 
376                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
377         }    
378         
379         /* now we know they both have usage */
380         /* if r0 not used in this instruction */
381         if (!r0iu) {
382                 /* push it if not already pushed */
383                 if (!_G.r0Pushed) {
384                         //pic14_emitcode ("push","%s",
385                         //                pic14_regWithIdx(R0_IDX)->dname);
386                         _G.r0Pushed++ ;
387                 }
388                 
389                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
390                 (*aopp)->type = AOP_R0;
391                 
392                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
393         }
394         
395         /* if r1 not used then */
396         
397         if (!r1iu) {
398                 /* push it if not already pushed */
399                 if (!_G.r1Pushed) {
400                         //pic14_emitcode ("push","%s",
401                         //                pic14_regWithIdx(R1_IDX)->dname);
402                         _G.r1Pushed++ ;
403                 }
404                 
405                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
406                 (*aopp)->type = AOP_R1;
407                 return pic14_regWithIdx(R1_IDX);
408         }
409         
410 endOfWorld :
411         /* I said end of world but not quite end of world yet */
412         /* if this is a result then we can push it on the stack*/
413         if (result) {
414                 (*aopp)->type = AOP_STK;        
415                 return NULL;
416         }
417         
418         /* other wise this is true end of the world */
419         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
420                 "getFreePtr should never reach here");
421         exit(0);
422 }
423 #endif
424
425 /*-----------------------------------------------------------------*/
426 /* newAsmop - creates a new asmOp                                                                  */
427 /*-----------------------------------------------------------------*/
428 asmop *newAsmop (short type)
429 {
430         asmop *aop;
431         
432         aop = Safe_calloc(1,sizeof(asmop));
433         aop->type = type;
434         return aop;
435 }
436
437 static void genSetDPTR(int n)
438 {
439         if (!n)
440         {
441                 pic14_emitcode(";", "Select standard DPTR");
442                 pic14_emitcode("mov", "dps, #0x00");
443         }
444         else
445         {
446                 pic14_emitcode(";", "Select alternate DPTR");
447                 pic14_emitcode("mov", "dps, #0x01");
448         }
449 }
450
451 /*-----------------------------------------------------------------*/
452 /* resolveIfx - converts an iCode ifx into a form more useful for  */
453 /*                              generating code                                                                    */
454 /*-----------------------------------------------------------------*/
455 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
456 {
457         if(!resIfx) 
458                 return;
459         
460         //  DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
461         
462         resIfx->condition = 1;  /* assume that the ifx is true */
463         resIfx->generated = 0;  /* indicate that the ifx has not been used */
464         
465         if(!ifx) {
466                 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL);      / * oops, there is no ifx. so create a label */
467                                                                                         /*
468                                                                                         DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
469                                                                                         __FUNCTION__,__LINE__,resIfx->lbl->key);
470                 */
471         } else {
472                 if(IC_TRUE(ifx)) {
473                         resIfx->lbl = IC_TRUE(ifx);
474                 } else {
475                         resIfx->lbl = IC_FALSE(ifx);
476                         resIfx->condition = 0;
477                 }
478                 /*
479                 if(IC_TRUE(ifx)) 
480                 DEBUGpic14_emitcode("; ***","ifx true is non-null");
481                 if(IC_FALSE(ifx)) 
482                 DEBUGpic14_emitcode("; ***","ifx false is non-null");
483                 */
484         }
485         
486         //  DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
487         
488 }
489 /*-----------------------------------------------------------------*/
490 /* pointerCode - returns the code for a pointer type                       */
491 /*-----------------------------------------------------------------*/
492 #if 0
493 static int pointerCode (sym_link *etype)
494 {
495         
496         return PTR_TYPE(SPEC_OCLS(etype));
497         
498 }
499 #endif
500
501 /*-----------------------------------------------------------------*/
502 /* aopForSym - for a true symbol                                                                   */
503 /*-----------------------------------------------------------------*/
504 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
505 {
506         asmop *aop;
507         memmap *space= SPEC_OCLS(sym->etype);
508         
509         DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
510         /* if already has one */
511         if (sym->aop)
512                 return sym->aop;
513         
514         //DEBUGpic14_emitcode(";","%d",__LINE__);
515         /* if it is in direct space */
516         if (IN_DIRSPACE(space)) {
517                 sym->aop = aop = newAsmop (AOP_DIR);
518                 aop->aopu.aop_dir = sym->rname ;
519                 aop->size = getSize(sym->type);
520                 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
521                 return aop;
522         }
523         
524         /* special case for a function */
525         if (IS_FUNC(sym->type)) {   
526                 
527                 sym->aop = aop = newAsmop(AOP_PCODE);
528                 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
529                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
530                 PCOI(aop->aopu.pcop)->_function = 1;
531                 PCOI(aop->aopu.pcop)->index = 0;
532                 aop->size = FPTRSIZE; 
533                 /*
534                 sym->aop = aop = newAsmop(AOP_IMMD);    
535                 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
536                 strcpy(aop->aopu.aop_immd,sym->rname);
537                 aop->size = FPTRSIZE; 
538                 */
539                 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
540                 return aop;
541         }
542         
543         if (IS_ARRAY(sym->type)) {
544                 sym->aop = aop = newAsmop(AOP_PCODE);
545                 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
546                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
547                 PCOI(aop->aopu.pcop)->_function = 0;
548                 PCOI(aop->aopu.pcop)->index = 0;
549                 aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
550                 
551                 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
552                 return aop;
553         }
554         
555         /* only remaining is far space */
556         /* in which case DPTR gets the address */
557         sym->aop = aop = newAsmop(AOP_PCODE);
558         
559         aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
560         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
561         PCOI(aop->aopu.pcop)->index = 0;
562         
563         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
564                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
565         
566         allocDirReg (IC_LEFT(ic));
567         
568         aop->size = FPTRSIZE;
569         /*
570         DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
571         sym->aop = aop = newAsmop(AOP_DPTR);
572         pic14_emitcode ("mov","dptr,#%s", sym->rname);
573         aop->size = getSize(sym->type);
574         
575           DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
576         */
577         
578         /* if it is in code space */
579         if (IN_CODESPACE(space))
580                 aop->code = 1;
581         
582         return aop;       
583 }
584
585 /*-----------------------------------------------------------------*/
586 /* aopForRemat - rematerialzes an object                                                   */
587 /*-----------------------------------------------------------------*/
588 static asmop *aopForRemat (operand *op) // x symbol *sym)
589 {
590         symbol *sym = OP_SYMBOL(op);
591         iCode *ic = NULL;
592         asmop *aop = newAsmop(AOP_PCODE);
593         int val = 0;
594         int offset = 0;
595         
596         ic = sym->rematiCode;
597
598         DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
599         if(IS_OP_POINTER(op)) {
600                 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
601         }
602         for (;;) {
603                 if (ic->op == '+') {
604                         val += (int) operandLitValue(IC_RIGHT(ic));
605                 } else if (ic->op == '-') {
606                         val -= (int) operandLitValue(IC_RIGHT(ic));
607                 } else
608                         break;
609                 
610                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
611         }
612         
613         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
614         aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
615         PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
616         PCOI(aop->aopu.pcop)->index = val;
617         
618         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
619                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
620                 val, IS_PTR_CONST(operandType(op)));
621         
622         //      DEBUGpic14_emitcode(";","aop type  %s",AopType(AOP_TYPE(IC_LEFT(ic))));
623         
624         allocDirReg (IC_LEFT(ic));
625         
626         return aop;              
627 }
628
629 int aopIdx (asmop *aop, int offset)
630 {
631         if(!aop)
632                 return -1;
633         
634         if(aop->type !=  AOP_REG)
635                 return -2;
636         
637         return aop->aopu.aop_reg[offset]->rIdx;
638         
639 }
640 /*-----------------------------------------------------------------*/
641 /* regsInCommon - two operands have some registers in common       */
642 /*-----------------------------------------------------------------*/
643 static bool regsInCommon (operand *op1, operand *op2)
644 {
645         symbol *sym1, *sym2;
646         int i;
647         
648         /* if they have registers in common */
649         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
650                 return FALSE ;
651         
652         sym1 = OP_SYMBOL(op1);
653         sym2 = OP_SYMBOL(op2);
654         
655         if (sym1->nRegs == 0 || sym2->nRegs == 0)
656                 return FALSE ;
657         
658         for (i = 0 ; i < sym1->nRegs ; i++) {
659                 int j;
660                 if (!sym1->regs[i])
661                         continue ;
662                 
663                 for (j = 0 ; j < sym2->nRegs ;j++ ) {
664                         if (!sym2->regs[j])
665                                 continue ;
666                         
667                         if (sym2->regs[j] == sym1->regs[i])
668                                 return TRUE ;
669                 }
670         }
671         
672         return FALSE ;
673 }
674
675 /*-----------------------------------------------------------------*/
676 /* operandsEqu - equivalent                                                                        */
677 /*-----------------------------------------------------------------*/
678 static bool operandsEqu ( operand *op1, operand *op2)
679 {
680         symbol *sym1, *sym2;
681         
682         /* if they not symbols */
683         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
684                 return FALSE;
685         
686         sym1 = OP_SYMBOL(op1);
687         sym2 = OP_SYMBOL(op2);
688         
689         /* if both are itemps & one is spilt
690         and the other is not then false */
691         if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
692                 sym1->isspilt != sym2->isspilt )
693                 return FALSE ;
694         
695         /* if they are the same */
696         if (sym1 == sym2)
697                 return TRUE ;
698         
699         if (sym1->rname[0] && sym2->rname[0]
700                 && strcmp (sym1->rname, sym2->rname) == 0)
701                 return TRUE;
702         
703         
704         /* if left is a tmp & right is not */
705         if (IS_ITEMP(op1)  && 
706                 !IS_ITEMP(op2) &&
707                 sym1->isspilt  &&
708                 (sym1->usl.spillLoc == sym2))
709                 return TRUE;
710         
711         if (IS_ITEMP(op2)  && 
712                 !IS_ITEMP(op1) &&
713                 sym2->isspilt  &&
714                 sym1->level > 0 &&
715                 (sym2->usl.spillLoc == sym1))
716                 return TRUE ;
717         
718         return FALSE ;
719 }
720
721 /*-----------------------------------------------------------------*/
722 /* pic14_sameRegs - two asmops have the same registers             */
723 /*-----------------------------------------------------------------*/
724 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
725 {
726         int i;
727         
728         if (aop1 == aop2)
729                 return TRUE ;
730         
731         if (aop1->type != AOP_REG ||
732                 aop2->type != AOP_REG )
733                 return FALSE ;
734         
735         if (aop1->size != aop2->size )
736                 return FALSE ;
737         
738         for (i = 0 ; i < aop1->size ; i++ )
739                 if (aop1->aopu.aop_reg[i] !=
740                         aop2->aopu.aop_reg[i] )
741                         return FALSE ;
742                 
743                 return TRUE ;
744 }
745
746 /*-----------------------------------------------------------------*/
747 /* aopOp - allocates an asmop for an operand  :                    */
748 /*-----------------------------------------------------------------*/
749 void aopOp (operand *op, iCode *ic, bool result)
750 {
751         asmop *aop;
752         symbol *sym;
753         int i;
754         
755         if (!op)
756                 return ;
757         
758         /* if this a literal */
759         if (IS_OP_LITERAL(op)) {
760                 op->aop = aop = newAsmop(AOP_LIT);
761                 aop->aopu.aop_lit = op->operand.valOperand;
762                 aop->size = getSize(operandType(op));
763                 return;
764         }
765         
766         {
767                 sym_link *type = operandType(op);
768                 if(IS_PTR_CONST(type))
769                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
770         }
771         
772         /* if already has a asmop then continue */
773         if (op->aop)
774                 return ;
775         
776         /* if the underlying symbol has a aop */
777         if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
778                 DEBUGpic14_emitcode(";","%d",__LINE__);
779                 op->aop = OP_SYMBOL(op)->aop;
780                 return;
781         }
782         
783         /* if this is a true symbol */
784         if (IS_TRUE_SYMOP(op)) {          
785                 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
786                 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
787                 return ;
788         }
789         
790         /* this is a temporary : this has
791         only four choices :
792         a) register
793         b) spillocation
794         c) rematerialize 
795         d) conditional   
796         e) can be a return use only */
797         
798         sym = OP_SYMBOL(op);
799         
800         
801         /* if the type is a conditional */
802         if (sym->regType == REG_CND) {
803                 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
804                 aop->size = 0;
805                 return;
806         }
807         
808         /* if it is spilt then two situations
809         a) is rematerialize 
810         b) has a spill location */
811         if (sym->isspilt || sym->nRegs == 0) {
812                 
813                 DEBUGpic14_emitcode(";","%d",__LINE__);
814                 /* rematerialize it NOW */
815                 if (sym->remat) {
816                         
817                         sym->aop = op->aop = aop = aopForRemat (op);
818                         aop->size = getSize(sym->type);
819                         //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
820                         return;
821                 }
822                 
823 #if 0
824                 /* WREG is not usable as an ordinary operand with PIC architecture,
825                  * one might introduce a scratch register that can be used to make
826                  * WREG accesible as an operand... disable WREG for now */
827                 if (sym->accuse) {
828                         int i;
829                         aop = op->aop = sym->aop = newAsmop(AOP_ACC);
830                         aop->size = getSize(sym->type);
831                         for ( i = 0 ; i < 2 ; i++ )
832                                 aop->aopu.aop_str[i] = accUse[i];
833                         DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
834                         return;  
835                 }
836 #endif
837                 
838                 if (sym->ruonly ) {
839                         if(sym->isptr) {        // && sym->uptr 
840                                 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
841                                 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
842                                 
843                                 //PCOI(aop->aopu.pcop)->_const = 0;
844                                 //PCOI(aop->aopu.pcop)->index = 0;
845                                 /*
846                                 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
847                                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
848                                 */
849                                 //allocDirReg (IC_LEFT(ic));
850                                 
851                                 aop->size = getSize(sym->type);
852                                 DEBUGpic14_emitcode(";","%d",__LINE__);
853                                 return;
854                                 
855                         } else {
856                                 
857                                 unsigned i;
858                                 
859                                 aop = op->aop = sym->aop = newAsmop(AOP_STR);
860                                 aop->size = getSize(sym->type);
861                                 for ( i = 0 ; i < fReturnSizePic ; i++ )
862                                         aop->aopu.aop_str[i] = fReturn[i];
863                                 
864                                 DEBUGpic14_emitcode(";","%d",__LINE__);
865                                 return;
866                         }
867                 }
868                 
869                 /* else spill location  */
870                 if (sym->usl.spillLoc)
871                 {
872                         asmop *oldAsmOp = NULL;
873
874                         if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
875                         {
876                                 /* force a new aop if sizes differ */
877                                 oldAsmOp = sym->usl.spillLoc->aop;
878                                 sym->usl.spillLoc->aop = NULL;
879                         }
880                         DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
881                                 __FUNCTION__,__LINE__,
882                                 sym->usl.spillLoc->rname,
883                                 sym->rname, sym->usl.spillLoc->offset);
884                 
885                         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
886                         if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
887                         {
888                                 /* Don't reuse the new aop, go with the last one */
889                                 sym->usl.spillLoc->aop = oldAsmOp;
890                         }
891                         //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
892                         aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
893                                 getSize(sym->type), 
894                                 sym->usl.spillLoc->offset);
895                         aop->size = getSize(sym->type);
896                 
897                         return;
898                 }
899         }
900         
901         {
902                 sym_link *type = operandType(op);
903                 if(IS_PTR_CONST(type)) 
904                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
905         }
906         
907         /* must be in a register */
908         DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
909         sym->aop = op->aop = aop = newAsmop(AOP_REG);
910         aop->size = sym->nRegs;
911         for ( i = 0 ; i < sym->nRegs ;i++)
912                 aop->aopu.aop_reg[i] = sym->regs[i];
913 }
914
915 /*-----------------------------------------------------------------*/
916 /* freeAsmop - free up the asmop given to an operand                       */
917 /*----------------------------------------------------------------*/
918 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
919 {       
920         asmop *aop ;
921         
922         if (!op)
923                 aop = aaop;
924         else 
925                 aop = op->aop;
926         
927         if (!aop)
928                 return ;
929         
930         if (aop->freed)
931                 goto dealloc; 
932         
933         aop->freed = 1;
934         
935         /* depending on the asmop type only three cases need work AOP_RO
936         , AOP_R1 && AOP_STK */
937 #if 0
938         switch (aop->type) {
939         case AOP_R0 :
940                 if (_G.r0Pushed ) {
941                         if (pop) {
942                                 pic14_emitcode ("pop","ar0");     
943                                 _G.r0Pushed--;
944                         }
945                 }
946                 bitVectUnSetBit(ic->rUsed,R0_IDX);
947                 break;
948                 
949         case AOP_R1 :
950                 if (_G.r1Pushed ) {
951                         if (pop) {
952                                 pic14_emitcode ("pop","ar1");
953                                 _G.r1Pushed--;
954                         }
955                 }
956                 bitVectUnSetBit(ic->rUsed,R1_IDX);                      
957                 break;
958                 
959         case AOP_STK :
960                 {
961                         int sz = aop->size;      
962                         int stk = aop->aopu.aop_stk + aop->size;
963                         bitVectUnSetBit(ic->rUsed,R0_IDX);
964                         bitVectUnSetBit(ic->rUsed,R1_IDX);                
965                         
966                         getFreePtr(ic,&aop,FALSE);
967                         
968                         if (options.stack10bit)
969                         {
970                                 /* I'm not sure what to do here yet... */
971                                 /* #STUB */
972                                 fprintf(stderr, 
973                                         "*** Warning: probably generating bad code for "
974                                         "10 bit stack mode.\n");
975                         }
976                         
977                         if (stk) {
978                                 pic14_emitcode ("mov","a,_bp");
979                                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
980                                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
981                         } else {
982                                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
983                         }
984                         
985                         while (sz--) {
986                                 pic14_emitcode("pop","acc");
987                                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
988                                 if (!sz) break;
989                                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
990                         }
991                         op->aop = aop;
992                         freeAsmop(op,NULL,ic,TRUE);
993                         if (_G.r0Pushed) {
994                                 pic14_emitcode("pop","ar0");
995                                 _G.r0Pushed--;
996                         }
997                         
998                         if (_G.r1Pushed) {
999                                 pic14_emitcode("pop","ar1");
1000                                 _G.r1Pushed--;
1001                         }         
1002                 }
1003         }
1004 #endif
1005         
1006 dealloc:
1007         /* all other cases just dealloc */
1008         if (op ) {
1009                 op->aop = NULL;
1010                 if (IS_SYMOP(op)) {
1011                         OP_SYMBOL(op)->aop = NULL;      
1012                         /* if the symbol has a spill */
1013                         if (SPIL_LOC(op))
1014                                 SPIL_LOC(op)->aop = NULL;
1015                 }
1016         }
1017 }
1018
1019 /*-----------------------------------------------------------------*/
1020 /* aopGet - for fetching value of the aop                                                  */
1021 /*-----------------------------------------------------------------*/
1022 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1023 {
1024         char *s = buffer ;
1025         char *rs;
1026         
1027         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1028         /* offset is greater than
1029         size then zero */
1030         assert(aop);
1031         if (offset > (aop->size - 1) &&
1032                 aop->type != AOP_LIT)
1033                 return zero;
1034         
1035         /* depending on type */
1036         switch (aop->type) {
1037                 
1038         case AOP_R0:
1039         case AOP_R1:
1040                 DEBUGpic14_emitcode(";","%d",__LINE__);
1041                 /* if we need to increment it */           
1042                 while (offset > aop->coff) {            
1043                         pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);    
1044                         aop->coff++;
1045                 }
1046                 
1047                 while (offset < aop->coff) {
1048                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1049                         aop->coff--;
1050                 }
1051                 
1052                 aop->coff = offset ;
1053                 if (aop->paged) {
1054                         pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1055                         return (dname ? "acc" : "a");
1056                 }               
1057                 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1058                 rs = Safe_calloc(1,strlen(s)+1);
1059                 strcpy(rs,s);   
1060                 return rs;
1061                 
1062         case AOP_DPTR:
1063         case AOP_DPTR2:
1064                 DEBUGpic14_emitcode(";","%d",__LINE__);
1065                 if (aop->type == AOP_DPTR2)
1066                 {
1067                         genSetDPTR(1);
1068                 }
1069                 
1070                 while (offset > aop->coff) {
1071                         pic14_emitcode ("inc","dptr");
1072                         aop->coff++;
1073                 }
1074                 
1075                 while (offset < aop->coff) {            
1076                         pic14_emitcode("lcall","__decdptr");
1077                         aop->coff--;
1078                 }
1079                 
1080                 aop->coff = offset;
1081                 if (aop->code) {
1082                         pic14_emitcode("clr","a");
1083                         pic14_emitcode("movc","a,@a+dptr");
1084                 }
1085                 else {
1086                         pic14_emitcode("movx","a,@dptr");
1087                 }
1088                 
1089                 if (aop->type == AOP_DPTR2)
1090                 {
1091                         genSetDPTR(0);
1092                 }
1093                 
1094                 return (dname ? "acc" : "a");
1095                 
1096                 
1097         case AOP_IMMD:
1098                 if (bit16) 
1099                         sprintf (s,"%s",aop->aopu.aop_immd);
1100                 else
1101                         if (offset) 
1102                                 sprintf(s,"(%s >> %d)",
1103                                 aop->aopu.aop_immd,
1104                                 offset*8);
1105                         else
1106                                 sprintf(s,"%s",
1107                                 aop->aopu.aop_immd);
1108                         DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1109                         rs = Safe_calloc(1,strlen(s)+1);
1110                         strcpy(rs,s);   
1111                         return rs;
1112                         
1113         case AOP_DIR:
1114                 if (offset) {
1115                         sprintf(s,"(%s + %d)",
1116                                 aop->aopu.aop_dir,
1117                                 offset);
1118                         DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1119                 } else
1120                         sprintf(s,"%s",aop->aopu.aop_dir);
1121                 rs = Safe_calloc(1,strlen(s)+1);
1122                 strcpy(rs,s);   
1123                 return rs;
1124                 
1125         case AOP_REG:
1126                 //if (dname) 
1127                 //        return aop->aopu.aop_reg[offset]->dname;
1128                 //else
1129                 return aop->aopu.aop_reg[offset]->name;
1130                 
1131         case AOP_CRY:
1132                 //pic14_emitcode(";","%d",__LINE__);
1133                 return aop->aopu.aop_dir;
1134                 
1135         case AOP_ACC:
1136                 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1137                 return "AOP_accumulator_bug";
1138                 
1139         case AOP_LIT:
1140                 sprintf(s, "0x%02x", pic14aopLiteral (aop->aopu.aop_lit, offset));
1141                 rs = Safe_strdup(s);
1142                 return rs;
1143                 
1144         case AOP_STR:
1145                 aop->coff = offset ;
1146                 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1147                         dname)
1148                         return "acc";
1149                 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1150                 
1151                 return aop->aopu.aop_str[offset];
1152                 
1153         case AOP_PCODE:
1154                 {
1155                         pCodeOp *pcop = aop->aopu.pcop;
1156                         DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1157                         if(pcop->name) {
1158                                 if (pcop->type == PO_IMMEDIATE) {
1159                                         offset += PCOI(pcop)->index;
1160                                 }
1161                                 if (offset) {
1162                                         DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1163                                         sprintf(s,"(%s+%d)", pcop->name,offset);
1164                                 } else {
1165                                         DEBUGpic14_emitcode(";","%s",pcop->name);
1166                                         sprintf(s,"%s", pcop->name);
1167                                 }
1168                         } else
1169                                 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1170                         
1171                 }
1172                 rs = Safe_calloc(1,strlen(s)+1);
1173                 strcpy(rs,s);   
1174                 return rs;
1175                 
1176   }
1177   
1178   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1179           "aopget got unsupported aop->type");
1180   exit(0);
1181 }
1182
1183
1184 /*-----------------------------------------------------------------*/
1185 /* popGetTempReg - create a new temporary pCodeOp                                  */
1186 /*-----------------------------------------------------------------*/
1187 pCodeOp *popGetTempReg(void)
1188 {
1189         
1190         pCodeOp *pcop;
1191         
1192         pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1193         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1194                 PCOR(pcop)->r->wasUsed=1;
1195                 PCOR(pcop)->r->isFree=0;
1196         }
1197         
1198         return pcop;
1199 }
1200
1201 /*-----------------------------------------------------------------*/
1202 /* popReleaseTempReg - create a new temporary pCodeOp                              */
1203 /*-----------------------------------------------------------------*/
1204 void popReleaseTempReg(pCodeOp *pcop)
1205 {
1206         
1207         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1208                 PCOR(pcop)->r->isFree = 1;
1209         
1210 }
1211 /*-----------------------------------------------------------------*/
1212 /* popGetLabel - create a new pCodeOp of type PO_LABEL                     */
1213 /*-----------------------------------------------------------------*/
1214 pCodeOp *popGetLabel(unsigned int key)
1215 {
1216         
1217         DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1218         
1219         if(key>(unsigned int)max_key)
1220                 max_key = key;
1221         
1222         return newpCodeOpLabel(NULL,key+100+labelOffset);
1223 }
1224
1225 /*-------------------------------------------------------------------*/
1226 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1227 /*-------------------------------------------------------------------*/
1228 pCodeOp *popGetHighLabel(unsigned int key)
1229 {
1230         pCodeOp *pcop;
1231         pcop = popGetLabel(key);
1232         PCOLAB(pcop)->offset = 1;
1233         return pcop;
1234 }
1235
1236 /*-----------------------------------------------------------------*/
1237 /* popGetLit - asm operator to pcode operator conversion                           */
1238 /*-----------------------------------------------------------------*/
1239 pCodeOp *popGetLit(unsigned int lit)
1240 {
1241         
1242         return newpCodeOpLit((unsigned char)lit);
1243 }
1244
1245 /*-----------------------------------------------------------------*/
1246 /* popGetImmd - asm operator to pcode immediate conversion                 */
1247 /*-----------------------------------------------------------------*/
1248 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1249 {
1250         
1251         return newpCodeOpImmd(name, offset,index, 0, is_func);
1252 }
1253
1254 extern set *externs;
1255
1256 /*-----------------------------------------------------------------*/
1257 /* popGetWithString - asm operator to pcode operator conversion                    */
1258 /*-----------------------------------------------------------------*/
1259 pCodeOp *popGetWithString(char *str, int isExtern)
1260 {
1261         pCodeOp *pcop;
1262         
1263         
1264         if(!str) {
1265                 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1266                 exit (1);
1267         }
1268         
1269         pcop = newpCodeOp(str,PO_STR);
1270         PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1271
1272         return pcop;
1273 }
1274
1275 pCodeOp *popGetExternal (char *str)
1276 {
1277         pCodeOp *pcop = popGetWithString (str, 1);
1278         
1279         if (str) {
1280           symbol *sym;
1281
1282           for (sym = setFirstItem (externs); sym; sym = setNextItem (externs))
1283           {
1284             if (!strcmp (str, sym->rname)) break;
1285           }
1286           
1287           if (!sym)
1288           {
1289             sym = newSymbol(str, 0);
1290             strncpy(sym->rname, str, SDCC_NAME_MAX);
1291             addSet (&externs, sym);
1292           } // if
1293           sym->used++;
1294         }
1295         return pcop;
1296 }
1297
1298 /*-----------------------------------------------------------------*/
1299 /* popRegFromString -                                                                                      */
1300 /*-----------------------------------------------------------------*/
1301 pCodeOp *popRegFromString(char *str, int size, int offset)
1302 {
1303         
1304         pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1305         pcop->type = PO_DIR;
1306         
1307         DEBUGpic14_emitcode(";","%d",__LINE__);
1308         
1309         if(!str)
1310                 str = "BAD_STRING";
1311         
1312         pcop->name = Safe_calloc(1,strlen(str)+1);
1313         strcpy(pcop->name,str);
1314         
1315         //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1316         
1317         PCOR(pcop)->r = dirregWithName(pcop->name);
1318         if(PCOR(pcop)->r == NULL) {
1319                 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1320                 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1321                 DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1322         } else {
1323                 DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1324         }
1325         PCOR(pcop)->instance = offset;
1326         
1327         return pcop;
1328 }
1329
1330 /*-----------------------------------------------------------------*/
1331 /*-----------------------------------------------------------------*/
1332 pCodeOp *popRegFromIdx(int rIdx)
1333 {
1334         pCodeOp *pcop;
1335         
1336         DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1337                 __FUNCTION__,__LINE__,rIdx);
1338         
1339         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1340         
1341         PCOR(pcop)->rIdx = rIdx;
1342         PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1343         PCOR(pcop)->r->isFree = 0;
1344         PCOR(pcop)->r->wasUsed = 1;
1345         
1346         pcop->type = PCOR(pcop)->r->pc_type;
1347         
1348         
1349         return pcop;
1350 }
1351
1352 /*-----------------------------------------------------------------*/
1353 /* popGet - asm operator to pcode operator conversion                      */
1354 /*-----------------------------------------------------------------*/
1355 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1356 {
1357         //char *s = buffer ;
1358         //char *rs;
1359         
1360         pCodeOp *pcop;
1361         
1362         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1363         /* offset is greater than
1364         size then zero */
1365
1366         assert (aop);
1367
1368
1369         /* XXX: still needed for BIT operands (AOP_CRY) */
1370         if (offset > (aop->size - 1) &&
1371                 aop->type != AOP_LIT &&
1372                 aop->type != AOP_PCODE)
1373         {
1374                 printf( "%s: (offset[%d] > AOP_SIZE(op)[%d]-1) && AOP_TYPE(op) != AOP_LIT)\n", __FUNCTION__, offset, aop->size);
1375                 return NULL;  //zero;
1376         }
1377         
1378         /* depending on type */
1379         switch (aop->type) {
1380                 
1381         case AOP_R0:
1382         case AOP_R1:
1383         case AOP_DPTR:
1384         case AOP_DPTR2:
1385         case AOP_ACC:
1386                 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1387                 return NULL;
1388                 
1389         case AOP_IMMD:
1390                 DEBUGpic14_emitcode(";","%d",__LINE__);
1391                 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1392                 
1393         case AOP_DIR:
1394                 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1395 #if 0
1396                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1397                 pcop->type = PO_DIR;
1398                 
1399                 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1400                 strcpy(pcop->name,aop->aopu.aop_dir);   
1401                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1402                 if(PCOR(pcop)->r == NULL) {
1403                         //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1404                         PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1405                         DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1406                 } else {
1407                         DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1408                 }
1409                 PCOR(pcop)->instance = offset;
1410                 
1411                 return pcop;
1412 #endif
1413                 
1414         case AOP_REG:
1415                 {
1416                         int rIdx;
1417                         assert (offset < aop->size);
1418                         rIdx = aop->aopu.aop_reg[offset]->rIdx;
1419                         
1420                         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1421                         PCOR(pcop)->rIdx = rIdx;
1422                         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1423                         PCOR(pcop)->r->wasUsed=1;
1424                         PCOR(pcop)->r->isFree=0;
1425                         
1426                         PCOR(pcop)->instance = offset;
1427                         pcop->type = PCOR(pcop)->r->pc_type;
1428                         //rs = aop->aopu.aop_reg[offset]->name;
1429                         DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1430                         return pcop;
1431                 }
1432                 
1433         case AOP_CRY:
1434                 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1435                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1436                 //if(PCOR(pcop)->r == NULL)
1437                 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1438                 return pcop;
1439                 
1440         case AOP_LIT:
1441                 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1442                 
1443         case AOP_STR:
1444                 DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1445                 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1446                 /*
1447                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1448                 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1449                 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1450                 pcop->type = PCOR(pcop)->r->pc_type;
1451                 pcop->name = PCOR(pcop)->r->name;
1452                 
1453                   return pcop;
1454                 */
1455                 
1456         case AOP_PCODE:
1457                 pcop = NULL;
1458                 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1459                         __LINE__, 
1460                         ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1461                 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1462                 switch (aop->aopu.pcop->type)
1463                 {
1464                 case PO_IMMEDIATE:
1465                   pcop = pCodeOpCopy (aop->aopu.pcop);
1466                   /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1467                    * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1468                   PCOI(pcop)->index += offset;
1469                   //PCOI(pcop)->offset = 0;
1470                   break;
1471                 case PO_DIR:
1472                   pcop = pCodeOpCopy (aop->aopu.pcop);
1473                   PCOR(pcop)->instance = offset;
1474                   break;
1475                 default:
1476                   assert ( !"unhandled pCode type" );
1477                   break;
1478                 } // switch
1479                 return pcop;
1480         }
1481         
1482         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1483                 "popGet got unsupported aop->type");
1484         exit(0);
1485 }
1486
1487 /*-----------------------------------------------------------------*/
1488 /* popGetAddr - access the low/high word of a symbol (immediate)   */
1489 /*              (for non-PO_IMMEDIATEs this is the same as popGet) */
1490 /*-----------------------------------------------------------------*/
1491 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1492 {
1493   if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1494   {
1495     pCodeOp *pcop = aop->aopu.pcop;
1496     assert (offset <= GPTRSIZE);
1497
1498     /* special case: index >= 2 should return GPOINTER-style values */
1499     if (offset == 2)
1500     {
1501       pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1502       return pcop;
1503     }
1504     
1505     pcop = pCodeOpCopy (pcop);
1506     /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1507      * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1508     PCOI(pcop)->offset += offset;
1509     PCOI(pcop)->index += index;
1510     //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);
1511     return pcop;
1512   } else {
1513     return popGet (aop, offset + index);
1514   }
1515 }
1516
1517 /*-----------------------------------------------------------------*/
1518 /* aopPut - puts a string for a aop                                                        */
1519 /*-----------------------------------------------------------------*/
1520 void aopPut (asmop *aop, char *s, int offset)
1521 {
1522         char *d = buffer ;
1523         symbol *lbl ;
1524         
1525         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1526         
1527         if (aop->size && offset > ( aop->size - 1)) {
1528                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1529                         "aopPut got offset > aop->size");
1530                 exit(0);
1531         }
1532         
1533         /* will assign value to value */
1534         /* depending on where it is ofcourse */
1535         switch (aop->type) {
1536         case AOP_DIR:
1537                 if (offset) {
1538                         sprintf(d,"(%s + %d)",
1539                                 aop->aopu.aop_dir,offset);
1540                         fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1541                         
1542                 } else
1543                         sprintf(d,"%s",aop->aopu.aop_dir);
1544                 
1545                 if (strcmp(d,s)) {
1546                         DEBUGpic14_emitcode(";","%d",__LINE__);
1547                         if(strcmp(s,"W"))
1548                                 pic14_emitcode("movf","%s,w",s);
1549                         pic14_emitcode("movwf","%s",d);
1550                         
1551                         if(strcmp(s,"W")) {
1552                                 pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1553                                 if(offset >= aop->size) {
1554                                         emitpcode(POC_CLRF,popGet(aop,offset));
1555                                         break;
1556                                 } else {
1557                                         emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1558                                 }
1559                         }
1560                         emitpcode(POC_MOVWF,popGet(aop,offset));
1561                 
1562                 }
1563                 break;
1564                 
1565         case AOP_REG:
1566                 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1567                         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1568                         /*
1569                         if (*s == '@'             ||
1570                         strcmp(s,"r0") == 0 ||
1571                         strcmp(s,"r1") == 0 ||
1572                         strcmp(s,"r2") == 0 ||
1573                         strcmp(s,"r3") == 0 ||
1574                         strcmp(s,"r4") == 0 ||
1575                         strcmp(s,"r5") == 0 ||
1576                         strcmp(s,"r6") == 0 || 
1577                         strcmp(s,"r7") == 0 )
1578                         pic14_emitcode("mov","%s,%s  ; %d",
1579                         aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1580                         else
1581                         */
1582                         
1583                         if(strcmp(s,"W")==0 )
1584                                 pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1585                         
1586                         pic14_emitcode("movwf","%s",
1587                                 aop->aopu.aop_reg[offset]->name);
1588                         
1589                         if(strcmp(s,zero)==0) {
1590                                 emitpcode(POC_CLRF,popGet(aop,offset));
1591                                 
1592                         } else if(strcmp(s,"W")==0) {
1593                                 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1594                                 pcop->type = PO_GPR_REGISTER;
1595                                 
1596                                 PCOR(pcop)->rIdx = -1;
1597                                 PCOR(pcop)->r = NULL;
1598                                 
1599                                 DEBUGpic14_emitcode(";","%d",__LINE__);
1600                                 pcop->name = Safe_strdup(s);
1601                                 emitpcode(POC_MOVFW,pcop);
1602                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1603                         } else if(strcmp(s,one)==0) {
1604                                 emitpcode(POC_CLRF,popGet(aop,offset));
1605                                 emitpcode(POC_INCF,popGet(aop,offset));
1606                         } else {
1607                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1608                         }
1609                 }
1610                 break;
1611                 
1612         case AOP_DPTR:
1613         case AOP_DPTR2:
1614                 
1615                 if (aop->type == AOP_DPTR2)
1616                 {
1617                         genSetDPTR(1);
1618                 }
1619                 
1620                 if (aop->code) {
1621                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1622                                 "aopPut writting to code space");
1623                         exit(0);
1624                 }
1625                 
1626                 while (offset > aop->coff) {
1627                         aop->coff++;
1628                         pic14_emitcode ("inc","dptr");
1629                 }
1630                 
1631                 while (offset < aop->coff) {
1632                         aop->coff-- ;
1633                         pic14_emitcode("lcall","__decdptr");
1634                 }
1635                 
1636                 aop->coff = offset;
1637                 
1638                 /* if not in accumulater */
1639                 MOVA(s);
1640                 
1641                 pic14_emitcode ("movx","@dptr,a");
1642                 
1643                 if (aop->type == AOP_DPTR2)
1644                 {
1645                         genSetDPTR(0);
1646                 }
1647                 break;
1648                 
1649         case AOP_R0:
1650         case AOP_R1:
1651                 while (offset > aop->coff) {
1652                         aop->coff++;
1653                         pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1654                 }
1655                 while (offset < aop->coff) {
1656                         aop->coff-- ;
1657                         pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1658                 }
1659                 aop->coff = offset;
1660                 
1661                 if (aop->paged) {
1662                         MOVA(s);                         
1663                         pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1664                         
1665                 } else
1666                         if (*s == '@') {
1667                                 MOVA(s);
1668                                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1669                         } else
1670                                 if (strcmp(s,"r0") == 0 ||
1671                                         strcmp(s,"r1") == 0 ||
1672                                         strcmp(s,"r2") == 0 ||
1673                                         strcmp(s,"r3") == 0 ||
1674                                         strcmp(s,"r4") == 0 ||
1675                                         strcmp(s,"r5") == 0 ||
1676                                         strcmp(s,"r6") == 0 || 
1677                                         strcmp(s,"r7") == 0 ) {
1678                                         char buffer[10];
1679                                         sprintf(buffer,"a%s",s);
1680                                         pic14_emitcode("mov","@%s,%s",
1681                                                 aop->aopu.aop_ptr->name,buffer);
1682                                 } else
1683                                         pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1684                                 
1685                                 break;
1686                                 
1687         case AOP_STK:
1688                 if (strcmp(s,"a") == 0)
1689                         pic14_emitcode("push","acc");
1690                 else
1691                         pic14_emitcode("push","%s",s);
1692                 
1693                 break;
1694                 
1695         case AOP_CRY:
1696                 /* if bit variable */
1697                 if (!aop->aopu.aop_dir) {
1698                         pic14_emitcode("clr","a");
1699                         pic14_emitcode("rlc","a");
1700                 } else {
1701                         if (s == zero) 
1702                                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1703                         else
1704                                 if (s == one)
1705                                         pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1706                                 else
1707                                         if (!strcmp(s,"c"))
1708                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1709                                         else {
1710                                                 lbl = newiTempLabel(NULL);
1711                                                 
1712                                                 if (strcmp(s,"a")) {
1713                                                         MOVA(s);
1714                                                 }
1715                                                 pic14_emitcode("clr","c");
1716                                                 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1717                                                 pic14_emitcode("cpl","c");
1718                                                 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1719                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1720                                         }
1721                 }
1722                 break;
1723                 
1724         case AOP_STR:
1725                 aop->coff = offset;
1726                 if (strcmp(aop->aopu.aop_str[offset],s))
1727                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1728                 break;
1729                 
1730         case AOP_ACC:
1731                 aop->coff = offset;
1732                 if (!offset && (strcmp(s,"acc") == 0))
1733                         break;
1734                 
1735                 if (strcmp(aop->aopu.aop_str[offset],s))
1736                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1737                 break;
1738                 
1739         default :
1740                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1741                         "aopPut got unsupported aop->type");
1742                 exit(0);
1743         }
1744         
1745 }
1746
1747 /*-----------------------------------------------------------------*/
1748 /* mov2w_op - generate either a MOVLW or MOVFW based operand type  */
1749 /*-----------------------------------------------------------------*/
1750 static void mov2w_op (operand *op, int offset)
1751 {
1752         assert (op);
1753         FENTRY;
1754
1755         /* for PO_IMMEDIATEs: use address or value? */
1756         if (op_isLitLike (op))
1757         {
1758                 /* access address of op */
1759                 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1760                 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1761                 {
1762                         if (offset == GPTRSIZE-1)
1763                                 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1764                         else
1765                                 emitpcode (POC_MOVLW, popGetLit (0));
1766                 }
1767                 else
1768                         emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1769         } else {
1770                 /* access value stored in op */
1771                 mov2w (AOP(op), offset);
1772         }
1773 }
1774
1775
1776 /*-----------------------------------------------------------------*/
1777 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1778 /*-----------------------------------------------------------------*/
1779 void mov2w (asmop *aop, int offset)
1780 {
1781         
1782         if(!aop)
1783                 return;
1784         
1785         DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1786         
1787         if ( aop_isLitLike (aop) )
1788                 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1789         else
1790                 emitpcode(POC_MOVFW,popGet(aop,offset));
1791         
1792 }
1793
1794 static void movwf (asmop *op, int offset)
1795 {
1796         emitpcode (POC_MOVWF, popGet(op, offset));
1797 }
1798
1799 static pCodeOp *get_argument_pcop (int idx)
1800 {
1801         assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1802         return popRegFromIdx (Gstack_base_addr - (idx - 1));
1803 }
1804
1805 static pCodeOp *get_return_val_pcop (int offset)
1806 {
1807         assert (offset > 0 && "the most significant byte is returned via WREG");
1808         return popRegFromIdx (Gstack_base_addr - (offset - 1));
1809 }
1810
1811 static void pass_argument (operand *op, int offset, int idx)
1812 {
1813         if (op)
1814                 mov2w_op (op, offset);
1815         if (idx != 0)
1816                 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1817 }
1818
1819 static void get_returnvalue (operand *op, int offset, int idx)
1820 {
1821         if (idx != 0)
1822                 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1823         movwf(AOP(op), offset);
1824 }
1825
1826 static void call_libraryfunc (char *name)
1827 {
1828     symbol *sym;
1829
1830     /* library code might reside in different page... */
1831     emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1832     /* call the library function */
1833     emitpcode (POC_CALL, popGetExternal (name));
1834     /* might return from different page... */
1835     emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1836
1837     /* create symbol, mark it as `extern' */
1838     sym = findSym(SymbolTab, NULL, name);
1839     if (!sym) {
1840         sym = newSymbol(name, 0);
1841         strncpy(sym->rname, name, SDCC_NAME_MAX);
1842         addSym(SymbolTab, sym, sym->rname, 0, 0, 0);
1843         addSet(&externs, sym); 
1844     } // if
1845     sym->used++;
1846 }
1847
1848 #if 0
1849 /*-----------------------------------------------------------------*/
1850 /* reAdjustPreg - points a register back to where it should        */
1851 /*-----------------------------------------------------------------*/
1852 static void reAdjustPreg (asmop *aop)
1853 {
1854         int size ;
1855         
1856         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1857         aop->coff = 0;
1858         if ((size = aop->size) <= 1)
1859                 return ;
1860         size-- ;
1861         switch (aop->type) {
1862         case AOP_R0 :
1863         case AOP_R1 :
1864                 while (size--)
1865                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1866                 break;                  
1867         case AOP_DPTR :
1868         case AOP_DPTR2:
1869                 if (aop->type == AOP_DPTR2)
1870                 {
1871                         genSetDPTR(1);
1872                 } 
1873                 while (size--)
1874                 {
1875                         pic14_emitcode("lcall","__decdptr");
1876                 }
1877                 
1878                 if (aop->type == AOP_DPTR2)
1879                 {
1880                         genSetDPTR(0);
1881                 }
1882                 break;
1883                 
1884         }
1885         
1886 }
1887 #endif
1888
1889
1890 #if 0
1891 /*-----------------------------------------------------------------*/
1892 /* opIsGptr: returns non-zero if the passed operand is             */
1893 /* a generic pointer type.                                         */
1894 /*-----------------------------------------------------------------*/ 
1895 static int opIsGptr(operand *op)
1896 {
1897         sym_link *type = operandType(op);
1898         
1899         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1900         if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1901         {
1902                 return 1;
1903         }
1904         return 0;          
1905 }
1906 #endif
1907
1908 /*-----------------------------------------------------------------*/
1909 /* pic14_getDataSize - get the operand data size                   */
1910 /*-----------------------------------------------------------------*/
1911 int pic14_getDataSize(operand *op)
1912 {
1913         int size;
1914         
1915         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1916         
1917 #if 0
1918         size = getSize(OP_SYM_ETYPE(op));
1919         return size;
1920         //return AOP_SIZE(op);
1921         
1922         // tsd- in the pic port, the genptr size is 1, so this code here
1923         // fails. ( in the 8051 port, the size was 4).
1924 #else
1925         size = AOP_SIZE(op);
1926         if (IS_GENPTR(OP_SYM_TYPE(op)))
1927         {
1928                 sym_link *type = operandType(op);
1929                 if (IS_GENPTR(type))
1930                 {
1931                         /* generic pointer; arithmetic operations
1932                         * should ignore the high byte (pointer type).
1933                         */
1934                         size--;
1935                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1936                 }
1937         }
1938         return size;
1939 #endif
1940 }
1941
1942 /*-----------------------------------------------------------------*/
1943 /* pic14_outAcc - output Acc                                       */
1944 /*-----------------------------------------------------------------*/
1945 void pic14_outAcc(operand *result)
1946 {
1947         int size,offset;
1948         DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1949         DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1950         
1951         
1952         size = pic14_getDataSize(result);
1953         if(size){
1954                 emitpcode(POC_MOVWF,popGet(AOP(result),0));
1955                 size--;
1956                 offset = 1;
1957                 /* unsigned or positive */
1958                 while(size--)
1959                         emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1960         }
1961         
1962 }
1963
1964 /*-----------------------------------------------------------------*/
1965 /* pic14_outBitC - output a bit C                                  */
1966 /*-----------------------------------------------------------------*/
1967 void pic14_outBitC(operand *result)
1968 {
1969         
1970         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1971         /* if the result is bit */
1972         if (AOP_TYPE(result) == AOP_CRY) 
1973                 aopPut(AOP(result),"c",0);
1974         else {
1975                 pic14_emitcode("clr","a  ; %d", __LINE__);
1976                 pic14_emitcode("rlc","a");
1977                 pic14_outAcc(result);
1978         }
1979 }
1980
1981 /*-----------------------------------------------------------------*/
1982 /* pic14_toBoolean - emit code for orl a,operator(sizeop)          */
1983 /*-----------------------------------------------------------------*/
1984 void pic14_toBoolean(operand *oper)
1985 {
1986         int size = AOP_SIZE(oper);
1987         int offset = 0;
1988         
1989         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1990
1991         assert (size > 0);
1992
1993         if (size == 1) {
1994                 /* MOVFW does not load the flags... */
1995                 if (AOP_TYPE(oper) == AOP_ACC) {
1996                         emitpcode(POC_IORLW, popGetLit(0));
1997                         offset = 1;
1998                 } else {
1999                         emitpcode(POC_MOVLW, popGetLit(0));
2000                         offset = 0;
2001                 }
2002         } else {
2003                 if ( AOP_TYPE(oper) != AOP_ACC) {
2004                         emitpcode(POC_MOVFW,popGet(AOP(oper),0));
2005                         offset = 1;
2006                 }
2007         }
2008         
2009         while (offset < size) {
2010                 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
2011         }
2012         /* Z is set iff (oper == 0) */
2013 }
2014
2015
2016 /*-----------------------------------------------------------------*/
2017 /* genNot - generate code for ! operation                          */
2018 /*-----------------------------------------------------------------*/
2019 static void genNot (iCode *ic)
2020 {
2021         //symbol *tlbl;
2022         int size;
2023
2024         FENTRY;
2025         
2026         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2027         /* assign asmOps to operand & result */
2028         aopOp (IC_LEFT(ic),ic,FALSE);
2029         aopOp (IC_RESULT(ic),ic,TRUE);
2030         
2031         DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2032         /* if in bit space then a special case */
2033         if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2034                 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2035                         emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2036                         emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2037                 } else {
2038                         emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2039                         emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2040                         emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2041                 }
2042                 goto release;
2043         }
2044         
2045         size = AOP_SIZE(IC_LEFT(ic));
2046         mov2w (AOP(IC_LEFT(ic)),0);
2047         while (--size > 0)
2048         {
2049           if (op_isLitLike (IC_LEFT(ic)))
2050             emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2051           else
2052             emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2053         }
2054         emitpcode(POC_MOVLW, popGetLit (0));
2055         emitSKPNZ;
2056         emitpcode(POC_MOVLW, popGetLit (1));
2057         movwf(AOP(IC_RESULT(ic)), 0);
2058
2059         for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2060         {
2061           emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2062         }
2063         goto release;
2064         
2065 release:        
2066         /* release the aops */
2067         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2068         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2069 }
2070
2071
2072 /*-----------------------------------------------------------------*/
2073 /* genCpl - generate code for complement                                                   */
2074 /*-----------------------------------------------------------------*/
2075 static void genCpl (iCode *ic)
2076 {
2077         operand *left, *result;
2078         int size, offset=0;  
2079         
2080         FENTRY;
2081         
2082         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2083         aopOp((left = IC_LEFT(ic)),ic,FALSE);
2084         aopOp((result=IC_RESULT(ic)),ic,TRUE);
2085         
2086         /* if both are in bit space then 
2087         a special case */
2088         if (AOP_TYPE(result) == AOP_CRY &&
2089                 AOP_TYPE(left) == AOP_CRY ) { 
2090                 
2091                 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir); 
2092                 pic14_emitcode("cpl","c"); 
2093                 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir); 
2094                 goto release; 
2095         } 
2096         
2097         size = AOP_SIZE(result);
2098         if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2099         while (size--) {
2100                 
2101                 if(AOP_TYPE(left) == AOP_ACC) 
2102                         emitpcode(POC_XORLW, popGetLit(0xff));
2103                 else
2104                         emitpcode(POC_COMFW,popGet(AOP(left),offset));
2105                 
2106                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2107                 offset++;
2108         }
2109         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2110         
2111         
2112 release:
2113         /* release the aops */
2114         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2115         freeAsmop(result,NULL,ic,TRUE);
2116 }
2117
2118 /*-----------------------------------------------------------------*/
2119 /* genUminusFloat - unary minus for floating points                        */
2120 /*-----------------------------------------------------------------*/
2121 static void genUminusFloat(operand *op,operand *result)
2122 {
2123         int size ,offset =0 ;
2124         char *l;
2125         
2126         FENTRY;
2127
2128         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2129         /* for this we just need to flip the 
2130         first it then copy the rest in place */
2131         size = AOP_SIZE(op) - 1;
2132         l = aopGet(AOP(op),3,FALSE,FALSE);
2133         
2134         MOVA(l);          
2135         
2136         pic14_emitcode("cpl","acc.7");
2137         aopPut(AOP(result),"a",3);      
2138         
2139         while(size--) {
2140                 aopPut(AOP(result),
2141                         aopGet(AOP(op),offset,FALSE,FALSE),
2142                         offset);
2143                 offset++;
2144         }                
2145 }
2146
2147 /*-----------------------------------------------------------------*/
2148 /* genUminus - unary minus code generation                                                 */
2149 /*-----------------------------------------------------------------*/
2150 static void genUminus (iCode *ic)
2151 {
2152         int size, i;
2153         sym_link *optype, *rtype;
2154         
2155         FENTRY;
2156         
2157         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2158         /* assign asmops */
2159         aopOp(IC_LEFT(ic),ic,FALSE);
2160         aopOp(IC_RESULT(ic),ic,TRUE);
2161         
2162         /* if both in bit space then special
2163         case */
2164         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2165                 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2166                 
2167                 emitpcode(POC_BCF,       popGet(AOP(IC_RESULT(ic)),0));
2168                 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2169                 emitpcode(POC_BSF,       popGet(AOP(IC_RESULT(ic)),0));
2170                 
2171                 goto release; 
2172         } 
2173         
2174         optype = operandType(IC_LEFT(ic));
2175         rtype = operandType(IC_RESULT(ic));
2176         
2177         /* if float then do float stuff */
2178         if (IS_FLOAT(optype)) {
2179                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2180                 goto release;
2181         }
2182         
2183         /* otherwise subtract from zero by taking the 2's complement */
2184         size = AOP_SIZE(IC_LEFT(ic));
2185         
2186         for(i=0; i<size; i++) {
2187                 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2188                         emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
2189                 else {
2190                         emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2191                         emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2192                 }
2193         }
2194         
2195         emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
2196         for(i=1; i<size; i++) {
2197                 emitSKPNZ;
2198                 emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
2199         }
2200         
2201 release:
2202         /* release the aops */
2203         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2204         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);  
2205 }
2206
2207 /*-----------------------------------------------------------------*/
2208 /* saveRegisters - will look for a call and save the registers     */
2209 /*-----------------------------------------------------------------*/
2210 static void saveRegisters(iCode *lic) 
2211 {
2212         int i;
2213         iCode *ic;
2214         bitVect *rsave;
2215         sym_link *dtype;
2216         
2217         FENTRY;
2218
2219         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2220         /* look for call */
2221         for (ic = lic ; ic ; ic = ic->next) 
2222                 if (ic->op == CALL || ic->op == PCALL)
2223                         break;
2224                 
2225                 if (!ic) {
2226                         fprintf(stderr,"found parameter push with no function call\n");
2227                         return ;
2228                 }
2229                 
2230                 /* if the registers have been saved already then
2231                 do nothing */
2232                 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2233                         return ;
2234                 
2235                         /* find the registers in use at this time 
2236                 and push them away to safety */
2237                 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2238                         ic->rUsed);
2239                 
2240                 ic->regsSaved = 1;
2241                 if (options.useXstack) {
2242                         if (bitVectBitValue(rsave,R0_IDX))
2243                                 pic14_emitcode("mov","b,r0");
2244                         pic14_emitcode("mov","r0,%s",spname);
2245                         for (i = 0 ; i < pic14_nRegs ; i++) {
2246                                 if (bitVectBitValue(rsave,i)) {
2247                                         if (i == R0_IDX)
2248                                                 pic14_emitcode("mov","a,b");
2249                                         else
2250                                                 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2251                                         pic14_emitcode("movx","@r0,a");
2252                                         pic14_emitcode("inc","r0");
2253                                 }
2254                         }
2255                         pic14_emitcode("mov","%s,r0",spname);
2256                         if (bitVectBitValue(rsave,R0_IDX))
2257                                 pic14_emitcode("mov","r0,b");     
2258                 }// else
2259                 //for (i = 0 ; i < pic14_nRegs ; i++) {
2260                 //        if (bitVectBitValue(rsave,i))
2261                 //      pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2262                 //}
2263                 
2264                 dtype = operandType(IC_LEFT(ic));
2265                 if (currFunc && dtype && 
2266                         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2267                         IFFUNC_ISISR(currFunc->type) &&
2268                         !ic->bankSaved) 
2269                         
2270                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2271                 
2272 }
2273 /*-----------------------------------------------------------------*/
2274 /* unsaveRegisters - pop the pushed registers                                      */
2275 /*-----------------------------------------------------------------*/
2276 static void unsaveRegisters (iCode *ic)
2277 {
2278         int i;
2279         bitVect *rsave;
2280         
2281         FENTRY;
2282
2283         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2284         /* find the registers in use at this time 
2285         and push them away to safety */
2286         rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2287                 ic->rUsed);
2288         
2289         if (options.useXstack) {
2290                 pic14_emitcode("mov","r0,%s",spname); 
2291                 for (i =  pic14_nRegs ; i >= 0 ; i--) {
2292                         if (bitVectBitValue(rsave,i)) {
2293                                 pic14_emitcode("dec","r0");
2294                                 pic14_emitcode("movx","a,@r0");
2295                                 if (i == R0_IDX)
2296                                         pic14_emitcode("mov","b,a");
2297                                 else
2298                                         pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2299                         }       
2300                         
2301                 }
2302                 pic14_emitcode("mov","%s,r0",spname);
2303                 if (bitVectBitValue(rsave,R0_IDX))
2304                         pic14_emitcode("mov","r0,b");
2305         } //else
2306         //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2307         //      if (bitVectBitValue(rsave,i))
2308         //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2309         //}
2310         
2311 }  
2312
2313
2314 /*-----------------------------------------------------------------*/
2315 /* pushSide -                            */
2316 /*-----------------------------------------------------------------*/
2317 static void pushSide(operand * oper, int size)
2318 {
2319 #if 0
2320         int offset = 0;
2321         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2322         while (size--) {
2323                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2324                 if (AOP_TYPE(oper) != AOP_REG &&
2325                         AOP_TYPE(oper) != AOP_DIR &&
2326                         strcmp(l,"a") ) {
2327                         pic14_emitcode("mov","a,%s",l);
2328                         pic14_emitcode("push","acc");
2329                 } else
2330                         pic14_emitcode("push","%s",l);
2331         }
2332 #endif
2333 }
2334
2335 /*-----------------------------------------------------------------*/
2336 /* assignResultValue -                           */
2337 /*-----------------------------------------------------------------*/
2338 static void assignResultValue(operand * oper)
2339 {
2340         int size = AOP_SIZE(oper);
2341         int offset = 0;
2342         
2343         FENTRY;
2344
2345         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2346         
2347         DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2348         
2349         /* assign MSB first (passed via WREG) */
2350         while (size--) {
2351                 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2352                 GpsuedoStkPtr++;
2353         }
2354 }
2355
2356
2357 /*-----------------------------------------------------------------*/
2358 /* genIpush - genrate code for pushing this gets a little complex  */
2359 /*-----------------------------------------------------------------*/
2360 static void genIpush (iCode *ic)
2361 {
2362         FENTRY;
2363         
2364         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2365 #if 0
2366         int size, offset = 0 ;
2367         char *l;
2368         
2369         
2370         /* if this is not a parm push : ie. it is spill push 
2371         and spill push is always done on the local stack */
2372         if (!ic->parmPush) {
2373                 
2374                 /* and the item is spilt then do nothing */
2375                 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2376                         return ;
2377                 
2378                 aopOp(IC_LEFT(ic),ic,FALSE);
2379                 size = AOP_SIZE(IC_LEFT(ic));
2380                 /* push it on the stack */
2381                 while(size--) {
2382                         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2383                         if (*l == '#') {
2384                                 MOVA(l);
2385                                 l = "acc";
2386                         }
2387                         pic14_emitcode("push","%s",l);
2388                 }
2389                 return ;                
2390         }
2391         
2392         /* this is a paramter push: in this case we call
2393         the routine to find the call and save those
2394         registers that need to be saved */   
2395         saveRegisters(ic);
2396         
2397         /* then do the push */
2398         aopOp(IC_LEFT(ic),ic,FALSE);
2399         
2400         
2401         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2402         size = AOP_SIZE(IC_LEFT(ic));
2403         
2404         while (size--) {
2405                 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2406                 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2407                         AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2408                         strcmp(l,"a") ) {
2409                         pic14_emitcode("mov","a,%s",l);
2410                         pic14_emitcode("push","acc");
2411                 } else
2412                         pic14_emitcode("push","%s",l);
2413         }         
2414         
2415         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2416 #endif
2417 }
2418
2419 /*-----------------------------------------------------------------*/
2420 /* genIpop - recover the registers: can happen only for spilling   */
2421 /*-----------------------------------------------------------------*/
2422 static void genIpop (iCode *ic)
2423 {
2424         FENTRY;
2425
2426         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2427         assert (!"genIpop -- unimplemented");
2428 #if 0
2429         int size,offset ;
2430         
2431         
2432         /* if the temp was not pushed then */
2433         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2434                 return ;
2435         
2436         aopOp(IC_LEFT(ic),ic,FALSE);
2437         size = AOP_SIZE(IC_LEFT(ic));
2438         offset = (size-1);
2439         while (size--) 
2440                 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2441                 FALSE,TRUE));
2442         
2443         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2444 #endif
2445 }
2446
2447 /*-----------------------------------------------------------------*/
2448 /* unsaverbank - restores the resgister bank from stack                    */
2449 /*-----------------------------------------------------------------*/
2450 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2451 {
2452         FENTRY;
2453
2454         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2455 #if 0
2456         int i;
2457         asmop *aop ;
2458         regs *r = NULL;
2459         
2460         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2461         if (popPsw) {
2462                 if (options.useXstack) {
2463                         aop = newAsmop(0);
2464                         r = getFreePtr(ic,&aop,FALSE);
2465                         
2466                         
2467                         pic14_emitcode("mov","%s,_spx",r->name);
2468                         pic14_emitcode("movx","a,@%s",r->name);
2469                         pic14_emitcode("mov","psw,a");
2470                         pic14_emitcode("dec","%s",r->name);
2471                         
2472                 }else
2473                         pic14_emitcode ("pop","psw");
2474         }
2475         
2476         for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2477                 if (options.useXstack) {           
2478                         pic14_emitcode("movx","a,@%s",r->name);
2479                         //pic14_emitcode("mov","(%s+%d),a",
2480                         //         regspic14[i].base,8*bank+regspic14[i].offset);
2481                         pic14_emitcode("dec","%s",r->name);
2482                         
2483                 } else 
2484                         pic14_emitcode("pop",""); //"(%s+%d)",
2485                 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2486         }
2487         
2488         if (options.useXstack) {
2489                 
2490                 pic14_emitcode("mov","_spx,%s",r->name);
2491                 freeAsmop(NULL,aop,ic,TRUE);
2492                 
2493         }
2494 #endif 
2495 }
2496
2497 /*-----------------------------------------------------------------*/
2498 /* saverbank - saves an entire register bank on the stack                  */
2499 /*-----------------------------------------------------------------*/
2500 static void saverbank (int bank, iCode *ic, bool pushPsw)
2501 {
2502         FENTRY;
2503
2504         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2505 #if 0
2506         int i;
2507         asmop *aop ;
2508         regs *r = NULL;
2509         
2510         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2511         if (options.useXstack) {
2512                 
2513                 aop = newAsmop(0);
2514                 r = getFreePtr(ic,&aop,FALSE);  
2515                 pic14_emitcode("mov","%s,_spx",r->name);
2516                 
2517         }
2518         
2519         for (i = 0 ; i < pic14_nRegs ;i++) {
2520                 if (options.useXstack) {
2521                         pic14_emitcode("inc","%s",r->name);
2522                         //pic14_emitcode("mov","a,(%s+%d)",
2523                         //               regspic14[i].base,8*bank+regspic14[i].offset);
2524                         pic14_emitcode("movx","@%s,a",r->name);                 
2525                 } else 
2526                         pic14_emitcode("push","");// "(%s+%d)",
2527                 //regspic14[i].base,8*bank+regspic14[i].offset);
2528         }
2529         
2530         if (pushPsw) {
2531                 if (options.useXstack) {
2532                         pic14_emitcode("mov","a,psw");
2533                         pic14_emitcode("movx","@%s,a",r->name); 
2534                         pic14_emitcode("inc","%s",r->name);
2535                         pic14_emitcode("mov","_spx,%s",r->name);                 
2536                         freeAsmop (NULL,aop,ic,TRUE);
2537                         
2538                 } else
2539                         pic14_emitcode("push","psw");
2540                 
2541                 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2542         }
2543         ic->bankSaved = 1;
2544 #endif
2545 }
2546
2547 /*-----------------------------------------------------------------*/
2548 /* genCall - generates a call statement                                                    */
2549 /*-----------------------------------------------------------------*/
2550 static void genCall (iCode *ic)
2551 {
2552         sym_link *dtype;         
2553         symbol *sym;
2554         char *name;
2555         int isExtern;
2556         
2557         FENTRY;
2558
2559         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2560         
2561         /* if caller saves & we have not saved then */
2562         if (!ic->regsSaved)
2563                 saveRegisters(ic);
2564         
2565                 /* if we are calling a function that is not using
2566                 the same register bank then we need to save the
2567         destination registers on the stack */
2568         dtype = operandType(IC_LEFT(ic));
2569         if (currFunc && dtype && 
2570                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2571                 IFFUNC_ISISR(currFunc->type) &&
2572                 !ic->bankSaved) 
2573                 
2574                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2575         
2576         /* if send set is not empty the assign */
2577         if (_G.sendSet) {
2578                 iCode *sic;
2579                 /* For the Pic port, there is no data stack.
2580                 * So parameters passed to functions are stored
2581                 * in registers. (The pCode optimizer will get
2582                 * rid of most of these :).
2583                 */
2584                 int psuedoStkPtr=-1;
2585                 int firstTimeThruLoop = 1;
2586                 
2587                 _G.sendSet = reverseSet(_G.sendSet);
2588                 
2589                 /* First figure how many parameters are getting passed */
2590                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2591                 sic = setNextItem(_G.sendSet)) {
2592                         
2593                         aopOp(IC_LEFT(sic),sic,FALSE);
2594                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2595                         freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2596                 }
2597                 
2598                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2599                 sic = setNextItem(_G.sendSet)) {
2600                         int size, offset = 0;
2601                         
2602                         aopOp(IC_LEFT(sic),sic,FALSE);
2603                         size = AOP_SIZE(IC_LEFT(sic));
2604                         
2605                         while (size--) {
2606                                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2607                                         AopType(AOP_TYPE(IC_LEFT(sic))));
2608                                 
2609                                 if(!firstTimeThruLoop) {
2610                                         /* If this is not the first time we've been through the loop
2611                                         * then we need to save the parameter in a temporary
2612                                         * register. The last byte of the last parameter is
2613                                         * passed in W. */
2614                                         emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2615                                         
2616                                 }
2617                                 firstTimeThruLoop=0;
2618                                 
2619                                 mov2w_op (IC_LEFT(sic),  offset);
2620                                 offset++;
2621                         }
2622                         freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2623                 }
2624                 _G.sendSet = NULL;
2625         }
2626         /* make the call */
2627         sym = OP_SYMBOL(IC_LEFT(ic));
2628         name = sym->rname[0] ? sym->rname : sym->name;
2629         isExtern = IS_EXTERN(sym->etype) || pic14_inISR;
2630         if (isExtern) {
2631                 /* Extern functions and ISRs maybe on a different page;
2632                  * must call pagesel */
2633                 emitpcode(POC_PAGESEL,popGetWithString(name,1));
2634         }
2635         emitpcode(POC_CALL,popGetWithString(name,isExtern));
2636         if (isExtern) {
2637                 /* May have returned from a different page;
2638                  * must use pagesel to restore PCLATH before next
2639                  * goto or call instruction */
2640                 emitpcode(POC_PAGESEL,popGetWithString("$",0));
2641         }
2642         GpsuedoStkPtr=0;
2643         /* if we need assign a result value */
2644         if ((IS_ITEMP(IC_RESULT(ic)) && 
2645                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2646                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2647                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2648                 
2649                 _G.accInUse++;
2650                 aopOp(IC_RESULT(ic),ic,FALSE);
2651                 _G.accInUse--;
2652                 
2653                 assignResultValue(IC_RESULT(ic));
2654                 
2655                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2656                         AopType(AOP_TYPE(IC_RESULT(ic))));
2657                 
2658                 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2659         }
2660         
2661         /* if register bank was saved then pop them */
2662         if (ic->bankSaved)
2663                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2664         
2665         /* if we hade saved some registers then unsave them */
2666         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2667                 unsaveRegisters (ic);
2668         
2669         
2670 }
2671
2672 /*-----------------------------------------------------------------*/
2673 /* genPcall - generates a call by pointer statement                        */
2674 /*-----------------------------------------------------------------*/
2675 static void genPcall (iCode *ic)
2676 {
2677         sym_link *dtype;
2678         symbol *albl = newiTempLabel(NULL);
2679         symbol *blbl = newiTempLabel(NULL);
2680         PIC_OPCODE poc;
2681         pCodeOp *pcop;
2682         operand *left;
2683         
2684         FENTRY;
2685
2686         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2687         /* if caller saves & we have not saved then */
2688         if (!ic->regsSaved)
2689                 saveRegisters(ic);
2690         
2691                 /* if we are calling a function that is not using
2692                 the same register bank then we need to save the
2693         destination registers on the stack */
2694         dtype = operandType(IC_LEFT(ic));
2695         if (currFunc && dtype && 
2696                 IFFUNC_ISISR(currFunc->type) &&
2697                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2698                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2699         
2700         left = IC_LEFT(ic);
2701         aopOp(left,ic,FALSE);
2702         DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2703         
2704         poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2705         
2706         pushSide(IC_LEFT(ic), FPTRSIZE);
2707         
2708         /* if send set is not empty, assign parameters */
2709         if (_G.sendSet) {
2710                 
2711                 DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2712                 /* no way to pass args - W always gets used to make the call */
2713         }
2714         /* first idea - factor out a common helper function and call it.
2715         But don't know how to get it generated only once in its own block
2716         
2717         if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2718                 char *rname;
2719                 char *buffer;
2720                 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2721                 DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2722                 buffer = Safe_calloc(1,strlen(rname)+16);
2723                 sprintf(buffer, "%s_goto_helper", rname);
2724                 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2725                 free(buffer);
2726         }
2727         */
2728         emitpcode(POC_CALL,popGetLabel(albl->key));
2729         pcop = popGetLabel(blbl->key);
2730         emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2731         emitpcode(POC_GOTO,pcop);
2732         emitpLabel(albl->key);
2733         
2734         emitpcode(poc,popGetAddr(AOP(left),1,0));
2735         emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2736         emitpcode(poc,popGetAddr(AOP(left),0,0));
2737         emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2738         
2739         emitpLabel(blbl->key);
2740         
2741         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2742         
2743         /* if we need to assign a result value */
2744         if ((IS_ITEMP(IC_RESULT(ic)) &&
2745                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2746                 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2747                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2748                 
2749                 _G.accInUse++;
2750                 aopOp(IC_RESULT(ic),ic,FALSE);
2751                 _G.accInUse--;
2752
2753                 GpsuedoStkPtr = 0;
2754                 
2755                 assignResultValue(IC_RESULT(ic));
2756                 
2757                 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2758         }
2759         
2760         /* if register bank was saved then unsave them */
2761         if (currFunc && dtype && 
2762                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2763                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2764         
2765                 /* if we hade saved some registers then
2766         unsave them */
2767         if (ic->regsSaved)
2768                 unsaveRegisters (ic);
2769         
2770 }
2771
2772 /*-----------------------------------------------------------------*/
2773 /* resultRemat - result  is rematerializable                                       */
2774 /*-----------------------------------------------------------------*/
2775 static int resultRemat (iCode *ic)
2776 {
2777         //      DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2778         FENTRY;
2779
2780         if (SKIP_IC(ic) || ic->op == IFX)
2781                 return 0;
2782         
2783         if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2784                 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2785                 if (sym->remat && !POINTER_SET(ic)) 
2786                         return 1;
2787         }
2788         
2789         return 0;
2790 }
2791
2792 #if 0
2793 /*-----------------------------------------------------------------*/
2794 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2795 /*-----------------------------------------------------------------*/
2796 static bool inExcludeList(char *s)
2797 {
2798         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2799         int i =0;
2800         
2801         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2802         if (options.excludeRegs[i] &&
2803                 STRCASECMP(options.excludeRegs[i],"none") == 0)
2804                 return FALSE ;
2805         
2806         for ( i = 0 ; options.excludeRegs[i]; i++) {
2807                 if (options.excludeRegs[i] &&
2808                         STRCASECMP(s,options.excludeRegs[i]) == 0)
2809                         return TRUE;
2810         }
2811         return FALSE ;
2812 }
2813 #endif
2814
2815 /*-----------------------------------------------------------------*/
2816 /* genFunction - generated code for function entry                                 */
2817 /*-----------------------------------------------------------------*/
2818 static void genFunction (iCode *ic)
2819 {
2820         symbol *sym;
2821         sym_link *ftype;
2822         
2823         FENTRY;
2824
2825         DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2826         
2827         labelOffset += (max_key+4);
2828         max_key=0;
2829         GpsuedoStkPtr=0;
2830         _G.nRegsSaved = 0;
2831         /* create the function header */
2832         pic14_emitcode(";","-----------------------------------------");
2833         pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2834         pic14_emitcode(";","-----------------------------------------");
2835         
2836         /* prevent this symbol from being emitted as 'extern' */
2837         pic14_stringInSet(sym->rname, &pic14_localFunctions, 1);
2838
2839         pic14_emitcode("","%s:",sym->rname);
2840         addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2841
2842         /* mark symbol as NOT extern (even if it was declared so previously) */
2843         assert(IS_SPEC(sym->etype));
2844         SPEC_EXTR(sym->etype) = 0;
2845         sym->cdef = 0;
2846         if (!SPEC_OCLS(sym->etype)) SPEC_OCLS(sym->etype) = code;
2847         addSetIfnotP(&SPEC_OCLS(sym->etype)->syms, sym);
2848         
2849         ftype = operandType(IC_LEFT(ic));
2850         
2851         /* if critical function then turn interrupts off */
2852         if (IFFUNC_ISCRITICAL(ftype))
2853                 pic14_emitcode("clr","ea");
2854         
2855                 /* here we need to generate the equates for the
2856         register bank if required */
2857 #if 0
2858         if (FUNC_REGBANK(ftype) != rbank) {
2859                 int i ;
2860                 
2861                 rbank = FUNC_REGBANK(ftype);
2862                 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2863                         if (strcmp(regspic14[i].base,"0") == 0)
2864                                 pic14_emitcode("","%s = 0x%02x",
2865                                 regspic14[i].dname,
2866                                 8*rbank+regspic14[i].offset);
2867                         else
2868                                 pic14_emitcode ("","%s = %s + 0x%02x",
2869                                 regspic14[i].dname,
2870                                 regspic14[i].base,
2871                                 8*rbank+regspic14[i].offset);
2872                 }
2873         }
2874 #endif
2875         
2876         /* if this is an interrupt service routine */
2877         pic14_inISR = 0;
2878         if (IFFUNC_ISISR(sym->type)) {
2879                 pic14_inISR = 1;
2880         /*  already done in pic14createInterruptVect() - delete me
2881         addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2882         emitpcodeNULLop(POC_NOP);
2883         emitpcodeNULLop(POC_NOP);
2884         emitpcodeNULLop(POC_NOP);
2885                 */
2886                 emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2887                 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2888                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2889                 emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2890                 emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2891                 emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2892                 emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2893                 
2894                 pBlockConvert2ISR(pb);
2895                 pic14_hasInterrupt = 1;
2896 #if 0  
2897                 if (!inExcludeList("acc"))              
2898                         pic14_emitcode ("push","acc");  
2899                 if (!inExcludeList("b"))
2900                         pic14_emitcode ("push","b");
2901                 if (!inExcludeList("dpl"))
2902                         pic14_emitcode ("push","dpl");
2903                 if (!inExcludeList("dph"))
2904                         pic14_emitcode ("push","dph");
2905                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2906                 {
2907                         pic14_emitcode ("push", "dpx");
2908                         /* Make sure we're using standard DPTR */
2909                         pic14_emitcode ("push", "dps");
2910                         pic14_emitcode ("mov", "dps, #0x00");
2911                         if (options.stack10bit)
2912                         { 
2913                                 /* This ISR could conceivably use DPTR2. Better save it. */
2914                                 pic14_emitcode ("push", "dpl1");
2915                                 pic14_emitcode ("push", "dph1");
2916                                 pic14_emitcode ("push", "dpx1");
2917                         }
2918                 }
2919                 /* if this isr has no bank i.e. is going to
2920                 run with bank 0 , then we need to save more
2921                 registers :-) */
2922                 if (!FUNC_REGBANK(sym->type)) {
2923                         
2924                 /* if this function does not call any other
2925                 function then we can be economical and
2926                         save only those registers that are used */
2927                         if (! IFFUNC_HASFCALL(sym->type)) {
2928                                 int i;
2929                                 
2930                                 /* if any registers used */
2931                                 if (sym->regsUsed) {
2932                                         /* save the registers used */
2933                                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2934                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2935                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2936                                                         pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);               
2937                                         }
2938                                 }
2939                                 
2940                         } else {
2941                         /* this function has    a function call cannot
2942                         determines register usage so we will have the
2943                                 entire bank */
2944                                 saverbank(0,ic,FALSE);
2945                         }       
2946                 }
2947 #endif
2948         } else {
2949         /* if callee-save to be used for this function
2950                 then save the registers being used in this function */
2951                 if (IFFUNC_CALLEESAVES(sym->type)) {
2952                         int i;
2953                         
2954                         /* if any registers used */
2955                         if (sym->regsUsed) {
2956                                 /* save the registers used */
2957                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2958                                         if (bitVectBitValue(sym->regsUsed,i) ||
2959                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2960                                                 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2961                                                 _G.nRegsSaved++;
2962                                         }
2963                                 }
2964                         }
2965                 }
2966         }
2967         
2968         /* set the register bank to the desired value */
2969         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2970                 pic14_emitcode("push","psw");
2971                 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);       
2972         }
2973         
2974         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2975                 
2976                 if (options.useXstack) {
2977                         pic14_emitcode("mov","r0,%s",spname);
2978                         pic14_emitcode("mov","a,_bp");
2979                         pic14_emitcode("movx","@r0,a");
2980                         pic14_emitcode("inc","%s",spname);
2981                 }
2982                 else
2983                 {
2984                         /* set up the stack */
2985                         pic14_emitcode ("push","_bp");   /* save the callers stack      */
2986                 }
2987                 pic14_emitcode ("mov","_bp,%s",spname);
2988         }
2989         
2990         /* adjust the stack for the function */
2991         if (sym->stack) {
2992                 
2993                 int i = sym->stack;
2994                 if (i > 256 ) 
2995                         werror(W_STACK_OVERFLOW,sym->name);
2996                 
2997                 if (i > 3 && sym->recvSize < 4) {                
2998                         
2999                         pic14_emitcode ("mov","a,sp");
3000                         pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3001                         pic14_emitcode ("mov","sp,a");
3002                         
3003                 }
3004                 else
3005                         while(i--)
3006                                 pic14_emitcode("inc","sp");
3007         }
3008         
3009         if (sym->xstack) {
3010                 
3011                 pic14_emitcode ("mov","a,_spx");
3012                 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3013                 pic14_emitcode ("mov","_spx,a");
3014         }
3015         
3016 }
3017
3018 /*-----------------------------------------------------------------*/
3019 /* genEndFunction - generates epilogue for functions                       */
3020 /*-----------------------------------------------------------------*/
3021 static void genEndFunction (iCode *ic)
3022 {
3023         symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3024         
3025         FENTRY;
3026
3027         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3028         
3029         if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3030         {
3031                 pic14_emitcode ("mov","%s,_bp",spname);
3032         }
3033         
3034         /* if use external stack but some variables were
3035         added to the local stack then decrement the
3036         local stack */
3037         if (options.useXstack && sym->stack) {    
3038                 pic14_emitcode("mov","a,sp");
3039                 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3040                 pic14_emitcode("mov","sp,a");
3041         }
3042         
3043         
3044         if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3045                 if (options.useXstack) {
3046                         pic14_emitcode("mov","r0,%s",spname);
3047                         pic14_emitcode("movx","a,@r0");
3048                         pic14_emitcode("mov","_bp,a");
3049                         pic14_emitcode("dec","%s",spname);
3050                 }
3051                 else
3052                 {
3053                         pic14_emitcode ("pop","_bp");
3054                 }
3055         }
3056         
3057         /* restore the register bank    */        
3058         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3059                 pic14_emitcode ("pop","psw");
3060         
3061         if (IFFUNC_ISISR(sym->type)) {
3062                 
3063                 /* now we need to restore the registers */
3064                 /* if this isr has no bank i.e. is going to
3065                 run with bank 0 , then we need to save more
3066 registers :-) */
3067                 if (!FUNC_REGBANK(sym->type)) {
3068                         
3069                 /* if this function does not call any other
3070                 function then we can be economical and
3071                         save only those registers that are used */
3072                         if (! IFFUNC_HASFCALL(sym->type)) {
3073                                 int i;
3074                                 
3075                                 /* if any registers used */
3076                                 if (sym->regsUsed) {
3077                                         /* save the registers used */
3078                                         for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3079                                                 if (bitVectBitValue(sym->regsUsed,i) ||
3080                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3081                                                         pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3082                                         }
3083                                 }
3084                                 
3085                         } else {
3086                         /* this function has    a function call cannot
3087                         determines register usage so we will have the
3088                                 entire bank */
3089                                 unsaverbank(0,ic,FALSE);
3090                         }       
3091                 }
3092 #if 0
3093                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3094                 {
3095                         if (options.stack10bit)
3096                         {
3097                                 pic14_emitcode ("pop", "dpx1");
3098                                 pic14_emitcode ("pop", "dph1");
3099                                 pic14_emitcode ("pop", "dpl1");
3100                         } 
3101                         pic14_emitcode ("pop", "dps");
3102                         pic14_emitcode ("pop", "dpx");
3103                 }
3104                 if (!inExcludeList("dph"))
3105                         pic14_emitcode ("pop","dph");
3106                 if (!inExcludeList("dpl"))
3107                         pic14_emitcode ("pop","dpl");
3108                 if (!inExcludeList("b"))
3109                         pic14_emitcode ("pop","b");
3110                 if (!inExcludeList("acc"))
3111                         pic14_emitcode ("pop","acc");
3112                 
3113                 if (IFFUNC_ISCRITICAL(sym->type))
3114                         pic14_emitcode("setb","ea");
3115 #endif
3116                 
3117                 /* if debug then send end of function */
3118                 if (options.debug && debugFile && currFunc) {
3119                         debugFile->writeEndFunction (currFunc, ic, 1);
3120                 }
3121                 
3122                 pic14_emitcode ("reti","");
3123                 emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
3124                 emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
3125                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
3126                 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3127                 emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
3128                 emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
3129                 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3130                 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3131                 emitpcodeNULLop(POC_RETFIE);
3132         }
3133         else {
3134                 if (IFFUNC_ISCRITICAL(sym->type))
3135                         pic14_emitcode("setb","ea");
3136                 
3137                 if (IFFUNC_CALLEESAVES(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                 }
3151                 
3152                 /* if debug then send end of function */
3153                 if (options.debug && debugFile && currFunc) {
3154                         debugFile->writeEndFunction (currFunc, ic, 1);
3155                 }
3156                 
3157                 pic14_emitcode ("return","");
3158                 emitpcodeNULLop(POC_RETURN);
3159                 
3160                 /* Mark the end of a function */
3161                 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3162         }
3163         
3164 }
3165
3166 /*-----------------------------------------------------------------*/
3167 /* genRet - generate code for return statement                                     */
3168 /*-----------------------------------------------------------------*/
3169 static void genRet (iCode *ic)
3170 {
3171         int size,offset = 0;
3172         
3173         FENTRY;
3174
3175         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3176         /* if we have no return value then
3177         just generate the "ret" */
3178         if (!IC_LEFT(ic)) 
3179                 goto jumpret;           
3180         
3181                 /* we have something to return then
3182         move the return value into place */
3183         aopOp(IC_LEFT(ic),ic,FALSE);
3184         size = AOP_SIZE(IC_LEFT(ic));
3185
3186         for (offset = 0; offset < size; offset++)
3187         {
3188                 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3189         }
3190         
3191         freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3192         
3193 jumpret:
3194         /* generate a jump to the return label
3195         if the next is not the return statement */
3196         if (!(ic->next && ic->next->op == LABEL &&
3197                 IC_LABEL(ic->next) == returnLabel)) {
3198                 
3199                 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3200         }
3201         
3202 }
3203
3204 /*-----------------------------------------------------------------*/
3205 /* genLabel - generates a label                                                                    */
3206 /*-----------------------------------------------------------------*/
3207 static void genLabel (iCode *ic)
3208 {
3209         FENTRY;
3210
3211         /* special case never generate */
3212         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3213         if (IC_LABEL(ic) == entryLabel)
3214                 return ;
3215         
3216         emitpLabel(IC_LABEL(ic)->key);
3217         pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3218 }
3219
3220 /*-----------------------------------------------------------------*/
3221 /* genGoto - generates a goto                                                                      */
3222 /*-----------------------------------------------------------------*/
3223 //tsd
3224 static void genGoto (iCode *ic)
3225 {
3226         FENTRY;
3227
3228         emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3229         pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3230 }
3231
3232
3233 /*-----------------------------------------------------------------*/
3234 /* genMultbits :- multiplication of bits                                                   */
3235 /*-----------------------------------------------------------------*/
3236 static void genMultbits (operand *left, 
3237                                                  operand *right, 
3238                                                  operand *result)
3239 {
3240         FENTRY;
3241         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3242         
3243         if(!pic14_sameRegs(AOP(result),AOP(right)))
3244                 emitpcode(POC_BSF,      popGet(AOP(result),0));
3245         
3246         emitpcode(POC_BTFSC,popGet(AOP(right),0));
3247         emitpcode(POC_BTFSS,popGet(AOP(left),0));
3248         emitpcode(POC_BCF,  popGet(AOP(result),0));
3249         
3250 }
3251
3252
3253 /*-----------------------------------------------------------------*/
3254 /* genMultOneByte : 8 bit multiplication & division                        */
3255 /*-----------------------------------------------------------------*/
3256 static void genMultOneByte (operand *left,
3257                                                         operand *right,
3258                                                         operand *result)
3259 {
3260         char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3261         
3262         // symbol *lbl ;
3263         int size,offset,i;
3264         
3265         
3266         FENTRY;
3267         
3268         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3269         DEBUGpic14_AopType(__LINE__,left,right,result);
3270         DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3271         
3272         /* (if two literals, the value is computed before) */
3273         /* if one literal, literal on the right */
3274         if (AOP_TYPE(left) == AOP_LIT){
3275                 operand *t = right;
3276                 right = left;
3277                 left = t;
3278         }
3279
3280         assert (AOP_SIZE(left) == AOP_SIZE(right));
3281         
3282         size = min(AOP_SIZE(result),AOP_SIZE(left));
3283         offset = Gstack_base_addr - (2*size - 1);
3284
3285         /* pass right operand as argument */
3286         for (i=0; i < size; i++)
3287         {
3288                 mov2w (AOP(right), i);
3289                 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3290         } // for
3291         
3292         /* pass left operand as argument */
3293         for (i=0; i < size; i++)
3294         {
3295                 mov2w (AOP(left), i);
3296                 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3297         } // for
3298         assert (offset == Gstack_base_addr);
3299         
3300         /* call library routine */
3301         assert (size > 0 && size <= 4);
3302         call_libraryfunc (func[size]);
3303         
3304         /* assign result */
3305         movwf (AOP(result), size-1);
3306         for (i=0; i < size - 1; i++)
3307         {
3308                 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3309                 movwf (AOP(result), size - 2 - i);
3310         } // for
3311
3312         /* now (zero-/sign) extend the result to its size */
3313         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3314 }
3315
3316 /*-----------------------------------------------------------------*/
3317 /* genMult - generates code for multiplication                                     */
3318 /*-----------------------------------------------------------------*/
3319 static void genMult (iCode *ic)
3320 {
3321         operand *left = IC_LEFT(ic);
3322         operand *right = IC_RIGHT(ic);
3323         operand *result= IC_RESULT(ic); 
3324         
3325         FENTRY;
3326
3327         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3328         /* assign the amsops */
3329         aopOp (left,ic,FALSE);
3330         aopOp (right,ic,FALSE);
3331         aopOp (result,ic,TRUE);
3332         
3333         DEBUGpic14_AopType(__LINE__,left,right,result);
3334         
3335         /* special cases first */
3336         /* both are bits */
3337         if (AOP_TYPE(left) == AOP_CRY &&
3338                 AOP_TYPE(right)== AOP_CRY) {
3339                 genMultbits(left,right,result);
3340                 goto release ;
3341         }
3342         
3343         /* if both are of size == 1 */
3344         if (AOP_SIZE(left) == 1 &&
3345                 AOP_SIZE(right) == 1 ) {
3346                 genMultOneByte(left,right,result);
3347                 goto release ;
3348         }
3349         
3350         /* should have been converted to function call */
3351         assert(0) ;
3352         
3353 release :
3354         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3355         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3356         freeAsmop(result,NULL,ic,TRUE); 
3357 }
3358
3359 /*-----------------------------------------------------------------*/
3360 /* genDivbits :- division of bits                                                                  */
3361 /*-----------------------------------------------------------------*/
3362 static void genDivbits (operand *left, 
3363                                                 operand *right, 
3364                                                 operand *result)
3365 {
3366         
3367         char *l;
3368         
3369         FENTRY;
3370
3371         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3372         /* the result must be bit */      
3373         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3374         l = aopGet(AOP(left),0,FALSE,FALSE);
3375         
3376         MOVA(l);          
3377         
3378         pic14_emitcode("div","ab");
3379         pic14_emitcode("rrc","a");
3380         aopPut(AOP(result),"c",0);
3381 }
3382
3383 /*-----------------------------------------------------------------*/
3384 /* genDivOneByte : 8 bit division                                                                  */
3385 /*-----------------------------------------------------------------*/
3386 static void genDivOneByte (operand *left,
3387                                                    operand *right,
3388                                                    operand *result)
3389 {
3390         int size;
3391         int sign;
3392         
3393         FENTRY;
3394         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3395         
3396         assert (AOP_SIZE(right) == 1);
3397         assert (AOP_SIZE(left) == 1);
3398
3399         size = min(AOP_SIZE(result),AOP_SIZE(left));
3400         sign = !(SPEC_USIGN(operandType(left))
3401                 && SPEC_USIGN(operandType(right)));
3402
3403         if (AOP_TYPE(right) == AOP_LIT)
3404         {
3405                 /* XXX: might add specialized code */
3406         }
3407
3408         if (!sign)
3409         {
3410                 /* unsigned division */
3411         #if 1
3412                 mov2w(AOP(right),0);
3413                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3414                 mov2w(AOP(left),0);
3415                 call_libraryfunc("__divuchar");
3416                 movwf(AOP(result),0);
3417         #else
3418                 pCodeOp *temp;
3419                 symbol *lbl;
3420
3421                 temp = popGetTempReg();
3422                 lbl = newiTempLabel(NULL);
3423                 
3424                 /* XXX: improve this naive approach:
3425                    [result] = [a] / [b]
3426                         ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3427
3428                    In PIC assembler:
3429                    movf  left,W
3430                    movwf temp           // temp <-- left
3431                    movf  right,W        // W <-- right
3432                    clrf  result
3433                    label1:
3434                    incf  result
3435                    subwf temp,F         // temp <-- temp - W
3436                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if temp < W
3437                    goto  label1
3438                    decf result          // we just subtract once too often
3439                  */
3440
3441                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3442                 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3443                 
3444                 mov2w(AOP(left),0);
3445                 emitpcode(POC_MOVWF, temp);
3446                 mov2w(AOP(right),0);
3447                 emitpcode(POC_CLRF, popGet(AOP(result),0));
3448
3449                 emitpLabel(lbl->key);
3450                 emitpcode(POC_INCF, popGet(AOP(result),0));
3451                 emitpcode(POC_SUBWF, temp);
3452                 emitSKPNC;
3453                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3454                 emitpcode(POC_DECF, popGet(AOP(result),0));
3455         #endif
3456         }
3457         else
3458         {
3459                 /* signed division */
3460                 mov2w(AOP(right),0);
3461                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3462                 mov2w(AOP(left),0);
3463                 call_libraryfunc("__divschar");
3464                 movwf(AOP(result),0);
3465         }
3466
3467         /* now performed the signed/unsigned division -- extend result */
3468         addSign(result, 1, sign);
3469 }
3470
3471 /*-----------------------------------------------------------------*/
3472 /* genDiv - generates code for division                            */
3473 /*-----------------------------------------------------------------*/
3474 static void genDiv (iCode *ic)
3475 {
3476         operand *left = IC_LEFT(ic);
3477         operand *right = IC_RIGHT(ic);
3478         operand *result= IC_RESULT(ic); 
3479         
3480         FENTRY;
3481         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3482         /* assign the amsops */
3483         aopOp (left,ic,FALSE);
3484         aopOp (right,ic,FALSE);
3485         aopOp (result,ic,TRUE);
3486         
3487         /* special cases first */
3488         /* both are bits */
3489         if (AOP_TYPE(left) == AOP_CRY &&
3490                 AOP_TYPE(right)== AOP_CRY) {
3491                 genDivbits(left,right,result);
3492                 goto release ;
3493         }
3494         
3495         /* if both are of size == 1 */
3496         if (AOP_SIZE(left) == 1 &&
3497                 AOP_SIZE(right) == 1 ) {
3498                 genDivOneByte(left,right,result);
3499                 goto release ;
3500         }
3501         
3502         /* should have been converted to function call */
3503         assert(0);
3504 release :
3505         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3506         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3507         freeAsmop(result,NULL,ic,TRUE); 
3508 }
3509
3510 /*-----------------------------------------------------------------*/
3511 /* genModOneByte : 8 bit modulus                                                                   */
3512 /*-----------------------------------------------------------------*/
3513 static void genModOneByte (operand *left,
3514                                                    operand *right,
3515                                                    operand *result)
3516 {
3517         int size;
3518         int sign;
3519         
3520         FENTRY;
3521         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3522         
3523         assert (AOP_SIZE(right) == 1);
3524         assert (AOP_SIZE(left) == 1);
3525
3526         size = min(AOP_SIZE(result),AOP_SIZE(left));
3527         sign = !(SPEC_USIGN(operandType(left))
3528                 && SPEC_USIGN(operandType(right)));
3529
3530         if (AOP_TYPE(right) == AOP_LIT)
3531         {
3532                 /* XXX: might add specialized code */
3533         }
3534
3535         if (!sign)
3536         {
3537                 /* unsigned division */
3538         #if 1
3539                 mov2w(AOP(right),0);
3540                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3541                 mov2w(AOP(left),0);
3542                 call_libraryfunc("__moduchar");
3543                 movwf(AOP(result),0);
3544         #else
3545                 pCodeOp *temp;
3546                 symbol *lbl;
3547
3548                 lbl = newiTempLabel(NULL);
3549                 
3550                 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3551
3552                 /* XXX: improve this naive approach:
3553                    [result] = [a] % [b]
3554                         ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3555
3556                    In PIC assembler:
3557                    movf  left,W
3558                    movwf result         // result <-- left
3559                    movf  right,W        // W <-- right
3560                    label1:
3561                    subwf result,F       // result <-- result - W
3562                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if result < W
3563                    goto  label1
3564                    addwf result, F      // we just subtract once too often
3565                  */
3566
3567                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3568                 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3569                 
3570                 if (!pic14_sameRegs(AOP(left), AOP(result)))
3571                 {
3572                         mov2w(AOP(left),0);
3573                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
3574                 }
3575                 mov2w(AOP(right),0);
3576
3577                 emitpLabel(lbl->key);
3578                 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3579                 emitSKPNC;
3580                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3581                 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3582         #endif
3583         }
3584         else
3585         {
3586                 /* signed division */
3587                 mov2w(AOP(right),0);
3588                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3589                 mov2w(AOP(left),0);
3590                 call_libraryfunc("__modschar");
3591                 movwf(AOP(result),0);
3592         }
3593
3594         /* now we performed the signed/unsigned modulus -- extend result */
3595         addSign(result, 1, sign);
3596 }
3597
3598 /*-----------------------------------------------------------------*/
3599 /* genMod - generates code for division                                                    */
3600 /*-----------------------------------------------------------------*/
3601 static void genMod (iCode *ic)
3602 {
3603         operand *left = IC_LEFT(ic);
3604         operand *right = IC_RIGHT(ic);
3605         operand *result= IC_RESULT(ic);  
3606         
3607         FENTRY;
3608         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3609         /* assign the amsops */
3610         aopOp (left,ic,FALSE);
3611         aopOp (right,ic,FALSE);
3612         aopOp (result,ic,TRUE);
3613         
3614         /* if both are of size == 1 */
3615         if (AOP_SIZE(left) == 1 &&
3616                 AOP_SIZE(right) == 1 ) {
3617                 genModOneByte(left,right,result);
3618                 goto release ;
3619         }
3620         
3621         /* should have been converted to function call */
3622         assert(0);
3623         
3624 release :
3625         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3626         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3627         freeAsmop(result,NULL,ic,TRUE); 
3628 }
3629
3630 /*-----------------------------------------------------------------*/
3631 /* genIfxJump :- will create a jump depending on the ifx                   */
3632 /*-----------------------------------------------------------------*/
3633 /*
3634 note: May need to add parameter to indicate when a variable is in bit space.
3635 */
3636 static void genIfxJump (iCode *ic, char *jval)
3637 {
3638         
3639         FENTRY;
3640         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3641         /* if true label then we jump if condition
3642         supplied is true */
3643         if ( IC_TRUE(ic) ) {
3644                 
3645                 if(strcmp(jval,"a") == 0)
3646                         emitSKPZ;
3647                 else if (strcmp(jval,"c") == 0)
3648                         emitSKPC;
3649                 else {
3650                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3651                         emitpcode(POC_BTFSC,    newpCodeOpBit(jval,-1,1));
3652                 }
3653                 
3654                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3655                 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3656                 
3657         }
3658         else {
3659                 /* false label is present */
3660                 if(strcmp(jval,"a") == 0)
3661                         emitSKPNZ;
3662                 else if (strcmp(jval,"c") == 0)
3663                         emitSKPNC;
3664                 else {
3665                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3666                         emitpcode(POC_BTFSS,    newpCodeOpBit(jval,-1,1));
3667                 }
3668                 
3669                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3670                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3671                 
3672         }
3673         
3674         
3675         /* mark the icode as generated */
3676         ic->generated = 1;
3677 }
3678
3679 #if 0
3680 /*-----------------------------------------------------------------*/
3681 /* genSkip                                                                                                                 */
3682 /*-----------------------------------------------------------------*/
3683 static void genSkip(iCode *ifx,int status_bit)
3684 {
3685         FENTRY;
3686         if(!ifx)
3687                 return;
3688         
3689         if ( IC_TRUE(ifx) ) {
3690                 switch(status_bit) {
3691                 case 'z':
3692                         emitSKPNZ;
3693                         break;
3694                         
3695                 case 'c':
3696                         emitSKPNC;
3697                         break;
3698                         
3699                 case 'd':
3700                         emitSKPDC;
3701                         break;
3702                         
3703                 }
3704                 
3705                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3706                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3707                 
3708         } else {
3709                 
3710                 switch(status_bit) {
3711                         
3712                 case 'z':
3713                         emitSKPZ;
3714                         break;
3715                         
3716                 case 'c':
3717                         emitSKPC;
3718                         break;
3719                         
3720                 case 'd':
3721                         emitSKPDC;
3722                         break;
3723                 }
3724                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3725                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3726                 
3727         }
3728         
3729 }
3730 #endif
3731
3732 /*-----------------------------------------------------------------*/
3733 /* genSkipc                                                                                                        */
3734 /*-----------------------------------------------------------------*/
3735 static void genSkipc(resolvedIfx *rifx)
3736 {
3737         FENTRY;
3738         if(!rifx)
3739                 return;
3740         
3741         if(rifx->condition)
3742                 emitSKPNC;
3743         else
3744                 emitSKPC;
3745         
3746         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3747         emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3748         rifx->generated = 1;
3749 }
3750
3751 #if 0
3752 /*-----------------------------------------------------------------*/
3753 /* genSkipz2                                                                                                       */
3754 /*-----------------------------------------------------------------*/
3755 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3756 {
3757         FENTRY;
3758         if(!rifx)
3759                 return;
3760         
3761         if( (rifx->condition ^ invert_condition) & 1)
3762                 emitSKPZ;
3763         else
3764                 emitSKPNZ;
3765         
3766         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3767         rifx->generated = 1;
3768 }
3769 #endif
3770
3771 #if 0
3772 /*-----------------------------------------------------------------*/
3773 /* genSkipz                                                        */
3774 /*-----------------------------------------------------------------*/
3775 static void genSkipz(iCode *ifx, int condition)
3776 {
3777         FENTRY;
3778         assert (ifx != NULL);
3779         
3780         if(condition)
3781                 emitSKPNZ;
3782         else
3783                 emitSKPZ;
3784         
3785         if ( IC_TRUE(ifx) )
3786                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3787         else
3788                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3789         
3790         if ( IC_TRUE(ifx) )
3791                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3792         else
3793                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3794         
3795 }
3796 #endif
3797
3798 #if 0
3799 /*-----------------------------------------------------------------*/
3800 /* genSkipCond                                                     */
3801 /*-----------------------------------------------------------------*/
3802 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3803 {
3804         FENTRY;
3805         if(!rifx)
3806                 return;
3807         
3808         if(rifx->condition)
3809                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3810         else
3811                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3812         
3813         
3814         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3815         rifx->generated = 1;
3816 }
3817 #endif
3818
3819 #if 0
3820 /*-----------------------------------------------------------------*/
3821 /* genChkZeroes :- greater or less than comparison                 */
3822 /*     For each byte in a literal that is zero, inclusive or the   */
3823 /*     the corresponding byte in the operand with W                */
3824 /*     returns true if any of the bytes are zero                   */
3825 /*-----------------------------------------------------------------*/
3826 static int genChkZeroes(operand *op, int lit,  int size)
3827 {
3828         
3829         int i;
3830         int flag =1;
3831         
3832         while(size--) {
3833                 i = (lit >> (size*8)) & 0xff;
3834                 
3835                 if(i==0) {
3836                         if(flag) 
3837                                 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3838                         else
3839                                 emitpcode(POC_IORFW, popGet(AOP(op),size));
3840                         flag = 0;
3841                 }
3842         }
3843         
3844         return (flag==0);
3845 }
3846 #endif
3847
3848
3849 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3850 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
3851 #define DEBUGpc           emitpComment
3852
3853 /*-----------------------------------------------------------------*/
3854 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
3855 /*                  aop (if it's NOT a literal) or from lit (if    */
3856 /*                  aop is a literal)                              */
3857 /*-----------------------------------------------------------------*/
3858 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3859   if (aop->type == AOP_LIT) {
3860     emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3861   } else {
3862     emitpcode (POC_MOVFW, popGet (aop, offset));
3863   }
3864 }
3865
3866 /* genCmp performs a left < right comparison, stores
3867  * the outcome in result (if != NULL) and generates
3868  * control flow code for the ifx (if != NULL).
3869  *
3870  * This version leaves in sequences like
3871  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3872  * which should be optmized by the peephole
3873  * optimizer - RN 2005-01-01 */
3874 static void genCmp (operand *left,operand *right,
3875                     operand *result, iCode *ifx, int sign)
3876 {
3877   resolvedIfx rIfx;
3878   int size;
3879   int offs;
3880   symbol *templbl;
3881   operand *dummy;
3882   unsigned long lit;
3883   unsigned long mask;
3884   int performedLt;
3885   int invert_result = 0;
3886
3887   FENTRY;
3888   
3889   assert (AOP_SIZE(left) == AOP_SIZE(right));
3890   assert (left && right);
3891
3892   size = AOP_SIZE(right) - 1;
3893   mask = (0x100UL << (size*8)) - 1;
3894   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3895   performedLt = 1;
3896   templbl = NULL;
3897   lit = 0;
3898   
3899   resolveIfx (&rIfx, ifx);
3900
3901   /**********************************************************************
3902    * handle bits - bit compares are promoted to int compares seemingly! *
3903    **********************************************************************/
3904 #if 0
3905   // THIS IS COMPLETELY UNTESTED!
3906   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3907     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3908     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3909     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3910
3911     emitSETC;
3912     // 1 < {0,1} is false --> clear C by skipping the next instruction
3913     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3914     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3915     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3916     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3917     emitCLRC; // only skipped for left=0 && right=1
3918
3919     goto correct_result_in_carry;
3920   } // if
3921 #endif
3922
3923   /*************************************************
3924    * make sure that left is register (or the like) *
3925    *************************************************/
3926   if (!isAOP_REGlike(left)) {
3927     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3928     assert (isAOP_LIT(left));
3929     assert (isAOP_REGlike(right));
3930     // swap left and right
3931     // left < right <==> right > left <==> (right >= left + 1)
3932     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3933
3934     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
3935       // MAXVALUE < right? always false
3936       if (performedLt) emitCLRC; else emitSETC;
3937       goto correct_result_in_carry;
3938     } // if
3939
3940     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
3941     // that's why we handled it above.
3942     lit++;
3943
3944     dummy = left;
3945     left = right;
3946     right = dummy;
3947
3948     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
3949   } else if (isAOP_LIT(right)) {
3950     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3951   } // if
3952
3953   assert (isAOP_REGlike(left)); // left must be register or the like
3954   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
3955
3956   /*************************************************
3957    * special cases go here                         *
3958    *************************************************/
3959
3960   if (isAOP_LIT(right)) {
3961     if (!sign) {
3962       // unsigned comparison to a literal
3963       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
3964       if (lit == 0) {
3965         // unsigned left < 0? always false
3966         if (performedLt) emitCLRC; else emitSETC;
3967         goto correct_result_in_carry;
3968       }
3969     } else {
3970       // signed comparison to a literal
3971       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
3972       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
3973         // signed left < 0x80000000? always false
3974         if (performedLt) emitCLRC; else emitSETC;
3975         goto correct_result_in_carry;
3976       } else if (lit == 0) {
3977         // compare left < 0; set CARRY if SIGNBIT(left) is set
3978         if (performedLt) emitSETC; else emitCLRC;
3979         emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
3980         if (performedLt) emitCLRC; else emitSETC;
3981         goto correct_result_in_carry;
3982       }
3983     } // if (!sign)
3984   } // right is literal
3985
3986   /*************************************************
3987    * perform a general case comparison             *
3988    * make sure we get CARRY==1 <==> left >= right  *
3989    *************************************************/
3990   // compare most significant bytes
3991   //DEBUGpc ("comparing bytes at offset %d", size);
3992   if (!sign) {
3993     // unsigned comparison
3994     pic14_mov2w_regOrLit (AOP(right), lit, size);
3995     emitpcode (POC_SUBFW, popGet (AOP(left), size));
3996   } else {
3997     // signed comparison
3998     // (add 2^n to both operands then perform an unsigned comparison)
3999     if (isAOP_LIT(right)) {
4000       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4001       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4002
4003       if (litbyte == 0x80) {
4004         // left >= 0x80 -- always true, but more bytes to come
4005         mov2w (AOP(left), size);
4006         emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
4007         emitSETC;
4008       } else {
4009         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4010         mov2w (AOP(left), size);
4011         emitpcode (POC_ADDLW, popGetLit (0x80));
4012         emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4013       } // if
4014     } else {
4015       pCodeOp *pctemp = popGetTempReg();
4016       mov2w (AOP(left), size);
4017       emitpcode (POC_ADDLW, popGetLit (0x80));
4018       emitpcode (POC_MOVWF, pctemp);
4019       mov2w (AOP(right), size);
4020       emitpcode (POC_ADDLW, popGetLit (0x80));
4021       emitpcode (POC_SUBFW, pctemp);
4022       popReleaseTempReg(pctemp);
4023     }
4024   } // if (!sign)
4025
4026   // compare remaining bytes (treat as unsigned case from above)
4027   templbl = newiTempLabel ( NULL );
4028   offs = size;
4029   while (offs--) {
4030     //DEBUGpc ("comparing bytes at offset %d", offs);
4031     emitSKPZ;
4032     emitpcode (POC_GOTO, popGetLabel (templbl->key));
4033     pic14_mov2w_regOrLit (AOP(right), lit, offs);
4034     emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4035   } // while (offs)
4036   emitpLabel (templbl->key);
4037   goto result_in_carry;
4038
4039 result_in_carry:
4040   
4041   /****************************************************
4042    * now CARRY contains the result of the comparison: *
4043    * SUBWF sets CARRY iff                             *
4044    * F-W >= 0 <==> F >= W <==> !(F < W)               *
4045    * (F=left, W=right)                                *
4046    ****************************************************/
4047
4048   if (performedLt) {
4049     invert_result = 1;
4050     // value will be used in the following genSkipc()
4051     rIfx.condition ^= 1;
4052   } // if
4053
4054 correct_result_in_carry:
4055
4056   // assign result to variable (if neccessary)
4057   if (result && AOP_TYPE(result) != AOP_CRY) {
4058     //DEBUGpc ("assign result");
4059     size = AOP_SIZE(result);
4060     while (size--) {
4061       emitpcode (POC_CLRF, popGet (AOP(result), size));
4062     } // while
4063     if (invert_result) {
4064       emitSKPC;
4065       emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4066     } else {
4067       emitpcode (POC_RLF, popGet (AOP(result), 0));
4068     }
4069   } // if (result)
4070
4071   // perform conditional jump
4072   if (ifx) {
4073     //DEBUGpc ("generate control flow");
4074     genSkipc (&rIfx);
4075     ifx->generated = 1;
4076   } // if
4077 }
4078
4079
4080 #if 0
4081 /* OLD VERSION -- BUGGY, DO NOT USE */
4082
4083 /*-----------------------------------------------------------------*/
4084 /* genCmp :- greater or less than comparison                       */
4085 /*-----------------------------------------------------------------*/
4086 static void genCmp (operand *left,operand *right,
4087                                         operand *result, iCode *ifx, int sign)
4088 {
4089         int size; //, offset = 0 ;
4090         unsigned long lit = 0L,i = 0;
4091         resolvedIfx rFalseIfx;
4092         //  resolvedIfx rTrueIfx;
4093         symbol *truelbl;
4094
4095         FENTRY;
4096         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4097         /*
4098         if(ifx) {
4099         DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4100         DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4101         }
4102         */
4103         
4104         resolveIfx(&rFalseIfx,ifx);
4105         truelbl  = newiTempLabel(NULL);
4106         size = max(AOP_SIZE(left),AOP_SIZE(right));
4107         
4108         DEBUGpic14_AopType(__LINE__,left,right,result);
4109         
4110 #define _swapp
4111         
4112         /* if literal is on the right then swap with left */
4113         if ((AOP_TYPE(right) == AOP_LIT)) {
4114                 operand *tmp = right ;
4115                 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4116                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4117 #ifdef _swapp
4118                 
4119                 lit = (lit - 1) & mask;
4120                 right = left;
4121                 left = tmp;
4122                 rFalseIfx.condition ^= 1;
4123 #endif
4124                 
4125         } else if ((AOP_TYPE(left) == AOP_LIT)) {
4126                 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4127         }
4128         
4129         
4130         //if(IC_TRUE(ifx) == NULL)
4131         /* if left & right are bit variables */
4132         if (AOP_TYPE(left) == AOP_CRY &&
4133                 AOP_TYPE(right) == AOP_CRY ) {
4134                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4135                 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4136         } else {
4137         /* subtract right from left if at the
4138         end the carry flag is set then we know that
4139                 left is greater than right */
4140                 
4141                 symbol *lbl  = newiTempLabel(NULL);
4142                 
4143 #ifndef _swapp
4144                 if(AOP_TYPE(right) == AOP_LIT) {
4145                         
4146                         //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4147                         
4148                         DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4149                         
4150                         /* special cases */
4151                         
4152                         if(lit == 0) {
4153                                 
4154                                 if(sign != 0) 
4155                                         genSkipCond(&rFalseIfx,left,size-1,7);
4156                                 else 
4157                                         /* no need to compare to 0...*/
4158                                         /* NOTE: this is a de-generate compare that most certainly 
4159                                         *       creates some dead code. */
4160                                         emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4161                                 
4162                                 if(ifx) ifx->generated = 1;
4163                                 return;
4164                                 
4165                         }
4166                         size--;
4167                         
4168                         if(size == 0) {
4169                                 //i = (lit >> (size*8)) & 0xff;
4170                                 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4171                                 
4172                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4173                                 
4174                                 i = ((0-lit) & 0xff);
4175                                 if(sign) {
4176                                         if( i == 0x81) { 
4177                                         /* lit is 0x7f, all signed chars are less than
4178                                                 * this except for 0x7f itself */
4179                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4180                                                 genSkipz2(&rFalseIfx,0);
4181                                         } else {
4182                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4183                                                 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4184                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4185                                         }
4186                                         
4187                                 } else {
4188                                         if(lit == 1) {
4189                                                 genSkipz2(&rFalseIfx,1);
4190                                         } else {
4191                                                 emitpcode(POC_ADDLW, popGetLit(i));
4192                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4193                                         }
4194                                 }
4195                                 
4196                                 if(ifx) ifx->generated = 1;
4197                                 return;
4198                         }
4199                         
4200                         /* chars are out of the way. now do ints and longs */
4201                         
4202                         
4203                         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4204                         
4205                         /* special cases */
4206                         
4207                         if(sign) {
4208                                 
4209                                 if(lit == 0) {
4210                                         genSkipCond(&rFalseIfx,left,size,7);
4211                                         if(ifx) ifx->generated = 1;
4212                                         return;
4213                                 }
4214                                 
4215                                 if(lit <0x100) {
4216                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4217                                         
4218                                         //rFalseIfx.condition ^= 1;
4219                                         //genSkipCond(&rFalseIfx,left,size,7);
4220                                         //rFalseIfx.condition ^= 1;
4221                                         
4222                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4223                                         if(rFalseIfx.condition)
4224                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4225                                         else
4226                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4227                                         
4228                                         emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4229                                         emitpcode(POC_ADDFW, popGet(AOP(left),0));
4230                                         emitpcode(POC_MOVFW, popGet(AOP(left),1));
4231                                         
4232                                         while(size > 1)
4233                                                 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4234                                         
4235                                         if(rFalseIfx.condition) {
4236                                                 emitSKPZ;
4237                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4238                                                 
4239                                         } else {
4240                                                 emitSKPNZ;
4241                                         }
4242                                         
4243                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4244                                         emitpLabel(truelbl->key);
4245                                         if(ifx) ifx->generated = 1;
4246                                         return;
4247                                         
4248                                 }
4249                                 
4250                                 if(size == 1) {
4251                                         
4252                                         if( (lit & 0xff) == 0) {
4253                                                 /* lower byte is zero */
4254                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4255                                                 i = ((lit >> 8) & 0xff) ^0x80;
4256                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4257                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4258                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4259                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4260                                                 
4261                                                 
4262                                                 if(ifx) ifx->generated = 1;
4263                                                 return;
4264                                                 
4265                                         }
4266                                 } else {
4267                                         /* Special cases for signed longs */
4268                                         if( (lit & 0xffffff) == 0) {
4269                                                 /* lower byte is zero */
4270                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4271                                                 i = ((lit >> 8*3) & 0xff) ^0x80;
4272                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4273                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4274                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4275                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4276                                                 
4277                                                 
4278                                                 if(ifx) ifx->generated = 1;
4279                                                 return;
4280                                                 
4281                                         }
4282                                         
4283                                 }
4284                                 
4285                                 
4286                                 if(lit & (0x80 << (size*8))) {
4287                                         /* lit is negative */
4288                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4289                                         
4290                                         //genSkipCond(&rFalseIfx,left,size,7);
4291                                         
4292                                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4293                                         
4294                                         if(rFalseIfx.condition)
4295                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4296                                         else
4297                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4298                                         
4299                                         
4300                                 } else {
4301                                         /* lit is positive */
4302                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4303                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4304                                         if(rFalseIfx.condition)
4305                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4306                                         else
4307                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4308                                         
4309                                 }
4310                                 
4311                                 /* There are no more special cases, so perform a general compare */
4312                                 
4313                                 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4314                                 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4315                                 
4316                                 while(size--) {
4317                                         
4318                                         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4319                                         emitSKPNZ;
4320                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4321                                 }
4322                                 //rFalseIfx.condition ^= 1;
4323                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4324                                 
4325                                 emitpLabel(truelbl->key);
4326                                 
4327                                 if(ifx) ifx->generated = 1;
4328                                 return;
4329                                 
4330                                 
4331                         }
4332
4333
4334                         /* sign is out of the way. So now do an unsigned compare */
4335                         DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4336
4337
4338                         /* General case - compare to an unsigned literal on the right.*/
4339
4340                         i = (lit >> (size*8)) & 0xff;
4341                         emitpcode(POC_MOVLW, popGetLit(i));
4342                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4343                         while(size--) {
4344                                 i = (lit >> (size*8)) & 0xff;
4345                                 
4346                                 if(i) {
4347                                         emitpcode(POC_MOVLW, popGetLit(i));
4348                                         emitSKPNZ;
4349                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4350                                 } else {
4351                                 /* this byte of the lit is zero, 
4352                                         *if it's not the last then OR in the variable */
4353                                         if(size)
4354                                                 emitpcode(POC_IORFW, popGet(AOP(left),size));
4355                                 }
4356                         }
4357
4358
4359                 emitpLabel(lbl->key);
4360                 //if(emitFinalCheck)
4361                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4362                 if(sign)
4363                         emitpLabel(truelbl->key);
4364
4365                 if(ifx) ifx->generated = 1;
4366                 return;
4367
4368
4369                 }
4370 #endif  // _swapp
4371
4372                 if(AOP_TYPE(left) == AOP_LIT) {
4373                         //symbol *lbl = newiTempLabel(NULL);
4374                         
4375                         //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4376                         
4377                         
4378                         DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4379                         
4380                         /* Special cases */
4381                         if((lit == 0) && (sign == 0)){
4382                                 
4383                                 size--;
4384                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4385                                 while(size) 
4386                                         emitpcode(POC_IORFW, popGet(AOP(right),--size));
4387                                 
4388                                 genSkipz2(&rFalseIfx,0);
4389                                 if(ifx) ifx->generated = 1;
4390                                 return;
4391                         }
4392                         
4393                         if(size==1) {
4394                                 /* Special cases */
4395                                 lit &= 0xff;
4396                                 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4397                                         /* degenerate compare can never be true */
4398                                         if(rFalseIfx.condition == 0)
4399                                                 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4400                                         
4401                                         if(ifx) ifx->generated = 1;
4402                                         return;
4403                                 }
4404                                 
4405                                 if(sign) {
4406                                         /* signed comparisons to a literal byte */
4407                                         
4408                                         int lp1 = (lit+1) & 0xff;
4409                                         
4410                                         DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4411                                         switch (lp1) {
4412                                         case 0:
4413                                                 rFalseIfx.condition ^= 1;
4414                                                 genSkipCond(&rFalseIfx,right,0,7);
4415                                                 break;
4416                                         case 0x7f:
4417                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4418                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4419                                                 genSkipz2(&rFalseIfx,1);
4420                                                 break;
4421                                         default:
4422                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4423                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4424                                                 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4425                                                 rFalseIfx.condition ^= 1;
4426                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4427                                                 break;
4428                                         }
4429                                         if(ifx) ifx->generated = 1;
4430                                 } else {
4431                                         /* unsigned comparisons to a literal byte */
4432                                         
4433                                         switch(lit & 0xff ) {
4434                                         case 0:
4435                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4436                                                 genSkipz2(&rFalseIfx,0);
4437                                                 if(ifx) ifx->generated = 1;
4438                                                 break;
4439                                         case 0x7f:
4440                                                 genSkipCond(&rFalseIfx,right,0,7);
4441                                                 if(ifx) ifx->generated = 1;
4442                                                 break;
4443                                                 
4444                                         default:
4445                                                 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4446                                                 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4447                                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4448                                                 rFalseIfx.condition ^= 1;
4449                                                 if (AOP_TYPE(result) == AOP_CRY) {
4450                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4451                                                         if(ifx) ifx->generated = 1;
4452                                                 } else {
4453                                                         DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4454                                                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4455                                                         emitpcode(POC_RLF, popGet(AOP(result),0));
4456                                                         emitpcode(POC_MOVLW, popGetLit(0x01));
4457                                                         emitpcode(POC_XORWF, popGet(AOP(result),0));
4458                                                 }       
4459                                                 break;
4460                                         }
4461                                 }
4462                                 
4463                                 //goto check_carry;
4464                                 return;
4465                                 
4466                         } else {
4467                                 
4468                                 /* Size is greater than 1 */
4469                                 
4470                                 if(sign) {
4471                                         int lp1 = lit+1;
4472                                         
4473                                         size--;
4474                                         
4475                                         if(lp1 == 0) {
4476                                                 /* this means lit = 0xffffffff, or -1 */
4477                                                 
4478                                                 
4479                                                 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4480                                                 rFalseIfx.condition ^= 1;
4481                                                 genSkipCond(&rFalseIfx,right,size,7);
4482                                                 if(ifx) ifx->generated = 1;
4483                                                 return;
4484                                         }
4485                                         
4486                                         if(lit == 0) {
4487                                                 int s = size;
4488                                                 
4489                                                 if(rFalseIfx.condition) {
4490                                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4491                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4492                                                 }
4493                                                 
4494                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4495                                                 while(size--)
4496                                                         emitpcode(POC_IORFW, popGet(AOP(right),size));
4497                                                 
4498                                                 
4499                                                 emitSKPZ;
4500                                                 if(rFalseIfx.condition) {
4501                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4502                                                         emitpLabel(truelbl->key);
4503                                                 }else {
4504                                                         rFalseIfx.condition ^= 1;
4505                                                         genSkipCond(&rFalseIfx,right,s,7);
4506                                                 }
4507                                                 
4508                                                 if(ifx) ifx->generated = 1;
4509                                                 return;
4510                                         }
4511                                         
4512                                         if((size == 1) &&  (0 == (lp1&0xff))) {
4513                                                 /* lower byte of signed word is zero */
4514                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4515                                                 i = ((lp1 >> 8) & 0xff) ^0x80;
4516                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4517                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4518                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4519                                                 rFalseIfx.condition ^= 1;
4520                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4521                                                 
4522                                                 
4523                                                 if(ifx) ifx->generated = 1;
4524                                                 return;
4525                                         }
4526                                         
4527                                         if(lit & (0x80 << (size*8))) {
4528                                                 /* Lit is less than zero */
4529                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4530                                                 //rFalseIfx.condition ^= 1;
4531                                                 //genSkipCond(&rFalseIfx,left,size,7);
4532                                                 //rFalseIfx.condition ^= 1;
4533                                                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4534                                                 //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4535                                                 
4536                                                 if(rFalseIfx.condition)
4537                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4538                                                 else
4539                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4540                                                 
4541                                                 
4542                                         } else {
4543                                                 /* Lit is greater than or equal to zero */
4544                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4545                                                 //rFalseIfx.condition ^= 1;
4546                                                 //genSkipCond(&rFalseIfx,right,size,7);
4547                                                 //rFalseIfx.condition ^= 1;
4548                                                 
4549                                                 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4550                                                 //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4551                                                 
4552                                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4553                                                 if(rFalseIfx.condition)
4554                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4555                                                 else
4556                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4557                                                 
4558                                         }
4559                                         
4560                                         
4561                                         emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4562                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4563                                         
4564                                         while(size--) {
4565                                                 
4566                                                 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4567                                                 emitSKPNZ;
4568                                                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4569                                         }
4570                                         rFalseIfx.condition ^= 1;
4571                                         //rFalseIfx.condition = 1;
4572                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4573                                         
4574                                         emitpLabel(truelbl->key);
4575                                         
4576                                         if(ifx) ifx->generated = 1;
4577                                         return;
4578                                         // end of if (sign)
4579                                 } else {
4580                                         
4581                                         /* compare word or long to an unsigned literal on the right.*/
4582                                         
4583                                         
4584                                         size--;
4585                                         if(lit < 0xff) {
4586                                                 DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4587                                                 switch (lit) {
4588                                                 case 0:
4589                                                         break; /* handled above */
4590                                                 /*
4591                                                 case 0xff:
4592                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4593                                                         while(size--)
4594                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4595                                                         genSkipz2(&rFalseIfx,0);
4596                                                         break;
4597                                                 */
4598                                                 default:
4599                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4600                                                         while(--size)
4601                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4602                                                         
4603                                                         emitSKPZ;
4604                                                         if(rFalseIfx.condition)
4605                                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4606                                                         else
4607                                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4608                                                         
4609                                                         
4610                                                         emitpcode(POC_MOVLW, popGetLit(lit+1));
4611                                                         emitpcode(POC_SUBFW, popGet(AOP(right),0));
4612                                                         
4613                                                         rFalseIfx.condition ^= 1;
4614                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4615                                                 }
4616                                                 
4617                                                 emitpLabel(truelbl->key);
4618                                                 
4619                                                 if(ifx) ifx->generated = 1;
4620                                                 return;
4621                                         }
4622                                         
4623                                         
4624                                         lit++;
4625                                         DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4626                                         i = (lit >> (size*8)) & 0xff;
4627                                         
4628                                         emitpcode(POC_MOVLW, popGetLit(i));
4629                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4630                                         
4631                                         while(size--) {
4632                                                 i = (lit >> (size*8)) & 0xff;
4633                                                 
4634                                                 if(i) {
4635                                                         emitpcode(POC_MOVLW, popGetLit(i));
4636                                                         emitSKPNZ;
4637                                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4638                                                 } else {
4639                                                 /* this byte of the lit is zero, 
4640                                                         *if it's not the last then OR in the variable */
4641                                                         if(size)
4642                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4643                                                 }
4644                                         }
4645                                         
4646                                         
4647                                         emitpLabel(lbl->key);
4648                                         
4649                                         rFalseIfx.condition ^= 1;
4650                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4651                                 }
4652                                 
4653                                 if(sign)
4654                                         emitpLabel(truelbl->key);
4655                                 if(ifx) ifx->generated = 1;
4656                                 return;
4657                         }
4658                 }
4659                 /* Compare two variables */
4660                 
4661                 DEBUGpic14_emitcode(";sign","%d",sign);
4662                 
4663                 size--;
4664                 if(sign) {
4665                         /* Sigh. thus sucks... */
4666                         if(size) {
4667                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4668                                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4669                                 emitpcode(POC_MOVLW, popGetLit(0x80));
4670                                 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4671                                 emitpcode(POC_XORFW, popGet(AOP(right),size));
4672                                 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4673                         } else {
4674                                 /* Signed char comparison */
4675                                 /* Special thanks to Nikolai Golovchenko for this snippet */
4676                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4677                                 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4678                                 emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4679                                 emitpcode(POC_XORFW, popGet(AOP(left),0));
4680                                 emitpcode(POC_XORFW, popGet(AOP(right),0));
4681                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4682                                 
4683                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4684                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4685                                 
4686                                 if(ifx) ifx->generated = 1;
4687                                 return;
4688                         }
4689                         
4690                 } else {
4691                         
4692                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4693                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4694                 }
4695                 
4696                 
4697                 /* The rest of the bytes of a multi-byte compare */
4698                 while (size) {
4699                         
4700                         emitSKPZ;
4701                         emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4702                         size--;
4703                         
4704                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4705                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4706                         
4707                         
4708                 }
4709                 
4710                 emitpLabel(lbl->key);
4711                 
4712                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4713                 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4714                         (AOP_TYPE(result) == AOP_REG)) {
4715                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4716                         emitpcode(POC_RLF, popGet(AOP(result),0));
4717                 } else {
4718                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4719                 }       
4720                 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4721                 if(ifx) ifx->generated = 1;
4722                 
4723                 return;
4724                 
4725         }
4726         
4727         // check_carry:
4728         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4729                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4730                 pic14_outBitC(result);
4731         } else {
4732                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4733                 /* if the result is used in the next
4734                 ifx conditional branch then generate
4735                 code a little differently */
4736                 if (ifx )
4737                         genIfxJump (ifx,"c");
4738                 else
4739                         pic14_outBitC(result);
4740                 /* leave the result in acc */
4741         }
4742         
4743 }
4744 #endif
4745
4746 /*-----------------------------------------------------------------*/
4747 /* genCmpGt :- greater than comparison                             */
4748 /*-----------------------------------------------------------------*/
4749 static void genCmpGt (iCode *ic, iCode *ifx)
4750 {
4751         operand *left, *right, *result;
4752         sym_link *letype , *retype;
4753         int sign ;
4754         
4755         FENTRY;
4756         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4757         left = IC_LEFT(ic);
4758         right= IC_RIGHT(ic);
4759         result = IC_RESULT(ic);
4760         
4761         letype = getSpec(operandType(left));
4762         retype =getSpec(operandType(right));
4763         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4764         /* assign the amsops */
4765         aopOp (left,ic,FALSE);
4766         aopOp (right,ic,FALSE);
4767         aopOp (result,ic,TRUE);
4768         
4769         genCmp(right, left, result, ifx, sign);
4770         
4771         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4772         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4773         freeAsmop(result,NULL,ic,TRUE); 
4774 }
4775
4776 /*-----------------------------------------------------------------*/
4777 /* genCmpLt - less than comparisons                                */
4778 /*-----------------------------------------------------------------*/
4779 static void genCmpLt (iCode *ic, iCode *ifx)
4780 {
4781         operand *left, *right, *result;
4782         sym_link *letype , *retype;
4783         int sign ;
4784         
4785         FENTRY;
4786         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4787         left = IC_LEFT(ic);
4788         right= IC_RIGHT(ic);
4789         result = IC_RESULT(ic);
4790         
4791         letype = getSpec(operandType(left));
4792         retype =getSpec(operandType(right));
4793         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4794         
4795         /* assign the amsops */
4796         aopOp (left,ic,FALSE);
4797         aopOp (right,ic,FALSE);
4798         aopOp (result,ic,TRUE);
4799         
4800         genCmp(left, right, result, ifx, sign);
4801         
4802         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4803         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4804         freeAsmop(result,NULL,ic,TRUE); 
4805 }
4806
4807 #if 0
4808 /*-----------------------------------------------------------------*/
4809 /* genc16bit2lit - compare a 16 bit value to a literal             */
4810 /*-----------------------------------------------------------------*/
4811 static void genc16bit2lit(operand *op, int lit, int offset)
4812 {
4813         int i;
4814         
4815         FENTRY;
4816         DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4817         if( (lit&0xff) == 0) 
4818                 i=1;
4819         else
4820                 i=0;
4821         
4822         switch( BYTEofLONG(lit,i)) { 
4823         case 0:
4824                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4825                 break;
4826         case 1:
4827                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4828                 break;
4829         case 0xff:
4830                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4831                 break;
4832         default:
4833                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4834                 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4835         }
4836         
4837         i ^= 1;
4838         
4839         switch( BYTEofLONG(lit,i)) { 
4840         case 0:
4841                 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4842                 break;
4843         case 1:
4844                 emitSKPNZ;
4845                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4846                 break;
4847         case 0xff:
4848                 emitSKPNZ;
4849                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4850                 break;
4851         default:
4852                 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4853                 emitSKPNZ;
4854                 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4855                 
4856         }
4857         
4858 }
4859 #endif
4860
4861 #if 0
4862 /*-----------------------------------------------------------------*/
4863 /* gencjneshort - compare and jump if not equal                    */
4864 /*-----------------------------------------------------------------*/
4865 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4866 {
4867         int size = min(AOP_SIZE(left),AOP_SIZE(right));
4868         int offset = 0;
4869         //resolvedIfx rIfx;
4870         symbol *lbl;
4871         
4872         //unsigned long lit = 0L;
4873         FENTRY;
4874         if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4875           emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4876           return;
4877         }
4878         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4879         DEBUGpic14_AopType(__LINE__,left,right,result);
4880         
4881         assert (!pic14_sameRegs (AOP(left), AOP(result)));
4882         assert (!pic14_sameRegs (AOP(right), AOP(result)));
4883         if (AOP_SIZE(result)) {
4884           for (offset = 0; offset < AOP_SIZE(result); offset++)
4885             emitpcode (POC_CLRF, popGet (AOP(result), offset));
4886         }
4887         
4888         assert (AOP_SIZE(left) == AOP_SIZE(right));
4889         //resolveIfx(&rIfx,ifx);
4890         lbl = newiTempLabel (NULL);
4891         while (size--)
4892         {
4893           mov2w (AOP(right),size);
4894           emitpcode (POC_XORFW, popGet (AOP(left), size));
4895           if (size)
4896           {
4897             emitSKPZ;
4898             emitpcode (POC_GOTO, popGetLabel (lbl->key));
4899           }
4900         } // while
4901         emitpLabel (lbl->key);
4902         if (AOP_SIZE(result)) {
4903           emitSKPNZ;
4904           emitpcode (POC_INCF, popGet (AOP(result), 0));
4905         } else {
4906           assert (ifx);
4907           genSkipz (ifx, NULL != IC_TRUE(ifx));
4908           ifx->generated = 1;
4909         }
4910         return;
4911 #if 0   
4912         if(result)
4913         {
4914                 DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4915                 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4916                 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4917                 for (offset=0; offset < AOP_SIZE(result); offset++)
4918                 {
4919                         emitpcode (POC_CLRF, popGet (AOP(result), offset));
4920                 } // for offset
4921         }
4922         
4923         
4924         /* if the left side is a literal or 
4925         if the right is in a pointer register and left 
4926         is not */
4927         if ((AOP_TYPE(left) == AOP_LIT) || 
4928                 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4929                 operand *t = right;
4930                 right = left;
4931                 left = t;
4932         }
4933         if(AOP_TYPE(right) == AOP_LIT)
4934                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4935         
4936         /* if the right side is a literal then anything goes */
4937         if (AOP_TYPE(right) == AOP_LIT &&
4938                 AOP_TYPE(left) != AOP_DIR ) {
4939                 switch(size) {
4940                 case 2:
4941                         genc16bit2lit(left, lit, 0);
4942                         emitSKPNZ;
4943                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
4944                         break;
4945                 default:
4946                         offset = 0;
4947                         while (size--) {
4948                                 if(lit & 0xff) {
4949                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4950                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4951                                 } else {
4952                                         emitpcode(POC_MOVF,popGet(AOP(left),offset));
4953                                 }
4954                                 
4955                                 emitSKPNZ;
4956                                 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4957                                 offset++;
4958                                 lit >>= 8;
4959                         }
4960                         break;
4961                 }
4962         }
4963         
4964         /* if the right side is in a register or in direct space or
4965         if the left is a pointer register & right is not */    
4966         else if (AOP_TYPE(right) == AOP_REG ||
4967                 AOP_TYPE(right) == AOP_DIR || 
4968                 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4969                 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4970                 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4971                 int lbl_key = lbl->key;
4972                 
4973                 if(!result) {
4974                         DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4975                         fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4976                                 __FUNCTION__,__LINE__);
4977                         return;
4978                 }
4979                 
4980                 /*     switch(size) { */
4981                 /*     case 2: */
4982                 /*       genc16bit2lit(left, lit, 0); */
4983                 /*       emitSKPNZ; */
4984                 /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4985                 /*       break; */
4986                 /*     default: */
4987                 offset = 0;
4988                 while (size--) {
4989                         int emit_skip=1;
4990                         if((AOP_TYPE(left) == AOP_DIR) && 
4991                                 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4992                                 
4993                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4994                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
4995                                 
4996                         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4997                                 
4998                                 switch (lit & 0xff) {
4999                                 case 0:
5000                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5001                                         break;
5002                                 case 1:
5003                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5004                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5005                                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
5006                                         emit_skip=0;
5007                                         break;
5008                                 case 0xff:
5009                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5010                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5011                                         //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5012                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5013                                         emit_skip=0;
5014                                         break;
5015                                 default:
5016                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5017                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5018                                 }
5019                                 lit >>= 8;
5020                                 
5021                         } else {
5022                                 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5023                         }
5024                         if(emit_skip) {
5025                                 if(AOP_TYPE(result) == AOP_CRY) {
5026                                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5027                                         if(rIfx.condition)
5028                                                 emitSKPNZ;
5029                                         else
5030                                                 emitSKPZ;
5031                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5032                                 } else {
5033                                         /* fix me. probably need to check result size too */
5034                                         //emitpcode(POC_CLRF,popGet(AOP(result),0));
5035                                         if(rIfx.condition)
5036                                                 emitSKPZ;
5037                                         else
5038                                                 emitSKPNZ;
5039                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5040                                 }
5041                                 if(ifx)
5042                                         ifx->generated=1;
5043                         }
5044                         emit_skip++;
5045                         offset++;
5046                 }
5047                 /*       break; */
5048                 /*     } */
5049         } else if(AOP_TYPE(right) == AOP_REG &&
5050                 AOP_TYPE(left) != AOP_DIR){
5051
5052                 offset = 0;
5053                 while(size--) {
5054                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5055                         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5056                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5057                         if(rIfx.condition)
5058                                 emitSKPNZ;
5059                         else
5060                                 emitSKPZ;
5061                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5062                         offset++;
5063                 }
5064                 
5065         }else{
5066                 /* right is a pointer reg need both a & b */
5067                 offset = 0;
5068                 while(size--) {
5069                         char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5070                         if(strcmp(l,"b"))
5071                                 pic14_emitcode("mov","b,%s",l);
5072                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5073                         pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5074                         offset++;
5075                 }
5076         }
5077         
5078         emitpcode(POC_INCF,popGet(AOP(result),0));
5079         if(!rIfx.condition)
5080                 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5081         
5082         emitpLabel(lbl->key);
5083         
5084         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5085         
5086         if(ifx)
5087                 ifx->generated = 1;
5088 #endif
5089 }
5090 #endif
5091
5092 #if 0
5093 /*-----------------------------------------------------------------*/
5094 /* gencjne - compare and jump if not equal                         */
5095 /*-----------------------------------------------------------------*/
5096 static void gencjne(operand *left, operand *right, iCode *ifx)
5097 {
5098         symbol *tlbl  = newiTempLabel(NULL);
5099         
5100         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5101         gencjneshort(left, right, lbl);
5102         
5103         pic14_emitcode("mov","a,%s",one);
5104         pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5105         pic14_emitcode("","%05d_DS_:",lbl->key+100);
5106         pic14_emitcode("clr","a");
5107         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5108         
5109         emitpLabel(lbl->key);
5110         emitpLabel(tlbl->key);
5111         
5112 }
5113 #endif
5114
5115 /*-----------------------------------------------------------------*/
5116 /* genCmpEq - generates code for equal to                          */
5117 /*-----------------------------------------------------------------*/
5118 static void genCmpEq (iCode *ic, iCode *ifx)
5119 {
5120   operand *left, *right, *result;
5121   int size;
5122   symbol *false_label;
5123
5124   FENTRY;
5125   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5126
5127   if(ifx)
5128     DEBUGpic14_emitcode ("; ifx is non-null","");
5129   else
5130     DEBUGpic14_emitcode ("; ifx is null","");
5131
5132   aopOp((left=IC_LEFT(ic)),ic,FALSE);
5133   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5134   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5135
5136   DEBUGpic14_AopType(__LINE__,left,right,result);
5137
5138   /* if literal, move literal to right */ 
5139   if (op_isLitLike (IC_LEFT(ic))) {
5140     operand *tmp = right ;
5141     right = left;
5142     left = tmp;
5143   }
5144
5145   false_label = NULL;
5146   if (ifx && !IC_TRUE(ifx))
5147   {
5148     assert (IC_FALSE(ifx));
5149     false_label = IC_FALSE(ifx);
5150   }
5151
5152   size = min(AOP_SIZE(left),AOP_SIZE(right));
5153   assert(!pic14_sameRegs(AOP(result),AOP(left)));
5154   assert(!pic14_sameRegs(AOP(result),AOP(right)));
5155
5156   /* assume left != right */
5157   {
5158     int i;
5159     for (i=0; i < AOP_SIZE(result); i++)
5160     {
5161       emitpcode(POC_CLRF, popGet(AOP(result),i));
5162     }
5163   }
5164
5165   if (AOP_TYPE(right) == AOP_LIT)
5166   {
5167     unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5168     int i;
5169     size = AOP_SIZE(left);
5170     assert(!op_isLitLike(left));
5171
5172     switch (lit)
5173     {
5174       case 0:
5175         mov2w(AOP(left), 0);
5176         for (i=1; i < size; i++)
5177           emitpcode(POC_IORFW,popGet(AOP(left),i));
5178         /* now Z is set iff `left == right' */
5179         emitSKPZ;
5180         if (!false_label) false_label = newiTempLabel(NULL);
5181         emitpcode(POC_GOTO, popGetLabel(false_label->key));
5182         break;
5183
5184       default:
5185         for (i=0; i < size; i++)
5186         {
5187           mov2w(AOP(left),i);
5188           emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5189           /* now Z is cleared if `left != right' */
5190           emitSKPZ;
5191           if (!false_label) false_label = newiTempLabel(NULL);
5192           emitpcode(POC_GOTO, popGetLabel(false_label->key));
5193         } // for i
5194         break;
5195     } // switch (lit)
5196   }
5197   else
5198   {
5199     /* right is no literal */
5200     int i;
5201
5202     for (i=0; i < size; i++)
5203     {
5204       mov2w(AOP(right),i);
5205       emitpcode(POC_XORFW,popGet(AOP(left),i));
5206       /* now Z is cleared if `left != right' */
5207       emitSKPZ;
5208       if (!false_label) false_label = newiTempLabel(NULL);
5209       emitpcode(POC_GOTO, popGetLabel(false_label->key));
5210     } // for i
5211   }
5212
5213   /* if we reach here, left == right */
5214
5215   if (AOP_SIZE(result) > 0)
5216   {
5217     emitpcode(POC_INCF, popGet(AOP(result),0));
5218   }
5219
5220   if (ifx && IC_TRUE(ifx))
5221   {
5222     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5223   }
5224
5225   if (false_label && (!ifx || IC_TRUE(ifx)))
5226     emitpLabel(false_label->key);
5227
5228   if (ifx) ifx->generated = 1;
5229
5230   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5231   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5232   freeAsmop(result,NULL,ic,TRUE);
5233 }
5234
5235 /*-----------------------------------------------------------------*/
5236 /* ifxForOp - returns the icode containing the ifx for operand     */
5237 /*-----------------------------------------------------------------*/
5238 static iCode *ifxForOp ( operand *op, iCode *ic )
5239 {
5240         FENTRY;
5241         /* if true symbol then needs to be assigned */
5242         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5243         if (IS_TRUE_SYMOP(op))
5244                 return NULL ;
5245         
5246         /* if this has register type condition and
5247         the next instruction is ifx with the same operand
5248         and live to of the operand is upto the ifx only then */
5249         if (ic->next &&
5250                 ic->next->op == IFX &&
5251                 IC_COND(ic->next)->key == op->key &&
5252                 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5253                 return ic->next;
5254         
5255         if (ic->next &&
5256                 ic->next->op == IFX &&
5257                 IC_COND(ic->next)->key == op->key) {
5258                 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5259                 return ic->next;
5260         }
5261         
5262         DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5263         if (ic->next &&
5264                 ic->next->op == IFX)
5265                 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5266         
5267         if (ic->next &&
5268                 ic->next->op == IFX &&
5269                 IC_COND(ic->next)->key == op->key) {
5270                 DEBUGpic14_emitcode ("; "," key is okay");
5271                 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5272                         OP_SYMBOL(op)->liveTo,
5273                         ic->next->seq);
5274         }
5275         
5276         
5277         return NULL;
5278 }
5279 /*-----------------------------------------------------------------*/
5280 /* genAndOp - for && operation                                     */
5281 /*-----------------------------------------------------------------*/
5282 static void genAndOp (iCode *ic)
5283 {
5284         operand *left,*right, *result;
5285         /*     symbol *tlbl; */
5286         
5287         FENTRY;
5288         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5289         /* note here that && operations that are in an
5290         if statement are taken away by backPatchLabels
5291         only those used in arthmetic operations remain */
5292         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5293         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5294         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5295         
5296         DEBUGpic14_AopType(__LINE__,left,right,result);
5297         
5298         emitpcode(POC_MOVFW,popGet(AOP(left),0));
5299         emitpcode(POC_ANDFW,popGet(AOP(right),0));
5300         emitpcode(POC_MOVWF,popGet(AOP(result),0));
5301         
5302         /* if both are bit variables */
5303         /*     if (AOP_TYPE(left) == AOP_CRY && */
5304         /*         AOP_TYPE(right) == AOP_CRY ) { */
5305         /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5306         /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5307         /*         pic14_outBitC(result); */
5308         /*     } else { */
5309         /*         tlbl = newiTempLabel(NULL); */
5310         /*         pic14_toBoolean(left);     */
5311         /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5312         /*         pic14_toBoolean(right); */
5313         /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5314         /*         pic14_outBitAcc(result); */
5315         /*     } */
5316         
5317         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5318         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5319         freeAsmop(result,NULL,ic,TRUE);
5320 }
5321
5322
5323 /*-----------------------------------------------------------------*/
5324 /* genOrOp - for || operation                                      */
5325 /*-----------------------------------------------------------------*/
5326 /*
5327 tsd pic port -
5328 modified this code, but it doesn't appear to ever get called
5329 */
5330
5331 static void genOrOp (iCode *ic)
5332 {
5333         operand *left,*right, *result;
5334         symbol *tlbl;
5335         int i;
5336         
5337         /* note here that || operations that are in an
5338         if statement are taken away by backPatchLabels
5339         only those used in arthmetic operations remain */
5340         FENTRY;
5341         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5342         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5343         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5344         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5345         
5346         DEBUGpic14_AopType(__LINE__,left,right,result);
5347
5348         for (i=0; i < AOP_SIZE(result); i++)
5349         {
5350                 emitpcode(POC_CLRF, popGet(AOP(result), i));
5351         } // for i
5352
5353         tlbl = newiTempLabel(NULL);
5354         pic14_toBoolean(left);
5355         emitSKPZ;
5356         emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5357         pic14_toBoolean(right);
5358         emitpLabel(tlbl->key);
5359         /* here Z is clear IFF `left || right' */
5360         emitSKPZ;
5361         emitpcode(POC_INCF, popGet(AOP(result), 0));
5362         
5363         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5364         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5365         freeAsmop(result,NULL,ic,TRUE);            
5366 }
5367
5368 /*-----------------------------------------------------------------*/
5369 /* isLiteralBit - test if lit == 2^n                               */
5370 /*-----------------------------------------------------------------*/
5371 static int isLiteralBit(unsigned long lit)
5372 {
5373         unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5374                 0x100L,0x200L,0x400L,0x800L,
5375                 0x1000L,0x2000L,0x4000L,0x8000L,
5376                 0x10000L,0x20000L,0x40000L,0x80000L,
5377                 0x100000L,0x200000L,0x400000L,0x800000L,
5378                 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5379                 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5380         int idx;
5381         
5382         FENTRY;
5383         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5384         for(idx = 0; idx < 32; idx++)
5385                 if(lit == pw[idx])
5386                         return idx+1;
5387                 return 0;
5388 }
5389
5390 /*-----------------------------------------------------------------*/
5391 /* continueIfTrue -                                                */
5392 /*-----------------------------------------------------------------*/
5393 static void continueIfTrue (iCode *ic)
5394 {
5395         FENTRY;
5396         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5397         if(IC_TRUE(ic))
5398         {
5399                 // Why +100?!?
5400                 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5401                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5402         }
5403         ic->generated = 1;
5404 }
5405
5406 /*-----------------------------------------------------------------*/
5407 /* jmpIfTrue -                                                     */
5408 /*-----------------------------------------------------------------*/
5409 static void jumpIfTrue (iCode *ic)
5410 {
5411         FENTRY;
5412         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5413         if(!IC_TRUE(ic))
5414         {
5415                 // Why +100?!?
5416                 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5417                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5418         }
5419         ic->generated = 1;
5420 }
5421
5422 /*-----------------------------------------------------------------*/
5423 /* jmpTrueOrFalse -                                                */
5424 /*-----------------------------------------------------------------*/
5425 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5426 {
5427         FENTRY;
5428         // ugly but optimized by peephole
5429         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5430         if(IC_TRUE(ic)){
5431                 symbol *nlbl = newiTempLabel(NULL);
5432                 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5433                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5434                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5435                 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5436         }
5437         else{
5438                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5439                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5440         }
5441         ic->generated = 1;
5442 }
5443
5444 /*-----------------------------------------------------------------*/
5445 /* genAnd  - code for and                                          */
5446 /*-----------------------------------------------------------------*/
5447 static void genAnd (iCode *ic, iCode *ifx)
5448 {
5449         operand *left, *right, *result;
5450         int size, offset=0;  
5451         unsigned long lit = 0L;
5452         int bytelit = 0;
5453         resolvedIfx rIfx;
5454         
5455         FENTRY;
5456         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5457         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5458         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5459         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5460         
5461         resolveIfx(&rIfx,ifx);
5462         
5463         /* if left is a literal & right is not then exchange them */
5464         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5465                 AOP_NEEDSACC(left)) {
5466                 operand *tmp = right ;
5467                 right = left;
5468                 left = tmp;
5469         }
5470         
5471         /* if result = right then exchange them */
5472         if(pic14_sameRegs(AOP(result),AOP(right))){
5473                 operand *tmp = right ;
5474                 right = left;
5475                 left = tmp;
5476         }
5477         
5478         /* if right is bit then exchange them */
5479         if (AOP_TYPE(right) == AOP_CRY &&
5480                 AOP_TYPE(left) != AOP_CRY){
5481                 operand *tmp = right ;
5482                 right = left;
5483                 left = tmp;
5484         }
5485         if(AOP_TYPE(right) == AOP_LIT)
5486                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5487         
5488         size = AOP_SIZE(result);
5489         
5490         DEBUGpic14_AopType(__LINE__,left,right,result);
5491         
5492         // if(bit & yy)
5493         // result = bit & yy;
5494         if (AOP_TYPE(left) == AOP_CRY){
5495                 // c = bit & literal;
5496                 if(AOP_TYPE(right) == AOP_LIT){
5497                         if(lit & 1) {
5498                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5499                                         // no change
5500                                         goto release;
5501                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5502                         } else {
5503                                 // bit(result) = 0;
5504                                 if(size && (AOP_TYPE(result) == AOP_CRY)){
5505                                         pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5506                                         goto release;
5507                                 }
5508                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5509                                         jumpIfTrue(ifx);
5510                                         goto release;
5511                                 }
5512                                 pic14_emitcode("clr","c");
5513                         }
5514                 } else {
5515                         if (AOP_TYPE(right) == AOP_CRY){
5516                                 // c = bit & bit;
5517                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5518                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5519                         } else {
5520                                 // c = bit & val;
5521                                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5522                                 // c = lsb
5523                                 pic14_emitcode("rrc","a");
5524                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5525                         }
5526                 }
5527                 // bit = c
5528                 // val = c
5529                 if(size)
5530                         pic14_outBitC(result);
5531                 // if(bit & ...)
5532                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5533                         genIfxJump(ifx, "c");           
5534                 goto release ;
5535         }
5536         
5537         // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5538         // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5539         if((AOP_TYPE(right) == AOP_LIT) &&
5540                 (AOP_TYPE(result) == AOP_CRY) &&
5541                 (AOP_TYPE(left) != AOP_CRY)){
5542                 int posbit = isLiteralBit(lit);
5543                 /* left &  2^n */
5544                 if(posbit){
5545                         posbit--;
5546                         //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5547                         // bit = left & 2^n
5548                         if(size)
5549                                 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5550                         // if(left &  2^n)
5551                         else{
5552                                 if(ifx){
5553                                         int offset = 0;
5554                                         while (posbit > 7) {
5555                                                 posbit -= 8;
5556                                                 offset++;
5557                                         }
5558                                         emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5559                                                 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5560                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5561                                         
5562                                         ifx->generated = 1;
5563                                 }
5564                                 goto release;
5565                         }
5566                 } else {
5567                         symbol *tlbl = newiTempLabel(NULL);
5568                         int sizel = AOP_SIZE(left);
5569                         if(size)
5570                                 pic14_emitcode("setb","c");
5571                         while(sizel--){
5572                                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5573                                         mov2w( AOP(left), offset);
5574                                         // byte ==  2^n ?
5575                                         if((posbit = isLiteralBit(bytelit)) != 0) {
5576                                                 emitpcode(rIfx.condition ? POC_BTFSC : POC_BTFSS, // XXX: or the other way round?
5577                                                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit - 1, 0));
5578                                                 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5579                                         }
5580                                         else{
5581                                                 emitpcode(POC_ANDLW, newpCodeOpLit(bytelit & 0x0ff));
5582                                                 if (rIfx.condition) emitSKPZ;
5583                                                 else emitSKPNZ;
5584                                                 
5585                                                 if(bytelit != 0x0FFL)
5586                                                 {
5587                                                         pic14_emitcode("anl","a,%s",
5588                                                         aopGet(AOP(right),offset,FALSE,TRUE));
5589                                                 }
5590                                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5591                                         }
5592
5593                                         emitpcode(POC_GOTO, popGetLabel(rIfx.lbl->key));
5594                                         ifx->generated = 1;
5595                                                 
5596                                 }
5597                                 offset++;
5598                         }
5599                         // bit = left & literal
5600                         if(size){
5601                                 pic14_emitcode("clr","c");
5602                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5603                         }
5604                         // if(left & literal)
5605                         else{
5606                                 if(ifx)
5607                                         jmpTrueOrFalse(ifx, tlbl);
5608                                 goto release ;
5609                         }
5610                 }
5611                 pic14_outBitC(result);
5612                 goto release ;
5613         }
5614         
5615         /* if left is same as result */
5616         if(pic14_sameRegs(AOP(result),AOP(left))){
5617                 int know_W = -1;
5618                 for(;size--; offset++,lit>>=8) {
5619                         if(AOP_TYPE(right) == AOP_LIT){
5620                                 switch(lit & 0xff) {
5621                                 case 0x00:
5622                                         /*  and'ing with 0 has clears the result */
5623                                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
5624                                         break;
5625                                 case 0xff:
5626                                         /* and'ing with 0xff is a nop when the result and left are the same */
5627                                         break;
5628                                         
5629                                 default:
5630                                         {
5631                                                 int p = my_powof2( (~lit) & 0xff );
5632                                                 if(p>=0) {
5633                                                         /* only one bit is set in the literal, so use a bcf instruction */
5634                                                         emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5635                                                         
5636                                                 } else {
5637                                                         if(know_W != (int)(lit&0xff))
5638                                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5639                                                         know_W = lit &0xff;
5640                                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5641                                                 }
5642                                         }    
5643                                 }
5644                         } else {
5645                                 if (AOP_TYPE(left) == AOP_ACC) {
5646                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5647                                 } else {        
5648                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5649                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5650                                         
5651                                 }
5652                         }
5653                 }
5654                 
5655         } else {
5656                 // left & result in different registers
5657                 if(AOP_TYPE(result) == AOP_CRY){
5658                         // result = bit
5659                         // if(size), result in bit
5660                         // if(!size && ifx), conditional oper: if(left & right)
5661                         symbol *tlbl = newiTempLabel(NULL);
5662                         int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5663                         if(size)
5664                                 pic14_emitcode("setb","c");
5665                         while(sizer--){
5666                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5667                                 pic14_emitcode("anl","a,%s",
5668                                         aopGet(AOP(left),offset,FALSE,FALSE));
5669                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5670                                 offset++;
5671                         }
5672                         if(size){
5673                                 CLRC;
5674                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5675                                 pic14_outBitC(result);
5676                         } else if(ifx)
5677                                 jmpTrueOrFalse(ifx, tlbl);
5678                 } else {
5679                         for(;(size--);offset++) {
5680                                 // normal case
5681                                 // result = left & right
5682                                 if(AOP_TYPE(right) == AOP_LIT){
5683                                         int t = (lit >> (offset*8)) & 0x0FFL;
5684                                         switch(t) { 
5685                                         case 0x00:
5686                                                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5687                                                 break;
5688                                         case 0xff:
5689                                                 if(AOP_TYPE(left) != AOP_ACC) {
5690                                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5691                                                 }
5692                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5693                                                 break;
5694                                         default:
5695                                                 if(AOP_TYPE(left) == AOP_ACC) {
5696                                                         emitpcode(POC_ANDLW, popGetLit(t));
5697                                                 } else {
5698                                                         emitpcode(POC_MOVLW, popGetLit(t));
5699                                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5700                                                 }
5701                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5702                                         }
5703                                         continue;
5704                                 }
5705                                 
5706                                 if (AOP_TYPE(left) == AOP_ACC) {
5707                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5708                                 } else {
5709                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5710                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5711                                 }
5712                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5713                         }
5714                 }
5715         }
5716         
5717 release :
5718         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5719         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5720         freeAsmop(result,NULL,ic,TRUE);     
5721 }
5722
5723 /*-----------------------------------------------------------------*/
5724 /* genOr  - code for or                                            */
5725 /*-----------------------------------------------------------------*/
5726 static void genOr (iCode *ic, iCode *ifx)
5727 {
5728         operand *left, *right, *result;
5729         int size, offset=0;
5730         unsigned long lit = 0L;
5731         
5732         FENTRY;
5733         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5734         
5735         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5736         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5737         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5738         
5739         DEBUGpic14_AopType(__LINE__,left,right,result);
5740         
5741         /* if left is a literal & right is not then exchange them */
5742         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5743                 AOP_NEEDSACC(left)) {
5744                 operand *tmp = right ;
5745                 right = left;
5746                 left = tmp;
5747         }
5748         
5749         /* if result = right then exchange them */
5750         if(pic14_sameRegs(AOP(result),AOP(right))){
5751                 operand *tmp = right ;
5752                 right = left;
5753                 left = tmp;
5754         }
5755         
5756         /* if right is bit then exchange them */
5757         if (AOP_TYPE(right) == AOP_CRY &&
5758                 AOP_TYPE(left) != AOP_CRY){
5759                 operand *tmp = right ;
5760                 right = left;
5761                 left = tmp;
5762         }
5763         
5764         DEBUGpic14_AopType(__LINE__,left,right,result);
5765         
5766         if(AOP_TYPE(right) == AOP_LIT)
5767                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5768         
5769         size = AOP_SIZE(result);
5770         
5771         // if(bit | yy)
5772         // xx = bit | yy;
5773         if (AOP_TYPE(left) == AOP_CRY){
5774                 if(AOP_TYPE(right) == AOP_LIT){
5775                         // c = bit & literal;
5776                         if(lit){
5777                                 // lit != 0 => result = 1
5778                                 if(AOP_TYPE(result) == AOP_CRY){
5779                                         if(size)
5780                                                 emitpcode(POC_BSF, popGet(AOP(result),0));
5781                                         //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5782                                         //   AOP(result)->aopu.aop_dir,
5783                                         //   AOP(result)->aopu.aop_dir);
5784                                         else if(ifx)
5785                                                 continueIfTrue(ifx);
5786                                         goto release;
5787                                 }
5788                         } else {
5789                                 // lit == 0 => result = left
5790                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5791                                         goto release;
5792                                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5793                         }
5794                 } else {
5795                         if (AOP_TYPE(right) == AOP_CRY){
5796                                 if(pic14_sameRegs(AOP(result),AOP(left))){
5797                                         // c = bit | bit;
5798                                         emitpcode(POC_BCF,   popGet(AOP(result),0));
5799                                         emitpcode(POC_BTFSC, popGet(AOP(right),0));
5800                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5801                                         
5802                                         pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5803                                                 AOP(result)->aopu.aop_dir,
5804                                                 AOP(result)->aopu.aop_dir);
5805                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5806                                                 AOP(right)->aopu.aop_dir,
5807                                                 AOP(right)->aopu.aop_dir);
5808                                         pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5809                                                 AOP(result)->aopu.aop_dir,
5810                                                 AOP(result)->aopu.aop_dir);
5811                                 } else {
5812                                         if( AOP_TYPE(result) == AOP_ACC) {
5813                                                 emitpcode(POC_MOVLW, popGetLit(0));
5814                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5815                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5816                                                 emitpcode(POC_MOVLW, popGetLit(1));
5817                                                 
5818                                         } else {
5819                                                 
5820                                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5821                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5822                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5823                                                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5824                                                 
5825                                                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5826                                                         AOP(result)->aopu.aop_dir,
5827                                                         AOP(result)->aopu.aop_dir);
5828                                                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5829                                                         AOP(right)->aopu.aop_dir,
5830                                                         AOP(right)->aopu.aop_dir);
5831                                                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5832                                                         AOP(left)->aopu.aop_dir,
5833                                                         AOP(left)->aopu.aop_dir);
5834                                                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5835                                                         AOP(result)->aopu.aop_dir,
5836                                                         AOP(result)->aopu.aop_dir);
5837                                         }
5838                                 }
5839                         } else {
5840                                 // c = bit | val;
5841                                 symbol *tlbl = newiTempLabel(NULL);
5842                                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5843                                 
5844                                 
5845                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5846                                 if( AOP_TYPE(right) == AOP_ACC) {
5847                                         emitpcode(POC_IORLW, popGetLit(0));
5848                                         emitSKPNZ;
5849                                         emitpcode(POC_BTFSC, popGet(AOP(left),0));
5850                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5851                                 }
5852                                 
5853                                 
5854                                 
5855                                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5856                                         pic14_emitcode(";XXX setb","c");
5857                                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5858                                         AOP(left)->aopu.aop_dir,tlbl->key+100);
5859                                 pic14_toBoolean(right);
5860                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5861                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5862                                         jmpTrueOrFalse(ifx, tlbl);
5863                                         goto release;
5864                                 } else {
5865                                         CLRC;
5866                                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5867                                 }
5868                         }
5869                 }
5870                 // bit = c
5871                 // val = c
5872                 if(size)
5873                         pic14_outBitC(result);
5874                 // if(bit | ...)
5875                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5876                         genIfxJump(ifx, "c");           
5877                 goto release ;
5878         }
5879
5880         // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5881         // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5882         if((AOP_TYPE(right) == AOP_LIT) &&
5883           (AOP_TYPE(result) == AOP_CRY) &&
5884           (AOP_TYPE(left) != AOP_CRY)){
5885                 if(lit){
5886                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5887                         // result = 1
5888                         if(size)
5889                                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5890                         else 
5891                                 continueIfTrue(ifx);
5892                         goto release;
5893                 } else {
5894                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5895                         // lit = 0, result = boolean(left)
5896                         if(size)
5897                                 pic14_emitcode(";XXX setb","c");
5898                         pic14_toBoolean(right);
5899                         if(size){
5900                                 symbol *tlbl = newiTempLabel(NULL);
5901                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5902                                 CLRC;
5903                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5904                         } else {
5905                                 genIfxJump (ifx,"a");
5906                                 goto release;
5907                         }
5908                 }
5909                 pic14_outBitC(result);
5910                 goto release ;
5911         }
5912
5913         /* if left is same as result */
5914         if(pic14_sameRegs(AOP(result),AOP(left))){
5915                 int know_W = -1;
5916                 for(;size--; offset++,lit>>=8) {
5917                         if(AOP_TYPE(right) == AOP_LIT){
5918                                 if((lit & 0xff) == 0)
5919                                         /*  or'ing with 0 has no effect */
5920                                         continue;
5921                                 else {
5922                                         int p = my_powof2(lit & 0xff);
5923                                         if(p>=0) {
5924                                                 /* only one bit is set in the literal, so use a bsf instruction */
5925                                                 emitpcode(POC_BSF,
5926                                                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5927                                         } else {
5928                                                 if(know_W != (int)(lit & 0xff))
5929                                                         emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5930                                                 know_W = lit & 0xff;
5931                                                 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5932                                         }
5933                                         
5934                                 }
5935                         } else {
5936                                 if (AOP_TYPE(left) == AOP_ACC) {
5937                                         emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5938                                         pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5939                                 } else {        
5940                                         emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5941                                         emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5942                                         
5943                                         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5944                                         pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5945                                         
5946                                 }
5947                         }
5948                 }
5949         } else {
5950                 // left & result in different registers
5951                 if(AOP_TYPE(result) == AOP_CRY){
5952                         // result = bit
5953                         // if(size), result in bit
5954                         // if(!size && ifx), conditional oper: if(left | right)
5955                         symbol *tlbl = newiTempLabel(NULL);
5956                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5957                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5958                         
5959                         
5960                         if(size)
5961                                 pic14_emitcode(";XXX setb","c");
5962                         while(sizer--){
5963                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5964                                 pic14_emitcode(";XXX orl","a,%s",
5965                                         aopGet(AOP(left),offset,FALSE,FALSE));
5966                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5967                                 offset++;
5968                         }
5969                         if(size){
5970                                 CLRC;
5971                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5972                                 pic14_outBitC(result);
5973                         } else if(ifx)
5974                                 jmpTrueOrFalse(ifx, tlbl);
5975                 } else for(;(size--);offset++){
5976                         // normal case
5977                         // result = left | right
5978                         if(AOP_TYPE(right) == AOP_LIT){
5979                                 int t = (lit >> (offset*8)) & 0x0FFL;
5980                                 switch(t) { 
5981                                 case 0x00:
5982                                         if (AOP_TYPE(left) != AOP_ACC) {
5983                                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
5984                                         }
5985                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5986                                         
5987                                         break;
5988                                 default:
5989                                         if (AOP_TYPE(left) == AOP_ACC) {
5990                                                 emitpcode(POC_IORLW,  popGetLit(t));
5991                                         } else {
5992                                                 emitpcode(POC_MOVLW,  popGetLit(t));
5993                                                 emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5994                                         }
5995                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));        
5996                                 }
5997                                 continue;
5998                         }
5999                         
6000                         // faster than result <- left, anl result,right
6001                         // and better if result is SFR
6002                         if (AOP_TYPE(left) == AOP_ACC) {
6003                                 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6004                         } else {
6005                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6006                                 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6007                         }
6008                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6009                 }
6010         }
6011
6012 release :
6013         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6014         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6015         freeAsmop(result,NULL,ic,TRUE);     
6016 }
6017
6018 /*-----------------------------------------------------------------*/
6019 /* genXor - code for xclusive or                                   */
6020 /*-----------------------------------------------------------------*/
6021 static void genXor (iCode *ic, iCode *ifx)
6022 {
6023         operand *left, *right, *result;
6024         int size, offset=0;
6025         unsigned long lit = 0L;
6026         
6027         FENTRY;
6028         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6029         
6030         aopOp((left = IC_LEFT(ic)),ic,FALSE);
6031         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6032         aopOp((result=IC_RESULT(ic)),ic,TRUE);
6033         
6034         /* if left is a literal & right is not ||
6035         if left needs acc & right does not */
6036         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6037                 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6038                 operand *tmp = right ;
6039                 right = left;
6040                 left = tmp;
6041         }
6042         
6043         /* if result = right then exchange them */
6044         if(pic14_sameRegs(AOP(result),AOP(right))){
6045                 operand *tmp = right ;
6046                 right = left;
6047                 left = tmp;
6048         }
6049         
6050         /* if right is bit then exchange them */
6051         if (AOP_TYPE(right) == AOP_CRY &&
6052                 AOP_TYPE(left) != AOP_CRY){
6053                 operand *tmp = right ;
6054                 right = left;
6055                 left = tmp;
6056         }
6057         if(AOP_TYPE(right) == AOP_LIT)
6058                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6059         
6060         size = AOP_SIZE(result);
6061         
6062         // if(bit ^ yy)
6063         // xx = bit ^ yy;
6064         if (AOP_TYPE(left) == AOP_CRY){
6065                 if(AOP_TYPE(right) == AOP_LIT){
6066                         // c = bit & literal;
6067                         if(lit>>1){
6068                                 // lit>>1  != 0 => result = 1
6069                                 if(AOP_TYPE(result) == AOP_CRY){
6070                                         if(size)
6071                                         {emitpcode(POC_BSF,  popGet(AOP(result),offset));
6072                                         pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6073                                         else if(ifx)
6074                                                 continueIfTrue(ifx);
6075                                         goto release;
6076                                 }
6077                                 pic14_emitcode("setb","c");
6078                         } else{
6079                                 // lit == (0 or 1)
6080                                 if(lit == 0){
6081                                         // lit == 0, result = left
6082                                         if(size && pic14_sameRegs(AOP(result),AOP(left)))
6083                                                 goto release;
6084                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6085                                 } else{
6086                                         // lit == 1, result = not(left)
6087                                         if(size && pic14_sameRegs(AOP(result),AOP(left))){
6088                                                 emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
6089                                                 emitpcode(POC_XORWF,  popGet(AOP(result),offset));
6090                                                 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6091                                                 goto release;
6092                                         } else {
6093                                                 assert ( !"incomplete genXor" );
6094                                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6095                                                 pic14_emitcode("cpl","c");
6096                                         }
6097                                 }
6098                         }
6099                         
6100                 } else {
6101                         // right != literal
6102                         symbol *tlbl = newiTempLabel(NULL);
6103                         if (AOP_TYPE(right) == AOP_CRY){
6104                                 // c = bit ^ bit;
6105                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6106                         }
6107                         else{
6108                                 int sizer = AOP_SIZE(right);
6109                                 // c = bit ^ val
6110                                 // if val>>1 != 0, result = 1
6111                                 pic14_emitcode("setb","c");
6112                                 while(sizer){
6113                                         MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6114                                         if(sizer == 1)
6115                                                 // test the msb of the lsb
6116                                                 pic14_emitcode("anl","a,#0xfe");
6117                                         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6118                                         sizer--;
6119                                 }
6120                                 // val = (0,1)
6121                                 pic14_emitcode("rrc","a");
6122                         }
6123                         pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6124                         pic14_emitcode("cpl","c");
6125                         pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6126                 }
6127                 // bit = c
6128                 // val = c
6129                 if(size)
6130                         pic14_outBitC(result);
6131                 // if(bit | ...)
6132                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6133                         genIfxJump(ifx, "c");           
6134                 goto release ;
6135         }
6136         
6137         if(pic14_sameRegs(AOP(result),AOP(left))){
6138                 /* if left is same as result */
6139                 for(;size--; offset++) {
6140                         if(AOP_TYPE(right) == AOP_LIT){
6141                                 int t  = (lit >> (offset*8)) & 0x0FFL;
6142                                 if(t == 0x00L)
6143                                         continue;
6144                                 else
6145                                         if (IS_AOP_PREG(left)) {
6146                                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6147                                                 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6148                                                 aopPut(AOP(result),"a",offset);
6149                                         } else {
6150                                                 emitpcode(POC_MOVLW, popGetLit(t));
6151                                                 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6152                                                 pic14_emitcode("xrl","%s,%s",
6153                                                         aopGet(AOP(left),offset,FALSE,TRUE),
6154                                                         aopGet(AOP(right),offset,FALSE,FALSE));
6155                                         }
6156                         } else {
6157                                 if (AOP_TYPE(left) == AOP_ACC)
6158                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6159                                 else {
6160                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6161                                         emitpcode(POC_XORWF,popGet(AOP(left),offset));
6162                                         /*
6163                                         if (IS_AOP_PREG(left)) {
6164                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6165                                         aopPut(AOP(result),"a",offset);
6166                                         } else
6167                                         pic14_emitcode("xrl","%s,a",
6168                                         aopGet(AOP(left),offset,FALSE,TRUE));
6169                                         */
6170                                 }
6171                         }
6172                 }
6173         } else {
6174                 // left & result in different registers
6175                 if(AOP_TYPE(result) == AOP_CRY){
6176                         // result = bit
6177                         // if(size), result in bit
6178                         // if(!size && ifx), conditional oper: if(left ^ right)
6179                         symbol *tlbl = newiTempLabel(NULL);
6180                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6181                         if(size)
6182                                 pic14_emitcode("setb","c");
6183                         while(sizer--){
6184                                 if((AOP_TYPE(right) == AOP_LIT) &&
6185                                         (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6186                                         MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6187                                 } else {
6188                                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6189                                         pic14_emitcode("xrl","a,%s",
6190                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6191                                 }
6192                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6193                                 offset++;
6194                         }
6195                         if(size){
6196                                 CLRC;
6197                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6198                                 pic14_outBitC(result);
6199                         } else if(ifx)
6200                                 jmpTrueOrFalse(ifx, tlbl);
6201                 } else for(;(size--);offset++){
6202                         // normal case
6203                         // result = left & right
6204                         if(AOP_TYPE(right) == AOP_LIT){
6205                                 int t = (lit >> (offset*8)) & 0x0FFL;
6206                                 switch(t) { 
6207                                 case 0x00:
6208                                         if (AOP_TYPE(left) != AOP_ACC) {
6209                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6210                                         }
6211                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6212                                         pic14_emitcode("movf","%s,w",
6213                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6214                                         pic14_emitcode("movwf","%s",
6215                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6216                                         break;
6217                                 case 0xff:
6218                                         if (AOP_TYPE(left) == AOP_ACC) {
6219                                                 emitpcode(POC_XORLW, popGetLit(t));
6220                                         } else {
6221                                                 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6222                                         }
6223                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6224                                         break;
6225                                 default:
6226                                         if (AOP_TYPE(left) == AOP_ACC) {
6227                                                 emitpcode(POC_XORLW, popGetLit(t));
6228                                         } else {
6229                                                 emitpcode(POC_MOVLW, popGetLit(t));
6230                                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6231                                         }
6232                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6233                                         pic14_emitcode("movlw","0x%x",t);
6234                                         pic14_emitcode("xorwf","%s,w",
6235                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6236                                         pic14_emitcode("movwf","%s",
6237                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6238                                         
6239                                 }
6240                                 continue;
6241                         }
6242                         
6243                         // faster than result <- left, anl result,right
6244                         // and better if result is SFR
6245                         if (AOP_TYPE(left) == AOP_ACC) {
6246                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6247                         } else {
6248                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6249                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6250                         }
6251                         if ( AOP_TYPE(result) != AOP_ACC){
6252                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6253                         }
6254                 }
6255         }
6256         
6257 release :
6258         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6259         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6260         freeAsmop(result,NULL,ic,TRUE);     
6261 }
6262
6263 /*-----------------------------------------------------------------*/
6264 /* genInline - write the inline code out                           */
6265 /*-----------------------------------------------------------------*/
6266 static void genInline (iCode *ic)
6267 {
6268   char *buffer, *bp, *bp1;
6269
6270   FENTRY;
6271   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6272
6273   _G.inLine += (!options.asmpeep);
6274
6275   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6276   strcpy(buffer,IC_INLINE(ic));
6277
6278   /* emit each line as a code */
6279   while (*bp) {
6280     if (*bp == '\n') {
6281       *bp++ = '\0';
6282       
6283       if(*bp1)
6284         addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6285       bp1 = bp;
6286     } else {
6287       if (*bp == ':') {
6288         bp++;
6289         *bp = '\0';
6290         bp++;
6291
6292         /* print label, use this special format with NULL directive
6293          * to denote that the argument should not be indented with tab */
6294         addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6295
6296         bp1 = bp;
6297       } else
6298         bp++;
6299     }
6300   }
6301   if ((bp1 != bp) && *bp1)
6302     addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6303
6304   Safe_free(buffer);
6305
6306   _G.inLine -= (!options.asmpeep);
6307 }
6308
6309 /*-----------------------------------------------------------------*/
6310 /* genRRC - rotate right with carry                                */
6311 /*-----------------------------------------------------------------*/
6312 static void genRRC (iCode *ic)
6313 {
6314         operand *left , *result ;
6315         int size, offset = 0, same;
6316         
6317         FENTRY;
6318         /* rotate right with carry */
6319         left = IC_LEFT(ic);
6320         result=IC_RESULT(ic);
6321         aopOp (left,ic,FALSE);
6322         aopOp (result,ic,FALSE);
6323         
6324         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6325         
6326         same = pic14_sameRegs(AOP(result),AOP(left));
6327         
6328         size = AOP_SIZE(result);    
6329         
6330         /* get the lsb and put it into the carry */
6331         emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6332         
6333         offset = 0 ;
6334         
6335         while(size--) {
6336                 
6337                 if(same) {
6338                         emitpcode(POC_RRF, popGet(AOP(left),offset));
6339                 } else {
6340                         emitpcode(POC_RRFW, popGet(AOP(left),offset));
6341                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6342                 }
6343                 
6344                 offset++;
6345         }
6346         
6347         freeAsmop(left,NULL,ic,TRUE);
6348         freeAsmop(result,NULL,ic,TRUE);
6349 }
6350
6351 /*-----------------------------------------------------------------*/
6352 /* genRLC - generate code for rotate left with carry               */
6353 /*-----------------------------------------------------------------*/
6354 static void genRLC (iCode *ic)
6355 {    
6356         operand *left , *result ;
6357         int size, offset = 0;
6358         int same;
6359         
6360         FENTRY;
6361         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6362         /* rotate right with carry */
6363         left = IC_LEFT(ic);
6364         result=IC_RESULT(ic);
6365         aopOp (left,ic,FALSE);
6366         aopOp (result,ic,FALSE);
6367         
6368         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6369         
6370         same = pic14_sameRegs(AOP(result),AOP(left));
6371         
6372         /* move it to the result */
6373         size = AOP_SIZE(result);    
6374         
6375         /* get the msb and put it into the carry */
6376         emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6377         
6378         offset = 0 ;
6379         
6380         while(size--) {
6381                 
6382                 if(same) {
6383                         emitpcode(POC_RLF, popGet(AOP(left),offset));
6384                 } else {
6385                         emitpcode(POC_RLFW, popGet(AOP(left),offset));
6386                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6387                 }
6388                 
6389                 offset++;
6390         }
6391         
6392         
6393         freeAsmop(left,NULL,ic,TRUE);
6394         freeAsmop(result,NULL,ic,TRUE);
6395 }
6396
6397 /*-----------------------------------------------------------------*/
6398 /* genGetHbit - generates code get highest order bit               */
6399 /*-----------------------------------------------------------------*/
6400 static void genGetHbit (iCode *ic)
6401 {
6402         operand *left, *result;
6403         left = IC_LEFT(ic);
6404         result=IC_RESULT(ic);
6405         aopOp (left,ic,FALSE);
6406         aopOp (result,ic,FALSE);
6407         
6408         FENTRY;
6409         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6410         /* get the highest order byte into a */
6411         MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6412         if(AOP_TYPE(result) == AOP_CRY){
6413                 pic14_emitcode("rlc","a");
6414                 pic14_outBitC(result);
6415         }
6416         else{
6417                 pic14_emitcode("rl","a");
6418                 pic14_emitcode("anl","a,#0x01");
6419                 pic14_outAcc(result);
6420         }
6421         
6422         
6423         freeAsmop(left,NULL,ic,TRUE);
6424         freeAsmop(result,NULL,ic,TRUE);
6425 }
6426
6427 /*-----------------------------------------------------------------*/
6428 /* AccLsh - shift left accumulator by known count                  */
6429 /* MARK: pic14 always rotates through CARRY!                       */
6430 /*-----------------------------------------------------------------*/
6431 static void AccLsh (pCodeOp *pcop,int shCount)
6432 {
6433         FENTRY;
6434         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6435         shCount &= 0x0007;              // shCount : 0..7
6436         switch(shCount){
6437         case 0 :
6438                 return;
6439                 break;
6440         case 1 :
6441                 emitCLRC;
6442                 emitpcode(POC_RLF,pcop);
6443                 return;
6444                 break;
6445         case 2 :
6446                 emitpcode(POC_RLF,pcop);
6447                 emitpcode(POC_RLF,pcop);
6448                 break;
6449         case 3 :
6450                 emitpcode(POC_RLF,pcop);
6451                 emitpcode(POC_RLF,pcop);
6452                 emitpcode(POC_RLF,pcop);
6453                 break;
6454         case 4 :
6455                 emitpcode(POC_SWAPF,pcop);
6456                 break;
6457         case 5 :
6458                 emitpcode(POC_SWAPF,pcop);
6459                 emitpcode(POC_RLF,pcop);
6460                 break;
6461         case 6 :
6462                 emitpcode(POC_SWAPF,pcop);
6463                 emitpcode(POC_RLF,pcop);
6464                 emitpcode(POC_RLF,pcop);
6465                 break;
6466         case 7 :
6467                 emitpcode(POC_RRFW,pcop);
6468                 emitpcode(POC_RRF,pcop);
6469                 break;
6470         }
6471         /* clear invalid bits */
6472         emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6473         emitpcode(POC_ANDWF, pcop);
6474 }
6475
6476 /*-----------------------------------------------------------------*/
6477 /* AccRsh - shift right accumulator by known count                 */
6478 /* MARK: pic14 always rotates through CARRY!                       */
6479 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6480 /*            1: mask out invalid bits (zero-extend)               */
6481 /*            2: sign-extend result (pretty slow)                  */
6482 /*-----------------------------------------------------------------*/
6483 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6484 {
6485         FENTRY;
6486         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6487         shCount &= 0x0007;              // shCount : 0..7
6488         switch(shCount){
6489         case 0 :
6490                 return;
6491                 break;
6492         case 1 :
6493                 /* load sign if needed */
6494                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6495                 else if (mask_mode == 1) emitCLRC;
6496                 emitpcode(POC_RRF,pcop);
6497                 return;
6498                 break;
6499         case 2 :
6500                 /* load sign if needed */
6501                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6502                 emitpcode(POC_RRF,pcop);
6503                 /* load sign if needed */
6504                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6505                 emitpcode(POC_RRF,pcop);
6506                 if (mask_mode == 2) return;
6507                 break;
6508         case 3 :
6509                 /* load sign if needed */
6510                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6511                 emitpcode(POC_RRF,pcop);
6512                 /* load sign if needed */
6513                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6514                 emitpcode(POC_RRF,pcop);
6515                 /* load sign if needed */
6516                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6517                 emitpcode(POC_RRF,pcop);
6518                 if (mask_mode == 2) return;
6519                 break;
6520         case 4 :
6521                 emitpcode(POC_SWAPF,pcop);
6522                 break;
6523         case 5 :
6524                 emitpcode(POC_SWAPF,pcop);
6525                 emitpcode(POC_RRF,pcop);
6526                 break;
6527         case 6 :
6528                 emitpcode(POC_SWAPF,pcop);
6529                 emitpcode(POC_RRF,pcop);
6530                 emitpcode(POC_RRF,pcop);
6531                 break;
6532         case 7 :
6533                 if (mask_mode == 2)
6534                 {
6535                         /* load sign */
6536                         emitpcode(POC_RLFW,pcop);
6537                         emitpcode(POC_CLRF,pcop);
6538                         emitSKPNC;
6539                         emitpcode(POC_COMF,pcop);
6540                         return;
6541                 } else {
6542                         emitpcode(POC_RLFW,pcop);
6543                         emitpcode(POC_RLF,pcop);
6544                 }
6545                 break;
6546         }
6547
6548         if (mask_mode == 0)
6549         {
6550                 /* leave invalid bits undefined */
6551                 return;
6552         }
6553         
6554         /* clear invalid bits -- zero-extend */
6555         emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6556         emitpcode(POC_ANDWF, pcop);
6557
6558         if (mask_mode == 2) {
6559           /* sign-extend */
6560           emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6561           emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6562           emitpcode(POC_IORWF, pcop);
6563         }
6564 }
6565
6566 #if 0
6567 /*-----------------------------------------------------------------*/
6568 /* AccSRsh - signed right shift accumulator by known count                 */
6569 /*-----------------------------------------------------------------*/
6570 static void AccSRsh (int shCount)
6571 {
6572         symbol *tlbl ;
6573         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6574         if(shCount != 0){
6575                 if(shCount == 1){
6576                         pic14_emitcode("mov","c,acc.7");
6577                         pic14_emitcode("rrc","a");
6578                 } else if(shCount == 2){
6579                         pic14_emitcode("mov","c,acc.7");
6580                         pic14_emitcode("rrc","a");
6581                         pic14_emitcode("mov","c,acc.7");
6582                         pic14_emitcode("rrc","a");
6583                 } else {
6584                         tlbl = newiTempLabel(NULL);
6585                         /* rotate right accumulator */
6586                         AccRol(8 - shCount);
6587                         /* and kill the higher order bits */
6588                         pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6589                         pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6590                         pic14_emitcode("orl","a,#0x%02x",
6591                                 (unsigned char)~SRMask[shCount]);
6592                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6593                 }
6594         }
6595 }
6596
6597 /*-----------------------------------------------------------------*/
6598 /* shiftR1Left2Result - shift right one byte from left to result   */
6599 /*-----------------------------------------------------------------*/
6600 static void shiftR1Left2ResultSigned (operand *left, int offl,
6601                                                                           operand *result, int offr,
6602                                                                           int shCount)
6603 {
6604         int same;
6605         
6606         FENTRY;
6607         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6608         
6609         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6610         
6611         switch(shCount) {
6612         case 1:
6613                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6614                 if(same) 
6615                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6616                 else {
6617                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6618                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6619                 }
6620                 
6621                 break;
6622         case 2:
6623                 
6624                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6625                 if(same) 
6626                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6627                 else {
6628                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6629                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6630                 }
6631                 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6632                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6633                 
6634                 break;
6635                 
6636         case 3:
6637                 if(same)
6638                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6639                 else {
6640                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6641                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6642                 }
6643                 
6644                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6645                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6646                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6647                 
6648                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6649                 emitpcode(POC_IORLW, popGetLit(0xe0));
6650                 
6651                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6652                 break;
6653                 
6654         case 4:
6655                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6656                 emitpcode(POC_ANDLW,  popGetLit(0x0f));
6657                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6658                 emitpcode(POC_IORLW,  popGetLit(0xf0));
6659                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6660                 break;
6661         case 5:
6662                 if(same) {
6663                         emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6664                 } else {
6665                         emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6666                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6667                 }
6668                 emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6669                 emitpcode(POC_ANDLW,  popGetLit(0x07));
6670                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6671                 emitpcode(POC_IORLW,  popGetLit(0xf8));
6672                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6673                 break;
6674                 
6675         case 6:
6676                 if(same) {
6677                         emitpcode(POC_MOVLW, popGetLit(0x00));
6678                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6679                         emitpcode(POC_MOVLW, popGetLit(0xfe));
6680                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6681                         emitpcode(POC_IORLW, popGetLit(0x01));
6682                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6683                 } else {
6684                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6685                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6686                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6687                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6688                         emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6689                 }
6690                 break;
6691                 
6692         case 7:
6693                 if(same) {
6694                         emitpcode(POC_MOVLW, popGetLit(0x00));
6695                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6696                         emitpcode(POC_MOVLW, popGetLit(0xff));
6697                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6698                 } else {
6699                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6700                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6701                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6702                 }
6703                 
6704         default:
6705                 break;
6706         }
6707 }
6708
6709 /*-----------------------------------------------------------------*/
6710 /* shiftR1Left2Result - shift right one byte from left to result   */
6711 /*-----------------------------------------------------------------*/
6712 static void shiftR1Left2Result (operand *left, int offl,
6713                                                                 operand *result, int offr,
6714                                                                 int shCount, int sign)
6715 {
6716         int same;
6717         
6718         FENTRY;
6719         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6720         
6721         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6722         
6723         /* Copy the msb into the carry if signed. */
6724         if(sign) {
6725                 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6726                 return;
6727         }
6728         
6729         
6730         
6731         switch(shCount) {
6732         case 1:
6733                 emitCLRC;
6734                 if(same) 
6735                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6736                 else {
6737                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6738                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6739                 }
6740                 break;
6741         case 2:
6742                 emitCLRC;
6743                 if(same) {
6744                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6745                 } else {
6746                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6747                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6748                 }
6749                 emitCLRC;
6750                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6751                 
6752                 break;
6753         case 3:
6754                 if(same)
6755                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6756                 else {
6757                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6758                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6759                 }
6760                 
6761                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6762                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6763                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6764                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6765                 break;
6766                 
6767         case 4:
6768                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6769                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6770                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6771                 break;
6772                 
6773         case 5:
6774                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6775                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6776                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6777                 emitCLRC;
6778                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6779                 
6780                 break;
6781         case 6:
6782                 
6783                 emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6784                 emitpcode(POC_ANDLW, popGetLit(0x80));
6785                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6786                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6787                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6788                 break;
6789                 
6790         case 7:
6791                 
6792                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6793                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6794                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6795                 
6796                 break;
6797                 
6798         default:
6799                 break;
6800         }
6801 }
6802
6803 /*-----------------------------------------------------------------*/
6804 /* shiftL1Left2Result - shift left one byte from left to result    */
6805 /*-----------------------------------------------------------------*/
6806 static void shiftL1Left2Result (operand *left, int offl,
6807                                                                 operand *result, int offr, int shCount)
6808 {
6809         int same;
6810         
6811         //    char *l;
6812         FENTRY;
6813         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6814         
6815         same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6816         DEBUGpic14_emitcode ("; ***","same =  %d",same);
6817         //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6818         //    MOVA(l);
6819         /* shift left accumulator */
6820         //AccLsh(shCount); // don't comment out just yet...
6821         //    aopPut(AOP(result),"a",offr);
6822         
6823         switch(shCount) {
6824         case 1:
6825                 /* Shift left 1 bit position */
6826                 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6827                 if(same) {
6828                         emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6829                 } else {
6830                         emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6831                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6832                 }
6833                 break;
6834         case 2:
6835                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6836                 emitpcode(POC_ANDLW,popGetLit(0x7e));
6837                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6838                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6839                 break;
6840         case 3:
6841                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6842                 emitpcode(POC_ANDLW,popGetLit(0x3e));
6843                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6844                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6845                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6846                 break;
6847         case 4:
6848                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6849                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6850                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6851                 break;
6852         case 5:
6853                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6854                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6855                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6856                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6857                 break;
6858         case 6:
6859                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6860                 emitpcode(POC_ANDLW, popGetLit(0x30));
6861                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6862                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6863                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6864                 break;
6865         case 7:
6866                 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6867                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6868                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6869                 break;
6870                 
6871         default:
6872                 DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6873         }
6874         
6875 }
6876 #endif
6877
6878 /*-----------------------------------------------------------------*/
6879 /* movLeft2Result - move byte from left to result                  */
6880 /*-----------------------------------------------------------------*/
6881 static void movLeft2Result (operand *left, int offl,
6882                                                         operand *result, int offr)
6883 {
6884         char *l;
6885         FENTRY;
6886         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6887         if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6888                 l = aopGet(AOP(left),offl,FALSE,FALSE);
6889                 
6890                 if (*l == '@' && (IS_AOP_PREG(result))) {
6891                         pic14_emitcode("mov","a,%s",l);
6892                         aopPut(AOP(result),"a",offr);
6893                 } else {
6894                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6895                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6896                 }
6897         }
6898 }
6899
6900 /*-----------------------------------------------------------------*/
6901 /* shiftLeft_Left2ResultLit - shift left by known count            */
6902 /*-----------------------------------------------------------------*/
6903
6904 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6905 {
6906         int size, same, offr, i;
6907
6908         size = AOP_SIZE(left);
6909         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6910         
6911         same = pic14_sameRegs (AOP(left), AOP(result));
6912         
6913         offr = shCount / 8;
6914         shCount = shCount & 0x07;
6915
6916         size -= offr;
6917
6918         switch (shCount)
6919         {
6920         case 0: /* takes 0 or 2N cycles (for offr==0) */
6921                 if (!same || offr) {
6922                         for (i=size-1; i >= 0; i--)
6923                                 movLeft2Result (left, i, result, offr + i);
6924                 } // if
6925                 break;
6926                 
6927         case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6928                 if (same && offr) {
6929                         shiftLeft_Left2ResultLit (left, result, 8 * offr);
6930                         shiftLeft_Left2ResultLit (result, result, shCount);
6931                         return; /* prevent clearing result again */
6932                 } else {
6933                         emitCLRC;
6934                         for (i=0; i < size; i++) {
6935                                 if (same && !offr) {
6936                                         emitpcode (POC_RLF, popGet (AOP(left), i));
6937                                 } else {
6938                                         emitpcode (POC_RLFW, popGet (AOP(left), i));
6939                                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6940                                 } // if
6941                         } // for
6942                 } // if (offr)
6943                 break;
6944                 
6945         case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6946                 /* works in-place/with offr as well */
6947                 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6948                 emitpcode (POC_ANDLW, popGetLit (0xF0));
6949                 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6950
6951                 for (i = size - 2; i >= 0; i--)
6952                 {
6953                         emitpcode (POC_SWAPFW, popGet (AOP(left), i));
6954                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6955                         emitpcode (POC_ANDLW, popGetLit (0x0F));
6956                         emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
6957                         emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
6958                 } // for i
6959                 break;
6960                 
6961         case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
6962                 /* works in-place/with offr as well */
6963                 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
6964                 for (i = size-2; i >= 0; i--) {
6965                         emitpcode (POC_RRFW, popGet (AOP(left), i));
6966                         emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
6967                 } // for i
6968                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6969                 emitpcode (POC_RRF, popGet (AOP(result), offr));
6970                 break;
6971         
6972         default:
6973                 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
6974                 shiftLeft_Left2ResultLit (result, result, 1);
6975                 return; /* prevent clearing result again */
6976                 break;
6977         } // switch
6978
6979         while (0 < offr--)
6980         {
6981                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6982         } // while
6983 }
6984
6985 /*-----------------------------------------------------------------*/
6986 /* shiftRight_Left2ResultLit - shift right by known count          */
6987 /*-----------------------------------------------------------------*/
6988
6989 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
6990 {
6991         int size, same, offr, i;
6992
6993         size = AOP_SIZE(left);
6994         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6995         
6996         same = pic14_sameRegs (AOP(left), AOP(result));
6997         
6998         offr = shCount / 8;
6999         shCount = shCount & 0x07;
7000
7001         size -= offr;
7002
7003         if (size)
7004         {
7005                 switch (shCount)
7006                 {
7007                 case 0: /* takes 0 or 2N cycles (for offr==0) */
7008                         if (!same || offr) {
7009                                 for (i=0; i < size; i++)
7010                                         movLeft2Result (left, i + offr, result, i);
7011                         } // if
7012                         break;
7013                         
7014                 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7015                         emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7016                         if (same && offr) {
7017                                 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7018                                 shiftRight_Left2ResultLit (result, result, shCount, sign);
7019                                 return; /* prevent sign-extending result again */
7020                         } else {
7021                                 emitCLRC;
7022                                 if (sign) {
7023                                         emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7024                                         emitSETC;
7025                                 }
7026                                 for (i = size-1; i >= 0; i--) {
7027                                         if (same && !offr) {
7028                                                 emitpcode (POC_RRF, popGet (AOP(left), i));
7029                                         } else {
7030                                                 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7031                                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7032                                         }
7033                                 } // for i
7034                         } // if (offr)
7035                         break;
7036                         
7037                 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7038                         /* works in-place/with offr as well */
7039                         emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7040                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7041                         emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7042
7043                         for (i = 1; i < size; i++)
7044                         {
7045                                 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7046                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7047                                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7048                                 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7049                                 emitpcode (POC_XORWF, popGet (AOP(result), i));
7050                         } // for i
7051
7052                         if (sign)
7053                         {
7054                                 emitpcode (POC_MOVLW, popGetLit (0xF0));
7055                                 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7056                                 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7057                         } // if
7058                         break;
7059                         
7060                 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7061                         /* works in-place/with offr as well */
7062                         emitpcode (POC_RLFW, popGet (AOP(left), offr));
7063                         for (i = 0; i < size-1; i++) {
7064                                 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7065                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7066                         } // for i
7067                         emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7068                         if (!sign) {
7069                                 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7070                         } else {
7071                                 emitSKPNC;
7072                                 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7073                         }
7074                         break;
7075                 
7076                 default:
7077                         shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7078                         shiftRight_Left2ResultLit (result, result, 1, sign);
7079                         return; /* prevent sign extending result again */
7080                         break;
7081                 } // switch
7082         } // if
7083
7084         addSign (result, size, sign);
7085 }
7086
7087 #if 0
7088 /*-----------------------------------------------------------------*/
7089 /* shiftL2Left2Result - shift left two bytes from left to result   */
7090 /*-----------------------------------------------------------------*/
7091 static void shiftL2Left2Result (operand *left, int offl,
7092                                                                 operand *result, int offr, int shCount)
7093 {
7094         FENTRY;
7095         
7096         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7097         
7098         if(pic14_sameRegs(AOP(result), AOP(left))) {
7099                 switch(shCount) {
7100                 case 0:
7101                         break;
7102                 case 1:
7103                 case 2:
7104                 case 3:
7105                         
7106                         emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7107                         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7108                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7109                         
7110                         while(--shCount) {
7111                                 emitCLRC;
7112                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7113                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7114                         }
7115                         
7116                         break;
7117                 case 4:
7118                 case 5:
7119                         emitpcode(POC_MOVLW, popGetLit(0x0f));
7120                         emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7121                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7122                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7123                         emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7124                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7125                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7126                         if(shCount >=5) {
7127                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7128                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7129                         }
7130                         break;
7131                 case 6:
7132                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7133                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7134                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7135                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7136                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7137                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7138                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7139                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7140                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7141                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7142                         break;
7143                 case 7:
7144                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7145                         emitpcode(POC_RRFW, popGet(AOP(result),offr));
7146                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7147                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7148                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7149                 }
7150                 
7151         } else {
7152                 switch(shCount) {
7153                 case 0:
7154                         break;
7155                 case 1:
7156                 case 2:
7157                 case 3:
7158                 /* note, use a mov/add for the shift since the mov has a
7159                         chance of getting optimized out */
7160                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7161                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7162                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7163                         emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
7164                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7165                         
7166                         while(--shCount) {
7167                                 emitCLRC;
7168                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7169                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7170                         }
7171                         break;
7172                         
7173                 case 4:
7174                 case 5:
7175                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7176                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7177                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7178                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7179                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7180                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7181                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7182                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7183                         
7184                         
7185                         if(shCount == 5) {
7186                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7187                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7188                         }
7189                         break;
7190                 case 6:
7191                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7192                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7193                         emitpcode(POC_RRFW, popGet(AOP(result),offl));
7194                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
7195                         
7196                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7197                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7198                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7199                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7200                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7201                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7202                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7203                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7204                         break;
7205                 case 7:
7206                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7207                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7208                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7209                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7210                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7211                 }
7212         }
7213         
7214 }
7215
7216 /*-----------------------------------------------------------------*/
7217 /* shiftR2Left2Result - shift right two bytes from left to result  */
7218 /*-----------------------------------------------------------------*/
7219 static void shiftR2Left2Result (operand *left, int offl,
7220                                                                 operand *result, int offr,
7221                                                                 int shCount, int sign)
7222 {
7223         int same=0;
7224         
7225         FENTRY;
7226         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7227         same = pic14_sameRegs(AOP(result), AOP(left));
7228         
7229         if(same && ((offl + MSB16) == offr)){
7230                 same=1;
7231                 /* don't crash result[offr] */
7232                 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7233                 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7234         }
7235         /* else {
7236         movLeft2Result(left,offl, result, offr);
7237         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7238         }
7239         */
7240         /* a:x >> shCount (x = lsb(result))*/
7241         /*
7242         if(sign)
7243         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7244         else {
7245         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7246         */
7247         switch(shCount) {
7248         case 0:
7249                 break;
7250         case 1:
7251         case 2:
7252         case 3:
7253                 if(sign)
7254                         emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7255                 else
7256                         emitCLRC;
7257                 
7258                 if(same) {
7259                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7260                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7261                 } else {
7262                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7263                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7264                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7265                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7266                 }
7267                 
7268                 while(--shCount) {
7269                         if(sign)
7270                                 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7271                         else
7272                                 emitCLRC;
7273                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7274                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7275                 }
7276                 break;
7277         case 4:
7278         case 5:
7279                 if(same) {
7280                         
7281                         emitpcode(POC_MOVLW, popGetLit(0xf0));
7282                         emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7283                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7284                         
7285                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7286                         emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7287                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7288                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7289                 } else {
7290                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7291                         emitpcode(POC_ANDLW, popGetLit(0x0f));
7292                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7293                         
7294                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7295                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7296                         emitpcode(POC_ANDLW, popGetLit(0xf0));
7297                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7298                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7299                 }
7300                 
7301                 if(shCount >=5) {
7302                         emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7303                         emitpcode(POC_RRF, popGet(AOP(result),offr));
7304                 }
7305                 
7306                 if(sign) {
7307                         emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7308                         emitpcode(POC_BTFSC, 
7309                                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7310                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7311                 }
7312                 
7313                 break;
7314                 
7315         case 6:
7316                 if(same) {
7317                         
7318                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7319                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7320                         
7321                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7322                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7323                         emitpcode(POC_RLFW, popGet(AOP(result),offr));
7324                         emitpcode(POC_ANDLW,popGetLit(0x03));
7325                         if(sign) {
7326                                 emitpcode(POC_BTFSC, 
7327                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7328                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7329                         }
7330                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7331                         emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7332                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7333                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7334                 } else {
7335                         emitpcode(POC_RLFW, popGet(AOP(left),offl));
7336                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7337                         emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7338                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7339                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7340                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7341                         emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7342                         emitpcode(POC_ANDLW,popGetLit(0x03));
7343                         if(sign) {
7344                                 emitpcode(POC_BTFSC, 
7345                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7346                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7347                         }
7348                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7349                         //emitpcode(POC_RLF,  popGet(AOP(result),offr));
7350                         
7351                         
7352                 }
7353                 
7354                 break;
7355         case 7:
7356                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7357                 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7358                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7359                 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7360                 if(sign) {
7361                         emitSKPNC;
7362                         emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7363                 } else 
7364                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7365   }
7366 }
7367
7368 /*-----------------------------------------------------------------*/
7369 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7370 /*-----------------------------------------------------------------*/
7371 static void shiftLLeftOrResult (operand *left, int offl,
7372                                                                 operand *result, int offr, int shCount)
7373 {
7374         FENTRY;
7375         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7376         
7377         /* shift left accumulator */
7378         AccLsh(left,offl,shCount);
7379         /* or with result */
7380         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7381         assert ( !"broken (modifies left, fails for left==result))" );
7382 }
7383
7384 /*-----------------------------------------------------------------*/
7385 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7386 /*-----------------------------------------------------------------*/
7387 static void shiftRLeftOrResult (operand *left, int offl,
7388                                                                 operand *result, int offr, int shCount)
7389 {
7390         FENTRY;
7391         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7392         
7393         /* shift right accumulator */
7394         AccRsh(left,offl,shCount);
7395         /* or with result */
7396         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7397         assert ( !"broken (modifies left, fails for left==result))" );
7398 }
7399
7400 /*-----------------------------------------------------------------*/
7401 /* genlshOne - left shift a one byte quantity by known count       */
7402 /*-----------------------------------------------------------------*/
7403 static void genlshOne (operand *result, operand *left, int shCount)
7404 {       
7405         FENTRY;
7406         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7407         shiftL1Left2Result(left, LSB, result, LSB, shCount);
7408 }
7409
7410 /*-----------------------------------------------------------------*/
7411 /* genlshTwo - left shift two bytes by known amount != 0           */
7412 /*-----------------------------------------------------------------*/
7413 static void genlshTwo (operand *result,operand *left, int shCount)
7414 {
7415         int size;
7416         
7417         FENTRY;
7418         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7419         size = pic14_getDataSize(result);
7420         
7421         /* if shCount >= 8 */
7422         if (shCount >= 8) {
7423                 shCount -= 8 ;
7424                 
7425                 if (size > 1){
7426                         if (shCount)
7427                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7428                         else 
7429                                 movLeft2Result(left, LSB, result, MSB16);
7430                 }
7431                 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7432         }
7433         
7434         /*  1 <= shCount <= 7 */
7435         else {  
7436                 if(size == 1)
7437                         shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7438                 else 
7439                         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7440         }
7441 }
7442
7443 /*-----------------------------------------------------------------*/
7444 /* shiftLLong - shift left one long from left to result            */
7445 /* offl = LSB or MSB16                                             */
7446 /*-----------------------------------------------------------------*/
7447 static void shiftLLong (operand *left, operand *result, int offr )
7448 {
7449         char *l;
7450         int size = AOP_SIZE(result);
7451         
7452         FENTRY;
7453         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7454         if(size >= LSB+offr){
7455                 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7456                 MOVA(l);
7457                 pic14_emitcode("add","a,acc");
7458                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7459                         size >= MSB16+offr && offr != LSB )
7460                         pic14_emitcode("xch","a,%s",
7461                         aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7462                 else      
7463                         aopPut(AOP(result),"a",LSB+offr);
7464         }
7465         
7466         if(size >= MSB16+offr){
7467                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7468                         l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7469                         MOVA(l);
7470                 }
7471                 pic14_emitcode("rlc","a");
7472                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7473                         size >= MSB24+offr && offr != LSB)
7474                         pic14_emitcode("xch","a,%s",
7475                         aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7476                 else      
7477                         aopPut(AOP(result),"a",MSB16+offr);
7478         }
7479         
7480         if(size >= MSB24+offr){
7481                 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7482                         l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7483                         MOVA(l);
7484                 }
7485                 pic14_emitcode("rlc","a");
7486                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7487                         size >= MSB32+offr && offr != LSB )
7488                         pic14_emitcode("xch","a,%s",
7489                         aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7490                 else      
7491                         aopPut(AOP(result),"a",MSB24+offr);
7492         }
7493         
7494         if(size > MSB32+offr){
7495                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7496                         l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7497                         MOVA(l);  
7498                 }
7499                 pic14_emitcode("rlc","a");
7500                 aopPut(AOP(result),"a",MSB32+offr);
7501         }
7502         if(offr != LSB)
7503                 aopPut(AOP(result),zero,LSB);       
7504 }
7505
7506 /*-----------------------------------------------------------------*/
7507 /* genlshFour - shift four byte by a known amount != 0             */
7508 /*-----------------------------------------------------------------*/
7509 static void genlshFour (operand *result, operand *left, int shCount)
7510 {
7511         int size;
7512         
7513         FENTRY;
7514         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7515         size = AOP_SIZE(result);
7516         
7517         /* if shifting more that 3 bytes */
7518         if (shCount >= 24 ) {
7519                 shCount -= 24;
7520                 if (shCount)
7521                 /* lowest order of left goes to the highest
7522                 order of the destination */
7523                 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7524                 else
7525                         movLeft2Result(left, LSB, result, MSB32);
7526                 aopPut(AOP(result),zero,LSB);
7527                 aopPut(AOP(result),zero,MSB16);
7528                 aopPut(AOP(result),zero,MSB32);
7529                 return;
7530         }
7531         
7532         /* more than two bytes */
7533         else if ( shCount >= 16 ) {
7534                 /* lower order two bytes goes to higher order two bytes */
7535                 shCount -= 16;
7536                 /* if some more remaining */
7537                 if (shCount)
7538                         shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7539                 else {
7540                         movLeft2Result(left, MSB16, result, MSB32);
7541                         movLeft2Result(left, LSB, result, MSB24);
7542                 }
7543                 aopPut(AOP(result),zero,MSB16);
7544                 aopPut(AOP(result),zero,LSB);
7545                 return;
7546         }    
7547         
7548         /* if more than 1 byte */
7549         else if ( shCount >= 8 ) {
7550                 /* lower order three bytes goes to higher order  three bytes */
7551                 shCount -= 8;
7552                 if(size == 2){
7553                         if(shCount)
7554                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7555                         else
7556                                 movLeft2Result(left, LSB, result, MSB16);
7557                 }
7558                 else{   /* size = 4 */
7559                         if(shCount == 0){
7560                                 movLeft2Result(left, MSB24, result, MSB32);
7561                                 movLeft2Result(left, MSB16, result, MSB24);
7562                                 movLeft2Result(left, LSB, result, MSB16);
7563                                 aopPut(AOP(result),zero,LSB);
7564                         }
7565                         else if(shCount == 1)
7566                                 shiftLLong(left, result, MSB16);
7567                         else{
7568                                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7569                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7570                                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7571                                 aopPut(AOP(result),zero,LSB);
7572                         }
7573                 }
7574         }
7575         
7576         /* 1 <= shCount <= 7 */
7577         else if(shCount <= 2){
7578                 shiftLLong(left, result, LSB);
7579                 if(shCount == 2)
7580                         shiftLLong(result, result, LSB);
7581         }
7582         /* 3 <= shCount <= 7, optimize */
7583         else{
7584                 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7585                 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7586                 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7587         }
7588 }
7589 #endif
7590
7591 #if 0
7592 /*-----------------------------------------------------------------*/
7593 /* genLeftShiftLiteral - left shifting by known count              */
7594 /*-----------------------------------------------------------------*/
7595 static void genLeftShiftLiteral (operand *left,
7596                                                                  operand *right,
7597                                                                  operand *result,
7598                                                                  iCode *ic)
7599 {    
7600         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7601         //int size;
7602         
7603         FENTRY;
7604         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7605         freeAsmop(right,NULL,ic,TRUE);
7606         
7607         aopOp(left,ic,FALSE);
7608         aopOp(result,ic,FALSE);
7609
7610         size = getSize(operandType(result));
7611         
7612 #if VIEW_SIZE
7613         pic14_emitcode("; shift left ","result %d, left %d",size,
7614                 AOP_SIZE(left));
7615 #endif
7616         
7617         /* I suppose that the left size >= result size */
7618         if(shCount == 0){
7619                 while(size--){
7620                         movLeft2Result(left, size, result, size);
7621                 }
7622         }
7623         
7624         else if(shCount >= (size * 8))
7625                 while(size--)
7626                         aopPut(AOP(result),zero,size);
7627                 else{
7628                         switch (size) {
7629                         case 1:
7630                                 genlshOne (result,left,shCount);
7631                                 break;
7632                                 
7633                         case 2:
7634                         case 3:
7635                                 genlshTwo (result,left,shCount);
7636                                 break;
7637                                 
7638                         case 4:
7639                                 genlshFour (result,left,shCount);
7640                                 break;
7641                         }
7642                 }
7643                 freeAsmop(left,NULL,ic,TRUE);
7644                 freeAsmop(result,NULL,ic,TRUE);
7645 }
7646 #endif
7647
7648 /*-----------------------------------------------------------------*
7649 * genMultiAsm - repeat assembly instruction for size of register.
7650 * if endian == 1, then the high byte (i.e base address + size of 
7651 * register) is used first else the low byte is used first;
7652 *-----------------------------------------------------------------*/
7653 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7654 {
7655         
7656         int offset = 0;
7657         
7658         FENTRY;
7659         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7660         
7661         if(!reg)
7662                 return;
7663         
7664         if(!endian) {
7665                 endian = 1;
7666         } else {
7667                 endian = -1;
7668                 offset = size-1;
7669         }
7670         
7671         while(size--) {
7672                 emitpcode(poc,    popGet(AOP(reg),offset));
7673                 offset += endian;
7674         }
7675         
7676 }
7677
7678 #if 0
7679 /*-----------------------------------------------------------------*/
7680 /* genLeftShift - generates code for left shifting                 */
7681 /*-----------------------------------------------------------------*/
7682 static void genLeftShift (iCode *ic)
7683 {
7684         operand *left,*right, *result;
7685         int size, offset;
7686         unsigned long lit = 0L;
7687         char *l;
7688         symbol *tlbl , *tlbl1;
7689         pCodeOp *pctemp;
7690         
7691         FENTRY;
7692         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7693         
7694         right = IC_RIGHT(ic);
7695         left  = IC_LEFT(ic);
7696         result = IC_RESULT(ic);
7697         
7698         aopOp(right,ic,FALSE);
7699         aopOp(left,ic,FALSE);
7700         aopOp(result,ic,FALSE);
7701         
7702         
7703         /* if the shift count is known then do it 
7704         as efficiently as possible */
7705         if (AOP_TYPE(right) == AOP_LIT) {
7706                 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7707                 return ;
7708         }
7709         
7710         /* shift count is unknown then we have to form 
7711         a loop get the loop count in B : Note: we take
7712         only the lower order byte since shifting
7713         more that 32 bits make no sense anyway, ( the
7714         largest size of an object can be only 32 bits ) */  
7715         
7716         /* this code fails for RIGHT == RESULT */
7717         assert (!pic14_sameRegs (AOP(right), AOP(result)));
7718         
7719         /* now move the left to the result if they are not the
7720         same */
7721         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7722                 AOP_SIZE(result) > 1) {
7723                 
7724                 size = AOP_SIZE(result);
7725                 offset=0;
7726                 while (size--) {
7727                         l = aopGet(AOP(left),offset,FALSE,TRUE);
7728                         if (*l == '@' && (IS_AOP_PREG(result))) {
7729                                 
7730                                 pic14_emitcode("mov","a,%s",l);
7731                                 aopPut(AOP(result),"a",offset);
7732                         } else {
7733                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7734                                 emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7735                                 //aopPut(AOP(result),l,offset);
7736                         }
7737                         offset++;
7738                 }
7739         }
7740         
7741         if(AOP_TYPE(left) == AOP_LIT)
7742                 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7743
7744         size = AOP_SIZE(result);
7745         
7746         /* if it is only one byte then */
7747         if (size == 1) {
7748                 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7749                         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7750                         emitpcode(POC_ANDLW,  popGetLit(0xf0));
7751                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7752                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7753                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7754                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7755                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7756                         emitpcode(POC_RLFW,   popGet(AOP(result),0));
7757                         emitpcode(POC_ANDLW,  popGetLit(0xfe));
7758                         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7759                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7760                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7761                 } else {
7762                         
7763                         tlbl = newiTempLabel(NULL);
7764                         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7765                                 mov2w (AOP(left), 0);
7766                                 emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7767                         }
7768                         
7769                         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7770                         emitpcode(POC_RRF,    popGet(AOP(result),0));
7771                         emitpLabel(tlbl->key);
7772                         emitpcode(POC_RLF,    popGet(AOP(result),0));
7773                         emitpcode(POC_ADDLW,  popGetLit(1));
7774                         emitSKPC;
7775                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7776                 }
7777                 goto release ;
7778         }
7779         
7780         if (pic14_sameRegs(AOP(left),AOP(result))) {
7781                 
7782                 tlbl = newiTempLabel(NULL);
7783                 emitpcode(POC_COMFW,  popGet(AOP(right),0));
7784                 genMultiAsm(POC_RRF, result, size,1);
7785                 emitpLabel(tlbl->key);
7786                 genMultiAsm(POC_RLF, result, size,0);
7787                 emitpcode(POC_ADDLW,  popGetLit(1));
7788                 emitSKPC;
7789                 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7790                 goto release;
7791         }
7792         
7793         //tlbl = newiTempLabel(NULL);
7794         //offset = 0 ;   
7795         //tlbl1 = newiTempLabel(NULL);
7796         
7797         //reAdjustPreg(AOP(result));    
7798         
7799         //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7800         //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7801         //l = aopGet(AOP(result),offset,FALSE,FALSE);
7802         //MOVA(l);
7803         //pic14_emitcode("add","a,acc");         
7804         //aopPut(AOP(result),"a",offset++);
7805         //while (--size) {
7806         //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7807         //  MOVA(l);
7808         //  pic14_emitcode("rlc","a");         
7809         //  aopPut(AOP(result),"a",offset++);
7810         //}
7811         //reAdjustPreg(AOP(result));
7812         
7813         //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7814         //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7815         
7816         
7817         tlbl = newiTempLabel(NULL);
7818         tlbl1= newiTempLabel(NULL);
7819         
7820         size = AOP_SIZE(result);
7821         offset = 1;
7822         
7823         pctemp = popGetTempReg();  /* grab a temporary working register. */
7824         
7825         emitpcode(POC_MOVFW, popGet(AOP(right),0));
7826         
7827         /* offset should be 0, 1 or 3 */
7828         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7829         emitSKPNZ;
7830         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7831         
7832         emitpcode(POC_MOVWF, pctemp);
7833         
7834         
7835         emitpLabel(tlbl->key);
7836         
7837         emitCLRC;
7838         emitpcode(POC_RLF,  popGet(AOP(result),0));
7839         while(--size)
7840                 emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7841         
7842         emitpcode(POC_DECFSZ,  pctemp);
7843         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7844         emitpLabel(tlbl1->key);
7845         
7846         popReleaseTempReg(pctemp);
7847         
7848         
7849 release:
7850         freeAsmop (right,NULL,ic,TRUE);
7851         freeAsmop(left,NULL,ic,TRUE);
7852         freeAsmop(result,NULL,ic,TRUE);
7853 }
7854 #endif
7855
7856 #if 0
7857 /*-----------------------------------------------------------------*/
7858 /* genrshOne - right shift a one byte quantity by known count      */
7859 /*-----------------------------------------------------------------*/
7860 static void genrshOne (operand *result, operand *left,
7861                                            int shCount, int sign)
7862 {
7863         FENTRY;
7864         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7865         shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7866 }
7867
7868 /*-----------------------------------------------------------------*/
7869 /* genrshTwo - right shift two bytes by known amount != 0          */
7870 /*-----------------------------------------------------------------*/
7871 static void genrshTwo (operand *result,operand *left,
7872                                            int shCount, int sign)
7873 {
7874         FENTRY;
7875         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7876         /* if shCount >= 8 */
7877         if (shCount >= 8) {
7878                 shCount -= 8 ;
7879                 if (shCount)
7880                         shiftR1Left2Result(left, MSB16, result, LSB,
7881                         shCount, sign);
7882                 else
7883                         movLeft2Result(left, MSB16, result, LSB);
7884                 
7885                 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7886                 
7887                 if(sign) {
7888                         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7889                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7890                 }
7891         }
7892         
7893         /*  1 <= shCount <= 7 */
7894         else
7895                 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7896 }
7897
7898 /*-----------------------------------------------------------------*/
7899 /* shiftRLong - shift right one long from left to result           */
7900 /* offl = LSB or MSB16                                             */
7901 /*-----------------------------------------------------------------*/
7902 static void shiftRLong (operand *left, int offl,
7903                                                 operand *result, int sign)
7904 {
7905         int size, same;
7906         
7907         FENTRY;
7908         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7909         
7910         size = AOP_SIZE(left);
7911         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7912         
7913         if (sign)
7914                 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7915         else
7916                 emitCLRC;
7917
7918         assert (offl >= 0 && offl < size);
7919
7920         same = pic14_sameRegs (AOP(left), AOP(result));
7921
7922         /* perform the shift */
7923         while (size--)
7924         {
7925                 if (same && !offl) {
7926                         emitpcode (POC_RRF, popGet (AOP(result), size));
7927                 } else {
7928                         emitpcode (POC_RRFW, popGet (AOP(left), size));
7929                         emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7930                 }
7931         } // while
7932
7933         addSign (result, AOP_SIZE(left) - offl, sign);
7934 }
7935
7936 /*-----------------------------------------------------------------*/
7937 /* genrshFour - shift four byte by a known amount != 0             */
7938 /*-----------------------------------------------------------------*/
7939 static void genrshFour (operand *result, operand *left,
7940                                                 int shCount, int sign)
7941 {
7942         FENTRY;
7943         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7944         /* if shifting more that 3 bytes */
7945         if(shCount >= 24 ) {
7946                 shCount -= 24;
7947                 if(shCount)
7948                         shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7949                 else
7950                         movLeft2Result(left, MSB32, result, LSB);
7951                 
7952                 addSign(result, MSB16, sign);
7953         }
7954         else if(shCount >= 16){
7955                 shCount -= 16;
7956                 if(shCount)
7957                         shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7958                 else{
7959                         movLeft2Result(left, MSB24, result, LSB);
7960                         movLeft2Result(left, MSB32, result, MSB16);
7961                 }
7962                 addSign(result, MSB24, sign);
7963         }
7964         else if(shCount >= 8){
7965                 shCount -= 8;
7966                 if(shCount == 1)
7967                         shiftRLong(left, MSB16, result, sign);
7968                 else if(shCount == 0){
7969                         movLeft2Result(left, MSB16, result, LSB);
7970                         movLeft2Result(left, MSB24, result, MSB16);
7971                         movLeft2Result(left, MSB32, result, MSB24);
7972                         addSign(result, MSB32, sign);
7973                 }
7974                 else{
7975                         shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7976                         shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7977                         /* the last shift is signed */
7978                         shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7979                         addSign(result, MSB32, sign);
7980                 }
7981         }
7982         else{   /* 1 <= shCount <= 7 */
7983                 if(shCount <= 2){
7984                         shiftRLong(left, LSB, result, sign);
7985                         if(shCount == 2)
7986                                 shiftRLong(result, LSB, result, sign);
7987                 }
7988                 else{
7989                         shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7990                         shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7991                         shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7992                 }
7993         }
7994 }
7995
7996 /*-----------------------------------------------------------------*/
7997 /* genRightShiftLiteral - right shifting by known count            */
7998 /*-----------------------------------------------------------------*/
7999 static void genRightShiftLiteral (operand *left,
8000                                                                   operand *right,
8001                                                                   operand *result,
8002                                                                   iCode *ic,
8003                                                                   int sign)
8004 {    
8005         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8006         int lsize,res_size;
8007         
8008         FENTRY;
8009         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8010         freeAsmop(right,NULL,ic,TRUE);
8011         
8012         aopOp(left,ic,FALSE);
8013         aopOp(result,ic,FALSE);
8014         
8015 #if VIEW_SIZE
8016         pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8017                 AOP_SIZE(left));
8018 #endif
8019         
8020         lsize = pic14_getDataSize(left);
8021         res_size = pic14_getDataSize(result);
8022         /* test the LEFT size !!! */
8023         
8024         /* I suppose that the left size >= result size */
8025         if(shCount == 0){
8026                 while(res_size--)
8027                         movLeft2Result(left, res_size, result, res_size);
8028         }
8029         
8030         else if(shCount >= (lsize * 8)){
8031                 
8032                 if(res_size == 1) {
8033                         emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8034                         if(sign) {
8035                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8036                                 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8037                         }
8038                 } else {
8039                         
8040                         if(sign) {
8041                                 emitpcode(POC_MOVLW, popGetLit(0));
8042                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8043                                 emitpcode(POC_MOVLW, popGetLit(0xff));
8044                                 while(res_size--)
8045                                         emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8046                                 
8047                         } else {
8048                                 
8049                                 while(res_size--)
8050                                         emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8051                         }
8052                 }
8053         } else {
8054                 
8055                 switch (res_size) {
8056                 case 1:
8057                         genrshOne (result,left,shCount,sign);
8058                         break;
8059                         
8060                 case 2:
8061                         genrshTwo (result,left,shCount,sign);
8062                         break;
8063                         
8064                 case 4:
8065                         genrshFour (result,left,shCount,sign);
8066                         break;
8067                 default :
8068                         break;
8069                 }
8070                 
8071         }
8072
8073         freeAsmop(left,NULL,ic,TRUE);
8074         freeAsmop(result,NULL,ic,TRUE);
8075 }
8076 #endif
8077
8078 #if 0
8079 /*-----------------------------------------------------------------*/
8080 /* genSignedRightShift - right shift of signed number              */
8081 /*-----------------------------------------------------------------*/
8082 static void genSignedRightShift (iCode *ic)
8083 {
8084         operand *right, *left, *result;
8085         int size, offset;
8086         //  char *l;
8087         symbol *tlbl, *tlbl1 ;
8088         pCodeOp *pctemp;
8089         
8090         //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8091         
8092         /* we do it the hard way put the shift count in b
8093         and loop thru preserving the sign */
8094         FENTRY;
8095         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8096         
8097         right = IC_RIGHT(ic);
8098         left  = IC_LEFT(ic);
8099         result = IC_RESULT(ic);
8100         
8101         aopOp(right,ic,FALSE);  
8102         aopOp(left,ic,FALSE);
8103         aopOp(result,ic,FALSE);
8104         
8105         
8106         if ( AOP_TYPE(right) == AOP_LIT) {
8107                 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8108                 //genRightShiftLiteral (left,right,result,ic,1);
8109                 return ;
8110         }
8111         /* shift count is unknown then we have to form 
8112         a loop get the loop count in B : Note: we take
8113         only the lower order byte since shifting
8114         more that 32 bits make no sense anyway, ( the
8115         largest size of an object can be only 32 bits ) */  
8116         
8117         //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8118         //pic14_emitcode("inc","b");
8119         //freeAsmop (right,NULL,ic,TRUE);
8120         //aopOp(left,ic,FALSE);
8121         //aopOp(result,ic,FALSE);
8122         
8123         /* now move the left to the result if they are not the
8124         same */
8125         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
8126                 AOP_SIZE(result) > 1) {
8127                 
8128                 size = AOP_SIZE(result);
8129                 offset=0;
8130                 while (size--) { 
8131                         /*
8132                         l = aopGet(AOP(left),offset,FALSE,TRUE);
8133                         if (*l == '@' && IS_AOP_PREG(result)) {
8134                                 pic14_emitcode("mov","a,%s",l);
8135                                 aopPut(AOP(result),"a",offset);
8136                         } else
8137                         aopPut(AOP(result),l,offset);
8138                         */
8139                         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
8140                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
8141                         
8142                         offset++;
8143                 }
8144         }
8145         
8146         /* mov the highest order bit to OVR */    
8147         tlbl = newiTempLabel(NULL);
8148         tlbl1= newiTempLabel(NULL);
8149         
8150         size = AOP_SIZE(result);
8151         offset = size - 1;
8152         
8153         pctemp = popGetTempReg();  /* grab a temporary working register. */
8154         
8155         emitpcode(POC_MOVFW, popGet(AOP(right),0));
8156         
8157         /* offset should be 0, 1 or 3 */
8158         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8159         emitSKPNZ;
8160         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
8161         
8162         emitpcode(POC_MOVWF, pctemp);
8163         
8164         
8165         emitpLabel(tlbl->key);
8166         
8167         emitpcode(POC_RLFW,  popGet(AOP(result),offset));
8168         emitpcode(POC_RRF,   popGet(AOP(result),offset));
8169         
8170         while(--size) {
8171                 emitpcode(POC_RRF,   popGet(AOP(result),--offset));
8172         }
8173         
8174         emitpcode(POC_DECFSZ,  pctemp);
8175         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8176         emitpLabel(tlbl1->key);
8177         
8178         popReleaseTempReg(pctemp);
8179 #if 0
8180         size = AOP_SIZE(result);
8181         offset = size - 1;
8182         pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8183         pic14_emitcode("rlc","a");
8184         pic14_emitcode("mov","ov,c");
8185         /* if it is only one byte then */
8186         if (size == 1) {
8187                 l = aopGet(AOP(left),0,FALSE,FALSE);
8188                 MOVA(l);
8189                 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8190                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8191                 pic14_emitcode("mov","c,ov");
8192                 pic14_emitcode("rrc","a");
8193                 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8194                 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8195                 aopPut(AOP(result),"a",0);
8196                 goto release ;
8197         }
8198         
8199         reAdjustPreg(AOP(result));
8200         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8201         pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
8202         pic14_emitcode("mov","c,ov");
8203         while (size--) {
8204                 l = aopGet(AOP(result),offset,FALSE,FALSE);
8205                 MOVA(l);
8206                 pic14_emitcode("rrc","a");         
8207                 aopPut(AOP(result),"a",offset--);
8208         }
8209         reAdjustPreg(AOP(result));
8210         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8211         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8212         
8213 release:
8214 #endif
8215         
8216         freeAsmop(left,NULL,ic,TRUE);
8217         freeAsmop(result,NULL,ic,TRUE);
8218         freeAsmop(right,NULL,ic,TRUE);
8219 }
8220 #endif
8221
8222 /*-----------------------------------------------------------------*/
8223 /* loadSignToC - load the operand's sign bit into CARRY            */
8224 /*-----------------------------------------------------------------*/
8225
8226 static void loadSignToC (operand *op)
8227 {
8228         FENTRY;
8229         assert (op && AOP(op) && AOP_SIZE(op));
8230
8231         emitCLRC;
8232         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8233         emitSETC;
8234 }
8235
8236 /*-----------------------------------------------------------------*/
8237 /* genRightShift - generate code for right shifting                */
8238 /*-----------------------------------------------------------------*/
8239 static void genGenericShift (iCode *ic, int shiftRight)
8240 {
8241         operand *right, *left, *result;
8242         sym_link *retype ;
8243         int size;
8244         symbol *tlbl, *tlbl1, *inverselbl;
8245         
8246         FENTRY;
8247         /* if signed then we do it the hard way preserve the
8248         sign bit moving it inwards */
8249         retype = getSpec(operandType(IC_RESULT(ic)));
8250         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8251         
8252         /* signed & unsigned types are treated the same : i.e. the
8253         signed is NOT propagated inwards : quoting from the
8254         ANSI - standard : "for E1 >> E2, is equivalent to division
8255         by 2**E2 if unsigned or if it has a non-negative value,
8256         otherwise the result is implementation defined ", MY definition
8257         is that the sign does not get propagated */
8258         
8259         right = IC_RIGHT(ic);
8260         left  = IC_LEFT(ic);
8261         result = IC_RESULT(ic);
8262         
8263         aopOp(right,ic,FALSE);
8264         aopOp(left,ic,FALSE);
8265         aopOp(result,ic,FALSE);
8266         
8267         /* if the shift count is known then do it 
8268         as efficiently as possible */
8269         if (AOP_TYPE(right) == AOP_LIT) {
8270                 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8271                 if (lit < 0)
8272                 {
8273                         lit = -lit;
8274                         shiftRight = !shiftRight;
8275                 }
8276                 
8277                 if (shiftRight)
8278                         shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8279                 else
8280                         shiftLeft_Left2ResultLit (left, result, lit);
8281                 //genRightShiftLiteral (left,right,result,ic, 0);
8282                 return ;
8283         }
8284         
8285         /* shift count is unknown then we have to form 
8286         a loop get the loop count in B : Note: we take
8287         only the lower order byte since shifting
8288         more that 32 bits make no sense anyway, ( the
8289         largest size of an object can be only 32 bits ) */  
8290
8291         /* we must not overwrite the shift counter */
8292         assert (!pic14_sameRegs(AOP(right),AOP(result)));
8293         
8294         /* now move the left to the result if they are not the
8295         same */
8296         if (!pic14_sameRegs(AOP(left),AOP(result)))
8297         {
8298                 size = min(AOP_SIZE(result), AOP_SIZE(left));
8299                 while (size--) {
8300                         mov2w(AOP(left), size);
8301                         movwf(AOP(result), size);
8302                 }
8303                 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8304         }
8305         
8306         tlbl = newiTempLabel(NULL);
8307         tlbl1= newiTempLabel(NULL);
8308         inverselbl = NULL;
8309         size = AOP_SIZE(result);
8310
8311         mov2w(AOP(right),0);
8312         if (!SPEC_USIGN(operandType(right)))
8313         {
8314                 inverselbl = newiTempLabel(NULL);
8315                 /* signed shift count -- invert shift direction for c<0 */
8316                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8317                 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8318         } // if
8319         emitpcode(POC_SUBLW, popGetLit(0));     /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8320         /* check for `a = b >> c' with `-c == 0' */
8321         emitSKPNZ;
8322         emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8323         emitpLabel(tlbl->key);
8324         /* propagate the sign bit inwards for SIGNED result */
8325         if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8326         genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8327         emitpcode(POC_ADDLW,  popGetLit(1));    /* clears CARRY (unless W==0 afterwards) */
8328         emitSKPC;
8329         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8330
8331         if (!SPEC_USIGN(operandType(right)))
8332         {
8333                 symbol *inv_loop = newiTempLabel(NULL);
8334
8335                 shiftRight = !shiftRight;       /* invert shift direction */
8336                 
8337                 /* we came here from the code above -- we are done */
8338                 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8339                 
8340                 /* emit code for shifting N<0 steps, count is already in W */
8341                 emitpLabel(inverselbl->key);
8342                 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8343                 emitpLabel(inv_loop->key);
8344                 /* propagate the sign bit inwards for SIGNED result */
8345                 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8346                 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8347                 emitpcode(POC_ADDLW, popGetLit(1));
8348                 emitSKPC;
8349                 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8350         } // if
8351         
8352         emitpLabel(tlbl1->key);
8353         
8354         freeAsmop(left,NULL,ic,TRUE);
8355         freeAsmop (right,NULL,ic,TRUE);
8356         freeAsmop(result,NULL,ic,TRUE);
8357 }
8358
8359 static void genRightShift (iCode *ic)
8360 {
8361         genGenericShift(ic, 1);
8362 }
8363
8364 static void genLeftShift (iCode *ic)
8365 {
8366         genGenericShift(ic, 0);
8367 }
8368
8369 /*-----------------------------------------------------------------*/
8370 /* SetIrp - Set IRP bit                                            */
8371 /*-----------------------------------------------------------------*/
8372 void SetIrp(operand *result) {
8373         FENTRY;
8374         if (AOP_TYPE(result) == AOP_LIT) {
8375                 unsigned lit = (unsigned)operandLitValue(result);
8376                 if (lit&0x100)
8377                         emitSETIRP;
8378                 else
8379                         emitCLRIRP;
8380         } else {
8381                 if (PCOP(AOP(result))->type == PO_LITERAL) {
8382                         int addrs = PCOL(AOP(result))->lit;
8383                         if (addrs & 0x100)
8384                                 emitSETIRP;
8385                         else
8386                                 emitCLRIRP;
8387                 } else {
8388                         emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8389                         if(AOP_SIZE(result) > 1) {
8390                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8391                                 emitSETIRP;
8392                         }
8393                 }
8394         }
8395 }
8396
8397 static void
8398 setup_fsr (operand *ptr)
8399 {
8400   mov2w_op(ptr, 0);
8401   emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8402
8403   /* also setup-up IRP */
8404   SetIrp (ptr);
8405 }
8406
8407 /*-----------------------------------------------------------------*/
8408 /* emitPtrByteGet - emits code to get a byte into WREG from an     */
8409 /*                  arbitrary pointer (__code, __data, generic)    */
8410 /*-----------------------------------------------------------------*/
8411 static void
8412 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8413 {
8414     FENTRY;
8415     switch (p_type)
8416     {
8417     case POINTER:
8418     case FPOINTER:
8419       if (!alreadyAddressed) setup_fsr (src);
8420       emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8421       break;
8422     
8423     case CPOINTER:
8424       assert( AOP_SIZE(src) == 2 );
8425       mov2w_op(src, 0);
8426       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8427       mov2w_op(src, 1);
8428       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8429       emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE));   /* GPOINTER tag for __code space */
8430       call_libraryfunc ("__gptrget1");
8431       break;
8432     
8433     case GPOINTER:
8434       assert( AOP_SIZE(src) == 3 );
8435       mov2w_op(src, 0);
8436       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8437       mov2w_op(src, 1);
8438       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8439       mov2w_op(src, 2);
8440       call_libraryfunc ("__gptrget1");
8441       break;
8442     
8443     default:
8444       assert( !"unhandled pointer type" );
8445       break;
8446     }
8447 }
8448
8449 /*-----------------------------------------------------------------*/
8450 /* emitPtrByteSet - emits code to set a byte from src through a    */
8451 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR).       */
8452 /*-----------------------------------------------------------------*/
8453 static void
8454 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8455 {
8456     FENTRY;
8457     switch (p_type)
8458     {
8459     case POINTER:
8460     case FPOINTER:
8461       if (!alreadyAddressed) setup_fsr (dst);
8462       emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8463       break;
8464     
8465     case CPOINTER:
8466       assert( !"trying to assign to __code pointer" );
8467       break;
8468     
8469     case GPOINTER:
8470       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8471       mov2w_op(dst, 0);
8472       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8473       mov2w_op(dst, 1);
8474       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8475       mov2w_op(dst, 2);
8476       call_libraryfunc ("__gptrput1");
8477       break;
8478
8479     default:
8480       assert( !"unhandled pointer type" );
8481       break;
8482     }
8483 }
8484
8485 /*-----------------------------------------------------------------*/
8486 /* genUnpackBits - generates code for unpacking bits               */
8487 /*-----------------------------------------------------------------*/
8488 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8489 {    
8490   int rsize;            /* result size */
8491   sym_link *etype;      /* bitfield type information */
8492   int blen;             /* bitfield length */
8493   int bstr;             /* bitfield starting bit within byte */
8494
8495   FENTRY;
8496   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8497   etype = getSpec(operandType(result));
8498   rsize = getSize (operandType (result));
8499   blen = SPEC_BLEN (etype);
8500   bstr = SPEC_BSTR (etype);
8501
8502   /* single bit field case */
8503   if (blen == 1) {
8504     if (ifx) { /* that is for an if statement */
8505       pCodeOp *pcop;
8506       resolvedIfx rIfx;
8507       resolveIfx(&rIfx,ifx);
8508       if (ptype == -1) /* direct */
8509         pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8510       else
8511         pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8512       emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8513       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8514       ifx->generated=1;
8515     } else {
8516       int i;
8517       assert (!pic14_sameRegs (AOP(result), AOP(left)));
8518       for (i=0; i < AOP_SIZE(result); i++)
8519         emitpcode (POC_CLRF, popGet (AOP(result), i));
8520
8521       switch (ptype)
8522       {
8523       case -1:
8524         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8525         /* adjust result below */
8526         break;
8527         
8528       case POINTER:
8529       case FPOINTER:
8530       case GPOINTER:
8531       case CPOINTER:
8532         emitPtrByteGet (left, ptype, FALSE);
8533         emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8534         emitSKPZ;
8535         /* adjust result below */
8536         break;
8537         
8538       default:
8539         assert( !"unhandled pointer type" );
8540       } // switch
8541
8542       /* move sign-/zero extended bit to result */
8543       if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8544         emitpcode (POC_INCF, popGet (AOP(result), 0));
8545       } else {
8546         emitpcode (POC_DECF, popGet (AOP(result), 0));
8547       }
8548       addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8549     }
8550     return;
8551   }
8552   else if (blen <= 8 && ((blen + bstr) <= 8))
8553   {
8554     /* blen > 1 */
8555     int i;
8556
8557     for (i=0; i < AOP_SIZE(result); i++)
8558       emitpcode (POC_CLRF, popGet (AOP(result), i));
8559
8560     switch (ptype)
8561     {
8562     case -1:
8563       mov2w(AOP(left), 0);
8564       break;
8565       
8566     case POINTER:
8567     case FPOINTER:
8568     case GPOINTER:
8569     case CPOINTER:
8570       emitPtrByteGet (left, ptype, FALSE);
8571       break;
8572       
8573     default:
8574       assert( !"unhandled pointer type" );
8575     } // switch
8576
8577     if (blen < 8)
8578       emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8579     movwf(AOP(result), 0);
8580     AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8581
8582     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8583     {
8584       /* signed bitfield */
8585       assert (bstr + blen > 0);
8586       emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8587       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8588       emitpcode(POC_IORWF, popGet(AOP(result),0));
8589     }
8590     addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8591     return;
8592   }
8593
8594   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8595 }
8596
8597 #if 1
8598 /*-----------------------------------------------------------------*/
8599 /* genDataPointerGet - generates code when ptr offset is known     */
8600 /*-----------------------------------------------------------------*/
8601 static void genDataPointerGet (operand *left, 
8602         operand *result, 
8603         iCode *ic)
8604 {
8605         int size , offset = 0;
8606                 
8607         FENTRY;
8608         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8609         
8610         
8611         /* optimization - most of the time, left and result are the same
8612         * address, but different types. for the pic code, we could omit
8613         * the following
8614         */
8615         aopOp(result,ic,TRUE);
8616         
8617         if (pic14_sameRegs (AOP(left), AOP(result)))
8618                 return;
8619         
8620         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8621         
8622         //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8623         
8624         size = AOP_SIZE(result);
8625         if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8626         
8627         offset = 0;
8628         while (size--) {
8629                 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8630                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8631                 offset++;
8632         }
8633         
8634         freeAsmop(left,NULL,ic,TRUE);
8635         freeAsmop(result,NULL,ic,TRUE);
8636 }
8637 #endif
8638
8639 /*-----------------------------------------------------------------*/
8640 /* genNearPointerGet - pic14_emitcode for near pointer fetch       */
8641 /*-----------------------------------------------------------------*/
8642 static void genNearPointerGet (operand *left, 
8643                                                            operand *result, 
8644                                                            iCode *ic)
8645 {
8646         asmop *aop = NULL;
8647         sym_link *ltype = operandType(left);
8648         sym_link *rtype = operandType(result);
8649         sym_link *retype= getSpec(rtype);      /* bitfield type information */
8650         int direct = 0;
8651
8652         FENTRY;
8653         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8654         
8655         
8656         aopOp(left,ic,FALSE);
8657         
8658         /* if left is rematerialisable and
8659         result is not bit variable type and
8660         the left is pointer to data space i.e
8661         lower 128 bytes of space */
8662         if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8663                 !IS_BITVAR(retype)         &&
8664                 PIC_IS_DATA_PTR(ltype)) {
8665                 genDataPointerGet (left,result,ic);
8666                 return ;
8667         }
8668         
8669         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8670         aopOp (result,ic,FALSE);
8671         
8672         /* Check if can access directly instead of via a pointer */
8673         if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8674                 && AOP_SIZE(result) == 1)
8675         {
8676                 direct = 1;
8677         }
8678
8679         if (IS_BITFIELD(getSpec(operandType(result)))) 
8680         {
8681                 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8682                 goto release;
8683         }
8684         
8685         /* If the pointer value is not in a the FSR then need to put it in */
8686         /* Must set/reset IRP bit for use with FSR. */
8687         if (!direct)
8688           setup_fsr (left);
8689         
8690 //      sym_link *etype;
8691         /* if bitfield then unpack the bits */
8692         {
8693                 /* we have can just get the values */
8694                 int size = AOP_SIZE(result);
8695                 int offset = 0 ;  
8696                 
8697                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8698                 
8699                 while(size--) {
8700                         if (direct)
8701                                 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8702                         else
8703                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8704                         if (AOP_TYPE(result) == AOP_LIT) {
8705                                 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8706                         } else {
8707                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8708                         }
8709                         if (size && !direct)
8710                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8711                         offset++;
8712                 }
8713         }
8714         
8715         /* now some housekeeping stuff */
8716         if (aop) {
8717                 /* we had to allocate for this iCode */
8718                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8719                 freeAsmop(NULL,aop,ic,TRUE);
8720         } else { 
8721                 /* we did not allocate which means left
8722                 already in a pointer register, then
8723                 if size > 0 && this could be used again
8724                 we have to point it back to where it 
8725                 belongs */
8726                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8727                 if (AOP_SIZE(result) > 1 &&
8728                         !OP_SYMBOL(left)->remat &&
8729                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8730                         ic->depth )) {
8731                         int size = AOP_SIZE(result) - 1;
8732                         while (size--)
8733                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8734                 }
8735         }
8736         
8737 release:
8738         /* done */
8739         freeAsmop(left,NULL,ic,TRUE);
8740         freeAsmop(result,NULL,ic,TRUE);
8741
8742 }
8743
8744 #if 0
8745 /*-----------------------------------------------------------------*/
8746 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8747 /*-----------------------------------------------------------------*/
8748 static void genPagedPointerGet (operand *left, 
8749                                                                 operand *result, 
8750                                                                 iCode *ic)
8751 {
8752         asmop *aop = NULL;
8753         regs *preg = NULL ;
8754         char *rname ;
8755         sym_link *rtype, *retype;    
8756         
8757         FENTRY;
8758         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8759         
8760         rtype = operandType(result);
8761         retype= getSpec(rtype);
8762         
8763         aopOp(left,ic,FALSE);
8764         
8765         /* if the value is already in a pointer register
8766         then don't need anything more */
8767         if (!AOP_INPREG(AOP(left))) {
8768                 /* otherwise get a free pointer register */
8769                 aop = newAsmop(0);
8770                 preg = getFreePtr(ic,&aop,FALSE);
8771                 pic14_emitcode("mov","%s,%s",
8772                         preg->name,
8773                         aopGet(AOP(left),0,FALSE,TRUE));
8774                 rname = preg->name ;
8775         } else
8776                 rname = aopGet(AOP(left),0,FALSE,FALSE);
8777         
8778         freeAsmop(left,NULL,ic,TRUE);
8779         aopOp (result,ic,FALSE);
8780         
8781         /* if bitfield then unpack the bits */
8782         if (IS_BITFIELD(retype)) 
8783                 genUnpackBits (result,left,rname,PPOINTER,0);
8784         else {
8785                 /* we have can just get the values */
8786                 int size = AOP_SIZE(result);
8787                 int offset = 0 ;  
8788                 
8789                 while (size--) {
8790                         
8791                         pic14_emitcode("movx","a,@%s",rname);
8792                         aopPut(AOP(result),"a",offset);
8793                         
8794                         offset++ ;
8795                         
8796                         if (size)
8797                                 pic14_emitcode("inc","%s",rname);
8798                 }
8799         }
8800         
8801         /* now some housekeeping stuff */
8802         if (aop) {
8803                 /* we had to allocate for this iCode */
8804                 freeAsmop(NULL,aop,ic,TRUE);
8805         } else { 
8806         /* we did not allocate which means left
8807         already in a pointer register, then
8808         if size > 0 && this could be used again
8809         we have to point it back to where it 
8810                 belongs */
8811                 if (AOP_SIZE(result) > 1 &&
8812                         !OP_SYMBOL(left)->remat &&
8813                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8814                         ic->depth )) {
8815                         int size = AOP_SIZE(result) - 1;
8816                         while (size--)
8817                                 pic14_emitcode("dec","%s",rname);
8818                 }
8819         }
8820         
8821         /* done */
8822         freeAsmop(result,NULL,ic,TRUE);
8823         
8824         
8825 }
8826
8827 /*-----------------------------------------------------------------*/
8828 /* genFarPointerGet - gget value from far space                    */
8829 /*-----------------------------------------------------------------*/
8830 static void genFarPointerGet (operand *left,
8831                                                           operand *result, iCode *ic)
8832 {
8833         int size, offset ;
8834         sym_link *retype = getSpec(operandType(result));
8835         
8836         FENTRY;
8837         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8838         
8839         aopOp(left,ic,FALSE);
8840         
8841         /* if the operand is already in dptr 
8842         then we do nothing else we move the value to dptr */
8843         if (AOP_TYPE(left) != AOP_STR) {
8844                 /* if this is remateriazable */
8845                 if (AOP_TYPE(left) == AOP_IMMD)
8846                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8847                 else { /* we need to get it byte by byte */
8848                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8849                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8850                         if (options.model == MODEL_FLAT24)
8851                         {
8852                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8853                         }
8854                 }
8855         }
8856         /* so dptr know contains the address */
8857         freeAsmop(left,NULL,ic,TRUE);
8858         aopOp(result,ic,FALSE);
8859         
8860         /* if bit then unpack */
8861         if (IS_BITFIELD(retype)) 
8862                 genUnpackBits(result,left,"dptr",FPOINTER,0);
8863         else {
8864                 size = AOP_SIZE(result);
8865                 offset = 0 ;
8866                 
8867                 while (size--) {
8868                         pic14_emitcode("movx","a,@dptr");
8869                         aopPut(AOP(result),"a",offset++);
8870                         if (size)
8871                                 pic14_emitcode("inc","dptr");
8872                 }
8873         }
8874         
8875         freeAsmop(result,NULL,ic,TRUE);
8876 }
8877 #endif
8878
8879 #if 0
8880 /*-----------------------------------------------------------------*/
8881 /* genCodePointerGet - get value from code space                  */
8882 /*-----------------------------------------------------------------*/
8883 static void genCodePointerGet (operand *left,
8884                                                            operand *result, iCode *ic)
8885 {
8886         int size, offset ;
8887         sym_link *retype = getSpec(operandType(result));
8888         
8889         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8890         
8891         aopOp(left,ic,FALSE);
8892         
8893         /* if the operand is already in dptr 
8894         then we do nothing else we move the value to dptr */
8895         if (AOP_TYPE(left) != AOP_STR) {
8896                 /* if this is remateriazable */
8897                 if (AOP_TYPE(left) == AOP_IMMD)
8898                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8899                 else { /* we need to get it byte by byte */
8900                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8901                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8902                         if (options.model == MODEL_FLAT24)
8903                         {
8904                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8905                         }
8906                 }
8907         }
8908         /* so dptr know contains the address */
8909         freeAsmop(left,NULL,ic,TRUE);
8910         aopOp(result,ic,FALSE);
8911         
8912         /* if bit then unpack */
8913         if (IS_BITFIELD(retype)) 
8914                 genUnpackBits(result,left,"dptr",CPOINTER,0);
8915         else {
8916                 size = AOP_SIZE(result);
8917                 offset = 0 ;
8918                 
8919                 while (size--) {
8920                         pic14_emitcode("clr","a");
8921                         pic14_emitcode("movc","a,@a+dptr");
8922                         aopPut(AOP(result),"a",offset++);
8923                         if (size)
8924                                 pic14_emitcode("inc","dptr");
8925                 }
8926         }
8927         
8928         freeAsmop(result,NULL,ic,TRUE);
8929 }
8930 #endif
8931 /*-----------------------------------------------------------------*/
8932 /* genGenPointerGet - gget value from generic pointer space        */
8933 /*-----------------------------------------------------------------*/
8934 static void genGenPointerGet (operand *left,
8935                                                           operand *result, iCode *ic)
8936 {
8937         FENTRY;
8938         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8939         aopOp(left,ic,FALSE);
8940         aopOp(result,ic,FALSE);
8941         
8942         
8943         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8944
8945         if (IS_BITFIELD(getSpec(operandType(result))))
8946         {
8947           genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
8948           return;
8949         }
8950
8951         {
8952           /* emit call to __gptrget */
8953           char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
8954           int size = AOP_SIZE(result);
8955           int idx = 0;
8956
8957           assert (size > 0 && size <= 4);
8958
8959           /* pass arguments */
8960           assert (AOP_SIZE(left) == 3);
8961           mov2w(AOP(left), 0);
8962           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8963           mov2w(AOP(left), 1);
8964           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8965           mov2w(AOP(left), 2);
8966           call_libraryfunc (func[size]);
8967           
8968           /* save result */
8969           movwf (AOP(result), --size);
8970           while (size--) {
8971             emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
8972             movwf (AOP(result), size);
8973           } // while
8974         }
8975         
8976         freeAsmop(left,NULL,ic,TRUE);
8977         freeAsmop(result,NULL,ic,TRUE);
8978         
8979 }
8980
8981 /*-----------------------------------------------------------------*/
8982 /* genConstPointerGet - get value from const generic pointer space */
8983 /*-----------------------------------------------------------------*/
8984 static void genConstPointerGet (operand *left,
8985                                                                 operand *result, iCode *ic)
8986 {
8987         //sym_link *retype = getSpec(operandType(result));
8988         #if 0
8989         symbol *albl, *blbl;//, *clbl;
8990         pCodeOp *pcop;
8991         #endif
8992         PIC_OPCODE poc;
8993         int i, size, lit;
8994         
8995         FENTRY;
8996         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8997         aopOp(left,ic,FALSE);
8998         aopOp(result,ic,FALSE);
8999         
9000         size = AOP_SIZE(result);
9001         
9002         DEBUGpic14_AopType(__LINE__,left,NULL,result);
9003         
9004         DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9005
9006         lit = op_isLitLike (left);
9007         poc = lit ? POC_MOVLW : POC_MOVFW;
9008
9009         if (IS_BITFIELD(getSpec(operandType(result))))
9010         {
9011                 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9012                 goto release;
9013         }
9014
9015         {
9016                 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9017                 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9018                 assert (size > 0 && size <= 4);
9019                 
9020                 mov2w_op(left, 0);
9021                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9022                 mov2w_op(left, 1);
9023                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9024                 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9025                 call_libraryfunc (func[size]);
9026
9027                 movwf(AOP(result),size-1);
9028                 for (i = 1; i < size; i++)
9029                 {
9030                         emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9031                         movwf(AOP(result),size - 1 - i);
9032                 } // for
9033         }
9034         
9035 release:
9036         freeAsmop(left,NULL,ic,TRUE);
9037         freeAsmop(result,NULL,ic,TRUE);
9038         
9039 }
9040 /*-----------------------------------------------------------------*/
9041 /* genPointerGet - generate code for pointer get                   */
9042 /*-----------------------------------------------------------------*/
9043 static void genPointerGet (iCode *ic)
9044 {
9045         operand *left, *result ;
9046         sym_link *type, *etype;
9047         int p_type = -1;
9048         
9049         FENTRY;
9050         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9051         
9052         left = IC_LEFT(ic);
9053         result = IC_RESULT(ic) ;
9054         
9055         /* depending on the type of pointer we need to
9056         move it to the correct pointer register */
9057         type = operandType(left);
9058         etype = getSpec(type);
9059         
9060         if (IS_PTR_CONST(type))
9061                 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9062         
9063         /* if left is of type of pointer then it is simple */
9064         if (IS_PTR(type) && !IS_FUNC(type->next)) 
9065                 p_type = DCL_TYPE(type);
9066         else {
9067                 /* we have to go by the storage class */
9068                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9069                 
9070                 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9071                 
9072                 if (SPEC_OCLS(etype)->codesp ) {
9073                         DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9074                         //p_type = CPOINTER ; 
9075                 }
9076                 else
9077                         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9078                                 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9079                         /*p_type = FPOINTER ;*/ 
9080                         else
9081                                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9082                                         DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9083                                 /*        p_type = PPOINTER; */
9084                                 else
9085                                         if (SPEC_OCLS(etype) == idata )
9086                                                 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9087                                         /*      p_type = IPOINTER; */
9088                                         else
9089                                                 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9090                                         /*      p_type = POINTER ; */
9091         }
9092         
9093         /* now that we have the pointer type we assign
9094         the pointer values */
9095         switch (p_type) {
9096                 
9097         case POINTER: 
9098         case FPOINTER:
9099         //case IPOINTER:
9100                 genNearPointerGet (left,result,ic);
9101                 break;
9102 /*
9103         case PPOINTER:
9104                 genPagedPointerGet(left,result,ic);
9105                 break;
9106                 
9107         case FPOINTER:
9108                 genFarPointerGet (left,result,ic);
9109                 break;
9110 */              
9111         case CPOINTER:
9112                 genConstPointerGet (left,result,ic);
9113                 break;
9114                 
9115         case GPOINTER:
9116                 genGenPointerGet (left,result,ic);
9117                 break;
9118         default:
9119                 assert ( !"unhandled pointer type" );
9120                 break;
9121         }
9122         
9123 }
9124
9125 /*-----------------------------------------------------------------*/
9126 /* genPackBits - generates code for packed bit storage             */
9127 /*-----------------------------------------------------------------*/
9128 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9129 {
9130   int blen;             /* bitfield length */
9131   int bstr;             /* bitfield starting bit within byte */
9132   int litval;           /* source literal value (if AOP_LIT) */
9133   unsigned char mask;   /* bitmask within current byte */
9134
9135   FENTRY;
9136   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9137
9138   blen = SPEC_BLEN (etype);
9139   bstr = SPEC_BSTR (etype);
9140
9141   /* If the bitfield length is less than a byte and does not cross byte boundaries */
9142   if ((blen <= 8) && ((bstr + blen) <= 8))
9143   {
9144     mask = ((unsigned char) (0xFF << (blen + bstr)) |
9145             (unsigned char) (0xFF >> (8 - bstr)));
9146
9147     if (AOP_TYPE (right) == AOP_LIT)
9148     {
9149       /* Case with a bitfield length <8 and literal source */
9150       int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9151       if (blen == 1) {
9152         pCodeOp *pcop;
9153         
9154         switch (p_type)
9155         {
9156         case -1:
9157           if (AOP(result)->type == AOP_PCODE)
9158             pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9159           else
9160             pcop = popGet(AOP(result),0);
9161           emitpcode(lit?POC_BSF:POC_BCF,pcop);
9162           break;
9163         
9164         case POINTER:
9165         case FPOINTER:
9166           setup_fsr (result);
9167           emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9168           break;
9169         
9170         case CPOINTER:
9171           assert( !"trying to assign to bitfield via pointer to __code space" );
9172           break;
9173         
9174         case GPOINTER:
9175           emitPtrByteGet(result, p_type, FALSE);
9176           if (lit) {
9177             emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9178           } else {
9179             emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9180           }
9181           emitPtrByteSet(result, p_type, TRUE);
9182           break;
9183         
9184         default:
9185           assert( !"unhandled pointer type" );
9186           break;
9187         } // switch (p_type)
9188       } else {
9189         /* blen > 1 */
9190         litval = lit << bstr;
9191         litval &= (~mask) & 0x00ff;
9192         
9193         switch (p_type)
9194         {
9195         case -1:
9196           mov2w (AOP(result), 0);
9197           if ((litval|mask) != 0x00ff)
9198             emitpcode(POC_ANDLW, popGetLit (mask));
9199           if (litval != 0x00)
9200             emitpcode(POC_IORLW, popGetLit (litval));
9201           movwf (AOP(result), 0);
9202           break;
9203         
9204         case POINTER:
9205         case FPOINTER:
9206         case GPOINTER:
9207           emitPtrByteGet(result, p_type, FALSE);
9208           if ((litval|mask) != 0x00ff)
9209             emitpcode(POC_ANDLW, popGetLit (mask));
9210           if (litval != 0x00)
9211             emitpcode(POC_IORLW, popGetLit (litval));
9212           emitPtrByteSet(result, p_type, TRUE);
9213           break;
9214         
9215         case CPOINTER:
9216           assert( !"trying to assign to bitfield via pointer to __code space" );
9217           break;
9218         
9219         default:
9220           assert( !"unhandled pointer type" );
9221           break;
9222         } // switch
9223       } // if (blen > 1)
9224     }
9225     else
9226     {
9227       /* right is no literal */
9228       if (blen==1) {
9229         switch (p_type)
9230         {
9231         case -1:
9232           /* Note more efficient code, of pre clearing bit then only setting it if required,
9233            * can only be done if it is known that the result is not a SFR */
9234           emitpcode(POC_RRFW,popGet(AOP(right),0));
9235           emitSKPC;
9236           emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9237           emitSKPNC;
9238           emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9239           break;
9240         
9241         case POINTER:
9242         case FPOINTER:
9243         case GPOINTER:
9244           emitPtrByteGet (result, p_type, FALSE);
9245           emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9246           emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9247           emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9248           emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9249           emitPtrByteSet (result, p_type, TRUE);
9250           break;
9251         
9252         case CPOINTER:
9253           assert( !"trying to assign to bitfield via pointer to __code space" );
9254           break;
9255         
9256         default:
9257           assert( !"unhandled pointer type" );
9258           break;
9259         } // switch
9260         return;
9261       } else {
9262         /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9263         pCodeOp *temp = popGetTempReg ();
9264
9265         mov2w (AOP(right), 0);
9266         if (blen < 8) {
9267           emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9268         }
9269         emitpcode(POC_MOVWF, temp);
9270         if (bstr) {
9271           AccLsh (temp, bstr);
9272         }
9273         
9274         switch (p_type)
9275         {
9276         case -1:
9277           mov2w (AOP(result), 0);
9278           emitpcode(POC_ANDLW, popGetLit (mask));
9279           emitpcode(POC_IORFW, temp);
9280           movwf (AOP(result), 0);
9281           break;
9282         
9283         case POINTER:
9284         case FPOINTER:
9285         case GPOINTER:
9286           emitPtrByteGet (result, p_type, FALSE);
9287           emitpcode(POC_ANDLW, popGetLit (mask));
9288           emitpcode(POC_IORFW, temp);
9289           emitPtrByteSet (result, p_type, TRUE);
9290           break;
9291         
9292         case CPOINTER:
9293           assert( !"trying to assign to bitfield via pointer to __code space" );
9294           break;
9295         
9296         default:
9297           assert( !"unhandled pointer type" );
9298           break;
9299         } // switch
9300
9301         popReleaseTempReg (temp);
9302       } // if (blen > 1)
9303     } // if (AOP(right)->type != AOP_LIT)
9304     return;
9305   } // if (blen <= 8 && ((blen + bstr) <= 8))
9306
9307   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9308 }
9309
9310 /*-----------------------------------------------------------------*/
9311 /* genDataPointerSet - remat pointer to data space                 */
9312 /*-----------------------------------------------------------------*/
9313 static void genDataPointerSet(operand *right,
9314         operand *result,
9315         iCode *ic)
9316 {
9317         int size, offset = 0 ;
9318         int ressize;
9319         
9320         FENTRY;
9321         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9322         aopOp(right,ic,FALSE);
9323         aopOp(result,ic,FALSE);
9324         
9325         assert (IS_SYMOP(result));
9326         assert (IS_PTR(OP_SYM_TYPE(result)));
9327         
9328         if (AOP_TYPE(right) == AOP_LIT)
9329           size = 4;
9330         else
9331           size = AOP_SIZE(right);
9332         ressize = getSize(OP_SYM_ETYPE(result));
9333         if (size > ressize) size = ressize;
9334         //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9335         
9336         //assert( !"what's going on here?" );
9337
9338         /*
9339         if ( AOP_TYPE(result) == AOP_PCODE) {
9340         fprintf(stderr,"genDataPointerSet   %s, %d\n",
9341         AOP(result)->aopu.pcop->name,
9342         PCOI(AOP(result)->aopu.pcop)->offset);
9343         }
9344         */
9345         
9346         // tsd, was l+1 - the underline `_' prefix was being stripped
9347         while (size--) {
9348                 emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
9349                 
9350                 if (AOP_TYPE(right) == AOP_LIT) {
9351                         unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
9352                         //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9353                         if(lit&0xff) {
9354                                 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9355                                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9356                         } else {
9357                                 emitpcode(POC_CLRF, popGet(AOP(result), offset));
9358                         }
9359                 } else {
9360                         //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9361                         emitpcode(POC_MOVFW, popGet(AOP(right), offset));
9362                         emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9363                 }
9364                 
9365                 offset++;
9366         }
9367         
9368         freeAsmop(right,NULL,ic,TRUE);
9369         freeAsmop(result,NULL,ic,TRUE);
9370 }
9371
9372 /*-----------------------------------------------------------------*/
9373 /* genNearPointerSet - pic14_emitcode for near pointer put         */
9374 /*-----------------------------------------------------------------*/
9375 static void genNearPointerSet (operand *right,
9376                                                            operand *result, 
9377                                                            iCode *ic)
9378 {
9379         asmop *aop = NULL;
9380         sym_link *ptype = operandType(result);
9381         sym_link *retype = getSpec(operandType(right));
9382         sym_link *letype = getSpec(ptype);
9383         int direct = 0;
9384         
9385         
9386         FENTRY;
9387         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9388         aopOp(result,ic,FALSE);
9389         
9390 #if 1
9391         /* if the result is rematerializable &
9392         in data space & not a bit variable */
9393         //if (AOP_TYPE(result) == AOP_IMMD &&
9394         if (AOP_TYPE(result) == AOP_PCODE &&
9395                 PIC_IS_DATA_PTR(ptype) &&
9396                 !IS_BITVAR (retype) &&
9397                 !IS_BITVAR (letype)) {
9398                 genDataPointerSet (right,result,ic);
9399                 freeAsmop(result,NULL,ic,TRUE);
9400                 return;
9401         }
9402 #endif
9403
9404         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9405         aopOp(right,ic,FALSE);
9406         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9407         
9408         /* Check if can access directly instead of via a pointer */
9409         if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9410                 direct = 1;
9411         }
9412         
9413         if (IS_BITFIELD (letype))
9414         {
9415           genPackBits (letype, result, right, direct?-1:POINTER);
9416           return;
9417         }
9418         
9419         /* If the pointer value is not in a the FSR then need to put it in */
9420         /* Must set/reset IRP bit for use with FSR. */
9421         /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9422         if (!direct)
9423                 setup_fsr (result);
9424
9425         {
9426                 /* we have can just get the values */
9427                 int size = AOP_SIZE(right);
9428                 int offset = 0 ;    
9429                 
9430                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9431                 while (size--) {
9432                         char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9433                         if (*l == '@' ) {
9434                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9435                         } else {
9436                                 if (AOP_TYPE(right) == AOP_LIT) {
9437                                         emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9438                                 } else {
9439                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9440                                 }
9441                                 if (direct)
9442                                         emitpcode(POC_MOVWF,popGet(AOP(result),0));
9443                                 else
9444                                         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9445                         }
9446                         if (size && !direct)
9447                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9448                         offset++;
9449                 }
9450         }
9451         
9452         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9453         /* now some housekeeping stuff */
9454         if (aop) {
9455                 /* we had to allocate for this iCode */
9456                 freeAsmop(NULL,aop,ic,TRUE);
9457         } else { 
9458                 /* we did not allocate which means left
9459                 already in a pointer register, then
9460                 if size > 0 && this could be used again
9461                 we have to point it back to where it 
9462                 belongs */
9463                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9464                 if (AOP_SIZE(right) > 1 &&
9465                         !OP_SYMBOL(result)->remat &&
9466                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9467                         ic->depth )) {
9468                         int size = AOP_SIZE(right) - 1;
9469                         while (size--)
9470                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9471                 }
9472         }
9473         
9474         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9475         /* done */
9476
9477         freeAsmop(right,NULL,ic,TRUE);
9478         freeAsmop(result,NULL,ic,TRUE);
9479 }
9480
9481 #if 0
9482 /*-----------------------------------------------------------------*/
9483 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
9484 /*-----------------------------------------------------------------*/
9485 static void genPagedPointerSet (operand *right,
9486                                                                 operand *result, 
9487                                                                 iCode *ic)
9488 {
9489         asmop *aop = NULL;
9490         regs *preg = NULL ;
9491         char *rname , *l;
9492         sym_link *retype;
9493         
9494         FENTRY;
9495         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9496         
9497         retype= getSpec(operandType(right));
9498         
9499         aopOp(result,ic,FALSE);
9500         
9501         /* if the value is already in a pointer register
9502         then don't need anything more */
9503         if (!AOP_INPREG(AOP(result))) {
9504                 /* otherwise get a free pointer register */
9505                 aop = newAsmop(0);
9506                 preg = getFreePtr(ic,&aop,FALSE);
9507                 pic14_emitcode("mov","%s,%s",
9508                         preg->name,
9509                         aopGet(AOP(result),0,FALSE,TRUE));
9510                 rname = preg->name ;
9511         } else
9512                 rname = aopGet(AOP(result),0,FALSE,FALSE);
9513         
9514         freeAsmop(result,NULL,ic,TRUE);
9515         aopOp (right,ic,FALSE);
9516         
9517         /* if bitfield then unpack the bits */
9518         if (IS_BITFIELD(retype)) 
9519                 genPackBits (retype,result,right,rname,PPOINTER);
9520         else {
9521                 /* we have can just get the values */
9522                 int size = AOP_SIZE(right);
9523                 int offset = 0 ;  
9524                 
9525                 while (size--) {
9526                         l = aopGet(AOP(right),offset,FALSE,TRUE);
9527                         
9528                         MOVA(l);
9529                         pic14_emitcode("movx","@%s,a",rname);
9530                         
9531                         if (size)
9532                                 pic14_emitcode("inc","%s",rname);
9533                         
9534                         offset++;
9535                 }
9536         }
9537         
9538         /* now some housekeeping stuff */
9539         if (aop) {
9540                 /* we had to allocate for this iCode */
9541                 freeAsmop(NULL,aop,ic,TRUE);
9542         } else { 
9543         /* we did not allocate which means left
9544         already in a pointer register, then
9545         if size > 0 && this could be used again
9546         we have to point it back to where it 
9547                 belongs */
9548                 if (AOP_SIZE(right) > 1 &&
9549                         !OP_SYMBOL(result)->remat &&
9550                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9551                         ic->depth )) {
9552                         int size = AOP_SIZE(right) - 1;
9553                         while (size--)
9554                                 pic14_emitcode("dec","%s",rname);
9555                 }
9556         }
9557         
9558         /* done */
9559         freeAsmop(right,NULL,ic,TRUE);
9560         
9561         
9562 }
9563
9564 /*-----------------------------------------------------------------*/
9565 /* genFarPointerSet - set value from far space                     */
9566 /*-----------------------------------------------------------------*/
9567 static void genFarPointerSet (operand *right,
9568                                                           operand *result, iCode *ic)
9569 {
9570         int size, offset ;
9571         sym_link *retype = getSpec(operandType(right));
9572         
9573         FENTRY;
9574         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9575         aopOp(result,ic,FALSE);
9576         
9577         /* if the operand is already in dptr 
9578         then we do nothing else we move the value to dptr */
9579         if (AOP_TYPE(result) != AOP_STR) {
9580                 /* if this is remateriazable */
9581                 if (AOP_TYPE(result) == AOP_IMMD)
9582                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9583                 else { /* we need to get it byte by byte */
9584                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9585                         pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9586                         if (options.model == MODEL_FLAT24)
9587                         {
9588                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9589                         }
9590                 }
9591         }
9592         /* so dptr know contains the address */
9593         freeAsmop(result,NULL,ic,TRUE);
9594         aopOp(right,ic,FALSE);
9595         
9596         /* if bit then unpack */
9597         if (IS_BITFIELD(retype)) 
9598                 genPackBits(retype,result,right,"dptr",FPOINTER);
9599         else {
9600                 size = AOP_SIZE(right);
9601                 offset = 0 ;
9602                 
9603                 while (size--) {
9604                         char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9605                         MOVA(l);
9606                         pic14_emitcode("movx","@dptr,a");
9607                         if (size)
9608                                 pic14_emitcode("inc","dptr");
9609                 }
9610         }
9611         
9612         freeAsmop(right,NULL,ic,TRUE);
9613 }
9614 #endif
9615
9616 /*-----------------------------------------------------------------*/
9617 /* genGenPointerSet - set value from generic pointer space         */
9618 /*-----------------------------------------------------------------*/
9619 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9620 {
9621         sym_link *retype = getSpec(operandType(result));
9622         
9623         FENTRY;
9624         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9625         aopOp(right,ic,FALSE);
9626         aopOp(result,ic,FALSE);
9627
9628         
9629         DEBUGpic14_AopType(__LINE__,right,NULL,result);
9630
9631         if (IS_BITFIELD(retype))
9632         {
9633           genPackBits (retype, result, right, GPOINTER);
9634           return;
9635         }
9636
9637         {
9638           /* emit call to __gptrput */
9639           char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9640           int size = AOP_SIZE(right);
9641           int idx = 0;
9642
9643           /* The following assertion fails for
9644            *   struct foo { char a; char b; } bar;
9645            *   void demo(struct foo *dst, char c) { dst->b = c; }
9646            * as size will be 1 (sizeof(c)), whereas dst->b will be accessed
9647            * using (((char *)dst)+1), whose OP_SYM_ETYPE still is struct foo
9648            * of size 2.
9649            * The frontend seems to guarantee that IC_LEFT has the correct size,
9650            * it works fine both for larger and smaller types of `char c'.
9651            * */
9652           //assert (size == getSize(OP_SYM_ETYPE(result)));
9653           assert (size > 0 && size <= 4);
9654
9655           /* pass arguments */
9656           /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9657           {
9658             int off = size;
9659             idx = 2;
9660             while (off--)
9661             {
9662               mov2w_op (right, off);
9663               emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9664             }
9665             idx = 0;
9666           }
9667           /* - address */
9668           assert (AOP_SIZE(result) == 3);
9669           mov2w(AOP(result), 0);
9670           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9671           mov2w(AOP(result), 1);
9672           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9673           mov2w(AOP(result), 2);
9674           call_libraryfunc (func[size]);
9675         }
9676         
9677         freeAsmop(right,NULL,ic,TRUE);
9678         freeAsmop(result,NULL,ic,TRUE);
9679 }
9680
9681 /*-----------------------------------------------------------------*/
9682 /* genPointerSet - stores the value into a pointer location        */
9683 /*-----------------------------------------------------------------*/
9684 static void genPointerSet (iCode *ic)
9685 {    
9686         operand *right, *result ;
9687         sym_link *type, *etype;
9688         int p_type;
9689         
9690         FENTRY;
9691         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9692         
9693         right = IC_RIGHT(ic);
9694         result = IC_RESULT(ic) ;
9695         
9696         /* depending on the type of pointer we need to
9697         move it to the correct pointer register */
9698         type = operandType(result);
9699         etype = getSpec(type);
9700         /* if left is of type of pointer then it is simple */
9701         if (IS_PTR(type) && !IS_FUNC(type->next)) {
9702                 p_type = DCL_TYPE(type);
9703         }
9704         else {
9705                 /* we have to go by the storage class */
9706                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9707                 
9708                 /*  if (SPEC_OCLS(etype)->codesp ) { */
9709                 /*      p_type = CPOINTER ;  */
9710                 /*  } */
9711                 /*  else */
9712                 /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9713                 /*    p_type = FPOINTER ; */
9714                 /*      else */
9715                 /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9716                 /*        p_type = PPOINTER ; */
9717                 /*    else */
9718                 /*        if (SPEC_OCLS(etype) == idata ) */
9719                 /*      p_type = IPOINTER ; */
9720                 /*        else */
9721                 /*      p_type = POINTER ; */
9722         }
9723         
9724         /* now that we have the pointer type we assign
9725         the pointer values */
9726         switch (p_type) {
9727                 
9728         case POINTER:
9729         case FPOINTER:
9730         //case IPOINTER:
9731                 genNearPointerSet (right,result,ic);
9732                 break;
9733 /*
9734         case PPOINTER:
9735                 genPagedPointerSet (right,result,ic);
9736                 break;
9737                 
9738         case FPOINTER:
9739                 genFarPointerSet (right,result,ic);
9740                 break;
9741 */
9742         case GPOINTER:
9743                 genGenPointerSet (right,result,ic);
9744                 break;
9745                 
9746         default:
9747                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9748                         "genPointerSet: illegal pointer type");
9749         }
9750 }
9751
9752 /*-----------------------------------------------------------------*/
9753 /* genIfx - generate code for Ifx statement                        */
9754 /*-----------------------------------------------------------------*/
9755 static void genIfx (iCode *ic, iCode *popIc)
9756 {
9757         operand *cond = IC_COND(ic);
9758         int isbit =0;
9759         
9760         FENTRY;
9761         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9762         
9763         aopOp(cond,ic,FALSE);
9764         
9765         /* get the value into acc */
9766         if (AOP_TYPE(cond) != AOP_CRY)
9767                 pic14_toBoolean(cond);
9768         else
9769                 isbit = 1;
9770         
9771         /* if there was something to be popped then do it */
9772         if (popIc)
9773                 genIpop(popIc);
9774         
9775         if (isbit)
9776         {
9777                 /* This assumes that CARRY is set iff cond is true */
9778                 if (IC_TRUE(ic))
9779                 {
9780                         assert (!IC_FALSE(ic));
9781                         emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9782                         //emitSKPNC;
9783                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9784                 } else {
9785                         assert (IC_FALSE(ic));
9786                         emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9787                         //emitSKPC;
9788                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9789                 }
9790                 if (0)
9791                 {
9792                         static int hasWarned = 0;
9793                         if (!hasWarned)
9794                         {
9795                                 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9796                                 hasWarned = 1;
9797                         }
9798                 }
9799         }
9800         else
9801         {
9802                 /* now Z is set iff !cond */
9803                 if (IC_TRUE(ic))
9804                 {
9805                         assert (!IC_FALSE(ic));
9806                         emitSKPZ;
9807                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9808                 } else {
9809                         emitSKPNZ;
9810                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9811                 }
9812         }
9813         
9814         ic->generated = 1;
9815         
9816         /* the result is now in the accumulator */
9817         freeAsmop(cond,NULL,ic,TRUE);
9818 }
9819
9820 /*-----------------------------------------------------------------*/
9821 /* genAddrOf - generates code for address of                       */
9822 /*-----------------------------------------------------------------*/
9823 static void genAddrOf (iCode *ic)
9824 {
9825         operand *right, *result, *left;
9826         int size, offset ;
9827         
9828         FENTRY;
9829         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9830         
9831         
9832         //aopOp(IC_RESULT(ic),ic,FALSE);
9833         
9834         aopOp((left=IC_LEFT(ic)),ic,FALSE);
9835         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9836         aopOp((result=IC_RESULT(ic)),ic,TRUE);
9837         
9838         DEBUGpic14_AopType(__LINE__,left,right,result);
9839         assert (IS_SYMOP (left));
9840         
9841         /* sanity check: generic pointers to code space are not yet supported,
9842          * pionters to codespace must not be assigned addresses of __data values. */
9843  #if 0
9844         fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9845         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)));
9846         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)));
9847         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)));
9848         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)));
9849 #endif
9850
9851         if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9852           fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9853                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9854                 OP_SYMBOL(left)->name);
9855         } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9856           fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9857                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9858                 OP_SYMBOL(left)->name);
9859         }
9860         
9861         size = AOP_SIZE(IC_RESULT(ic));
9862         if (IS_GENPTR(OP_SYM_TYPE(result))) {
9863                 /* strip tag */
9864                 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9865         }
9866         offset = 0;
9867         
9868         while (size--) {
9869                 /* fixing bug #863624, reported from (errolv) */
9870                 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9871                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9872                 
9873 #if 0
9874                 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9875                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9876 #endif
9877                 offset++;
9878         }
9879
9880         if (IS_GENPTR(OP_SYM_TYPE(result)))
9881         {
9882                 /* provide correct tag */
9883                 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9884                 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9885                 movwf (AOP(result), 2);
9886         }
9887         
9888         freeAsmop(left,NULL,ic,FALSE);
9889         freeAsmop(result,NULL,ic,TRUE);
9890         
9891 }
9892
9893 #if 0
9894 /*-----------------------------------------------------------------*/
9895 /* genFarFarAssign - assignment when both are in far space         */
9896 /*-----------------------------------------------------------------*/
9897 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9898 {
9899         int size = AOP_SIZE(right);
9900         int offset = 0;
9901         char *l ;
9902         /* first push the right side on to the stack */
9903         while (size--) {
9904                 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9905                 MOVA(l);
9906                 pic14_emitcode ("push","acc");
9907         }
9908         
9909         freeAsmop(right,NULL,ic,FALSE);
9910         /* now assign DPTR to result */
9911         aopOp(result,ic,FALSE);
9912         size = AOP_SIZE(result);
9913         while (size--) {
9914                 pic14_emitcode ("pop","acc");
9915                 aopPut(AOP(result),"a",--offset);
9916         }
9917         freeAsmop(result,NULL,ic,FALSE);
9918         
9919 }
9920 #endif
9921
9922 /*-----------------------------------------------------------------*/
9923 /* genAssign - generate code for assignment                        */
9924 /*-----------------------------------------------------------------*/
9925 static void genAssign (iCode *ic)
9926 {
9927         operand *result, *right;
9928         int size, offset,know_W;
9929         unsigned long lit = 0L;
9930         
9931         result = IC_RESULT(ic);
9932         right  = IC_RIGHT(ic) ;
9933         
9934         FENTRY;
9935         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9936         
9937         /* if they are the same */
9938         if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9939                 return ;
9940         
9941         aopOp(right,ic,FALSE);
9942         aopOp(result,ic,TRUE);
9943         
9944         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9945         
9946         /* if they are the same registers */
9947         if (pic14_sameRegs(AOP(right),AOP(result)))
9948                 goto release;
9949
9950         /* special case: assign from __code */
9951         if (!IS_ITEMP(right)                            /* --> iTemps never reside in __code */
9952                 && IS_SYMOP (right)                     /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
9953                 && !IS_FUNC(OP_SYM_TYPE(right))         /* --> we would want its address instead of the first instruction */
9954                 && !IS_CODEPTR(OP_SYM_TYPE(right))      /* --> get symbols address instread */
9955                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
9956         {
9957           emitpComment ("genAssign from CODESPACE");
9958           genConstPointerGet (right, result, ic);
9959           goto release;
9960         }
9961         
9962         /* just for symmetry reasons... */
9963         if (!IS_ITEMP(result)
9964                 && IS_SYMOP (result)
9965                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
9966         {
9967           assert ( !"cannot write to CODESPACE" );
9968         }
9969
9970         /* if the result is a bit */
9971         if (AOP_TYPE(result) == AOP_CRY) {
9972                 
9973         /* if the right size is a literal then
9974                 we know what the value is */
9975                 if (AOP_TYPE(right) == AOP_LIT) {
9976                         
9977                         emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9978                                 popGet(AOP(result),0));
9979                         
9980                         if (((int) operandLitValue(right))) 
9981                                 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9982                                 AOP(result)->aopu.aop_dir,
9983                                 AOP(result)->aopu.aop_dir);
9984                         else
9985                                 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9986                                 AOP(result)->aopu.aop_dir,
9987                                 AOP(result)->aopu.aop_dir);
9988                         goto release;
9989                 }
9990                 
9991                 /* the right is also a bit variable */
9992                 if (AOP_TYPE(right) == AOP_CRY) {
9993                         emitpcode(POC_BCF,    popGet(AOP(result),0));
9994                         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9995                         emitpcode(POC_BSF,    popGet(AOP(result),0));
9996                         
9997                         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9998                                 AOP(result)->aopu.aop_dir,
9999                                 AOP(result)->aopu.aop_dir);
10000                         pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10001                                 AOP(right)->aopu.aop_dir,
10002                                 AOP(right)->aopu.aop_dir);
10003                         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10004                                 AOP(result)->aopu.aop_dir,
10005                                 AOP(result)->aopu.aop_dir);
10006                         goto release ;
10007                 }
10008                 
10009                 /* we need to or */
10010                 emitpcode(POC_BCF,    popGet(AOP(result),0));
10011                 pic14_toBoolean(right);
10012                 emitSKPZ;
10013                 emitpcode(POC_BSF,    popGet(AOP(result),0));
10014                 //aopPut(AOP(result),"a",0);
10015                 goto release ;
10016         }
10017         
10018         /* bit variables done */
10019         /* general case */
10020         size = AOP_SIZE(result);
10021         offset = 0 ;
10022         if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10023                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10024                 if(aopIdx(AOP(result),0) == 4) {
10025                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10026                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10027                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10028                         goto release;
10029                 } else
10030                         DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10031         }
10032         
10033         know_W=-1;
10034         while (size--) {
10035         
10036                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10037                 if(AOP_TYPE(right) == AOP_LIT) {
10038                         lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
10039                         if(lit&0xff) {
10040                                 if(know_W != (int)(lit&0xff))
10041                                         emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10042                                 know_W = lit&0xff;
10043                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10044                         } else
10045                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10046                         
10047                 } else if (AOP_TYPE(right) == AOP_CRY) {
10048                         emitpcode(POC_CLRF, popGet(AOP(result),offset));
10049                         if(offset == 0) {
10050                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10051                                 emitpcode(POC_INCF, popGet(AOP(result),0));
10052                         }
10053                 } else {
10054                         mov2w_op (right, offset);
10055                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10056                 }
10057                 
10058                 offset++;
10059         }
10060         
10061         
10062 release:
10063         freeAsmop (right,NULL,ic,FALSE);
10064         freeAsmop (result,NULL,ic,TRUE);
10065 }   
10066
10067 /*-----------------------------------------------------------------*/
10068 /* genJumpTab - genrates code for jump table                       */
10069 /*-----------------------------------------------------------------*/
10070 static void genJumpTab (iCode *ic)
10071 {
10072         symbol *jtab;
10073         char *l;
10074         
10075         FENTRY;
10076         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10077         
10078         aopOp(IC_JTCOND(ic),ic,FALSE);
10079         /* get the condition into accumulator */
10080         l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10081         MOVA(l);
10082         /* multiply by three */
10083         pic14_emitcode("add","a,acc");
10084         pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10085         
10086         jtab = newiTempLabel(NULL);
10087         pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10088         pic14_emitcode("jmp","@a+dptr");
10089         pic14_emitcode("","%05d_DS_:",jtab->key+100);
10090         
10091         emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10092         emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10093         emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10094         emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10095         emitSKPNC;
10096         emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10097         emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10098         emitpLabel(jtab->key);
10099         
10100         freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10101         
10102         /* now generate the jump labels */
10103         for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10104         jtab = setNextItem(IC_JTLABELS(ic))) {
10105                 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10106                 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10107                 
10108         }
10109         
10110 }
10111
10112 /*-----------------------------------------------------------------*/
10113 /* genMixedOperation - gen code for operators between mixed types  */
10114 /*-----------------------------------------------------------------*/
10115 /*
10116 TSD - Written for the PIC port - but this unfortunately is buggy.
10117 This routine is good in that it is able to efficiently promote 
10118 types to different (larger) sizes. Unfortunately, the temporary
10119 variables that are optimized out by this routine are sometimes
10120 used in other places. So until I know how to really parse the 
10121 iCode tree, I'm going to not be using this routine :(.
10122 */
10123 static int genMixedOperation (iCode *ic)
10124 {
10125         FENTRY;
10126 #if 0
10127         operand *result = IC_RESULT(ic);
10128         sym_link *ctype = operandType(IC_LEFT(ic));
10129         operand *right = IC_RIGHT(ic);
10130         int ret = 0;
10131         int big,small;
10132         int offset;
10133         
10134         iCode *nextic;
10135         operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10136         
10137         pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10138         
10139         nextic = ic->next;
10140         if(!nextic)
10141                 return 0;
10142         
10143         nextright = IC_RIGHT(nextic);
10144         nextleft  = IC_LEFT(nextic);
10145         nextresult = IC_RESULT(nextic);
10146         
10147         aopOp(right,ic,FALSE);
10148         aopOp(result,ic,FALSE);
10149         aopOp(nextright,  nextic, FALSE);
10150         aopOp(nextleft,   nextic, FALSE);
10151         aopOp(nextresult, nextic, FALSE);
10152         
10153         if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10154                 
10155                 operand *t = right;
10156                 right = nextright;
10157                 nextright = t; 
10158                 
10159                 pic14_emitcode(";remove right +","");
10160                 
10161         } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10162         /*
10163         operand *t = right;
10164         right = nextleft;
10165         nextleft = t; 
10166                 */
10167                 pic14_emitcode(";remove left +","");
10168         } else
10169                 return 0;
10170         
10171         big = AOP_SIZE(nextleft);
10172         small = AOP_SIZE(nextright);
10173         
10174         switch(nextic->op) {
10175                 
10176         case '+':
10177                 pic14_emitcode(";optimize a +","");
10178                 /* if unsigned or not an integral type */
10179                 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10180                         pic14_emitcode(";add a bit to something","");
10181                 } else {
10182                         
10183                         pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10184                         
10185                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10186                                 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10187                                 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10188                         } else
10189                                 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10190                         
10191                         offset = 0;
10192                         while(--big) {
10193                                 
10194                                 offset++;
10195                                 
10196                                 if(--small) {
10197                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10198                                                 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10199                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10200                                         }
10201                                         
10202                                         pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10203                                         emitSKPNC;
10204                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10205                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10206                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10207                                         pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10208                                         pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10209                                         
10210                                 } else {
10211                                         pic14_emitcode("rlf","known_zero,w");
10212                                         
10213                                         /*
10214                                         if right is signed
10215                                         btfsc  right,7
10216                                         addlw ff
10217                                         */
10218                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10219                                                 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10220                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10221                                         } else {
10222                                                 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10223                                         }
10224                                 }
10225                         }
10226                         ret = 1;
10227                 }
10228         }
10229         ret = 1;
10230         
10231 release:
10232         freeAsmop(right,NULL,ic,TRUE);
10233         freeAsmop(result,NULL,ic,TRUE);
10234         freeAsmop(nextright,NULL,ic,TRUE);
10235         freeAsmop(nextleft,NULL,ic,TRUE);
10236         if(ret)
10237                 nextic->generated = 1;
10238         
10239         return ret;
10240 #else
10241         return 0;
10242 #endif
10243 }
10244 /*-----------------------------------------------------------------*/
10245 /* genCast - gen code for casting                                  */
10246 /*-----------------------------------------------------------------*/
10247 static void genCast (iCode *ic)
10248 {
10249         operand *result = IC_RESULT(ic);
10250         sym_link *restype = operandType(result);
10251         sym_link *rtype = operandType(IC_RIGHT(ic));
10252         operand *right = IC_RIGHT(ic);
10253         int size, offset ;
10254         
10255         FENTRY;
10256         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10257         /* if they are equivalent then do nothing */
10258         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10259                 return ;
10260         
10261         aopOp(right,ic,FALSE) ;
10262         aopOp(result,ic,FALSE);
10263         
10264         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10265         
10266         /* if the result is a bit */
10267         if (AOP_TYPE(result) == AOP_CRY) {
10268                 assert(!"assigning to bit variables is not supported");
10269         }
10270         
10271         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10272                 int offset = 1;
10273                 size = AOP_SIZE(result);
10274                 
10275                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10276                 
10277                 emitpcode(POC_CLRF,   popGet(AOP(result),0));
10278                 emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10279                 emitpcode(POC_INCF,   popGet(AOP(result),0));
10280                 
10281                 while (size--)
10282                         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
10283                 
10284                 goto release;
10285         }
10286         
10287         if (IS_PTR(restype))
10288         {
10289           operand *result = IC_RESULT(ic);
10290           //operand *left = IC_LEFT(ic);
10291           operand *right = IC_RIGHT(ic);
10292           int tag = 0xff;
10293           
10294           /* copy common part */
10295           int max, size = AOP_SIZE(result);
10296           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10297           DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10298
10299           /* warn if we discard generic opinter tag */
10300           if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10301           {
10302             //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10303           } // if
10304
10305           max = size;
10306           while (size--)
10307           {
10308             mov2w_op (right, size);
10309             movwf (AOP(result), size);
10310           } // while
10311
10312           /* upcast into generic pointer type? */
10313           if (IS_GENPTR(restype)
10314                 && (size < AOP_SIZE(result))
10315                 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10316           {
10317             //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10318             if (IS_PTR(rtype))
10319             {
10320               switch (DCL_TYPE(rtype))
10321               {
10322               case POINTER:     /* __data */
10323               case FPOINTER:    /* __data */
10324                 assert (AOP_SIZE(right) == 2);
10325                 tag = GPTRTAG_DATA;
10326                 break;
10327
10328               case CPOINTER:    /* __code */
10329                 assert (AOP_SIZE(right) == 2);
10330                 tag = GPTRTAG_CODE;
10331                 break;
10332                 
10333               case GPOINTER:    /* unknown destination, __data or __code */
10334                 /* assume __data space (address of immediate) */
10335                 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10336                 if (AOP(right)->code)
10337                   tag = GPTRTAG_CODE;
10338                 else
10339                   tag = GPTRTAG_DATA;
10340                 break;
10341                 
10342               default:
10343                 assert (!"unhandled pointer type");
10344               } // switch
10345             } else {
10346               /* convert other values into pointers to __data space */
10347               tag = GPTRTAG_DATA;
10348             }
10349
10350             assert (AOP_SIZE(result) == 3);
10351             if (tag == 0) {
10352               emitpcode(POC_CLRF, popGet(AOP(result), 2));
10353             } else {
10354               emitpcode(POC_MOVLW, popGetLit(tag));
10355               movwf(AOP(result), 2);
10356             }
10357           } else {
10358             addSign(result, max, 0);
10359           } // if
10360           goto release;
10361         }
10362         
10363         /* if they are the same size : or less */
10364         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10365                 
10366                 /* if they are in the same place */
10367                 if (pic14_sameRegs(AOP(right),AOP(result)))
10368                         goto release;
10369                 
10370                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10371                 if (IS_PTR_CONST(rtype))
10372                         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10373                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10374                         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10375                 
10376                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10377                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10378                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
10379                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10380                         emitpcode(POC_MOVWF, popGet(AOP(result),1));
10381                         if(AOP_SIZE(result) <2)
10382                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10383                         
10384                 } else {
10385                         
10386                         /* if they in different places then copy */
10387                         size = AOP_SIZE(result);
10388                         offset = 0 ;
10389                         while (size--) {
10390                                 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10391                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10392                                 
10393                                 //aopPut(AOP(result),
10394                                 // aopGet(AOP(right),offset,FALSE,FALSE),
10395                                 // offset);
10396                                 
10397                                 offset++;
10398                         }
10399                 }
10400                 goto release;
10401         }
10402         
10403         /* so we now know that the size of destination is greater
10404         than the size of the source.
10405         Now, if the next iCode is an operator then we might be
10406         able to optimize the operation without performing a cast.
10407         */
10408         if(0 && genMixedOperation(ic)) {
10409                 /* XXX: cannot optimize: must copy regs! */
10410                 goto release;
10411         }
10412         
10413         /* we move to result for the size of source */
10414         size = AOP_SIZE(right);
10415         offset = 0 ;
10416         while (size--) {
10417                 emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
10418                 emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
10419                 offset++;
10420         }
10421
10422         addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10423
10424 release:
10425         freeAsmop(right,NULL,ic,TRUE);
10426         freeAsmop(result,NULL,ic,TRUE);
10427         
10428 }
10429
10430 /*-----------------------------------------------------------------*/
10431 /* genDjnz - generate decrement & jump if not zero instrucion      */
10432 /*-----------------------------------------------------------------*/
10433 static int genDjnz (iCode *ic, iCode *ifx)
10434 {
10435         symbol *lbl, *lbl1;
10436         FENTRY;
10437         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10438         
10439         if (!ifx)
10440                 return 0;
10441         
10442                 /* if the if condition has a false label
10443         then we cannot save */
10444         if (IC_FALSE(ifx))
10445                 return 0;
10446         
10447                 /* if the minus is not of the form 
10448         a = a - 1 */
10449         if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10450                 !IS_OP_LITERAL(IC_RIGHT(ic)))
10451                 return 0;
10452         
10453         if (operandLitValue(IC_RIGHT(ic)) != 1)
10454                 return 0;
10455         
10456                 /* if the size of this greater than one then no
10457         saving */
10458         if (getSize(operandType(IC_RESULT(ic))) > 1)
10459                 return 0;
10460         
10461         /* otherwise we can save BIG */
10462         lbl = newiTempLabel(NULL);
10463         lbl1= newiTempLabel(NULL);
10464         
10465         aopOp(IC_RESULT(ic),ic,FALSE);
10466         
10467         if (IS_AOP_PREG(IC_RESULT(ic))) {
10468                 pic14_emitcode("dec","%s",
10469                         aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10470                 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10471                 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10472         } else {  
10473                 
10474                 
10475                 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10476                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10477                 
10478                 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10479                 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10480                 
10481         }
10482         /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10483         /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10484         /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10485         /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10486         
10487         
10488         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10489         ifx->generated = 1;
10490         return 1;
10491 }
10492
10493 /*-----------------------------------------------------------------*/
10494 /* genReceive - generate code for a receive iCode                  */
10495 /*-----------------------------------------------------------------*/
10496 static void genReceive (iCode *ic)
10497 {
10498         FENTRY;
10499         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10500         
10501         if (isOperandInFarSpace(IC_RESULT(ic)) &&
10502                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10503                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10504                 
10505                 int size = getSize(operandType(IC_RESULT(ic)));
10506                 int offset =  fReturnSizePic - size;
10507                 while (size--) {
10508                         pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10509                                 fReturn[fReturnSizePic - offset - 1] : "acc"));
10510                         offset++;
10511                 }
10512                 aopOp(IC_RESULT(ic),ic,FALSE);
10513                 size = AOP_SIZE(IC_RESULT(ic));
10514                 offset = 0;
10515                 while (size--) {
10516                         pic14_emitcode ("pop","acc");
10517                         aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10518                 }
10519                 
10520         } else {
10521                 _G.accInUse++;
10522                 aopOp(IC_RESULT(ic),ic,FALSE);
10523                 _G.accInUse--;
10524                 GpsuedoStkPtr = ic->parmBytes; // address used arg on stack
10525                 assignResultValue(IC_RESULT(ic));
10526         }
10527         
10528         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10529 }
10530
10531 /*-----------------------------------------------------------------*/
10532 /* genDummyRead - generate code for dummy read of volatiles        */
10533 /*-----------------------------------------------------------------*/
10534 static void
10535 genDummyRead (iCode * ic)
10536 {
10537         FENTRY;
10538         pic14_emitcode ("; genDummyRead","");
10539         pic14_emitcode ("; not implemented","");
10540         
10541         ic = ic;
10542 }
10543
10544 /*-----------------------------------------------------------------*/
10545 /* genpic14Code - generate code for pic14 based controllers        */
10546 /*-----------------------------------------------------------------*/
10547 /*
10548 * At this point, ralloc.c has gone through the iCode and attempted
10549 * to optimize in a way suitable for a PIC. Now we've got to generate
10550 * PIC instructions that correspond to the iCode.
10551 *
10552 * Once the instructions are generated, we'll pass through both the
10553 * peep hole optimizer and the pCode optimizer.
10554 *-----------------------------------------------------------------*/
10555
10556 void genpic14Code (iCode *lic)
10557 {
10558         iCode *ic;
10559         int cln = 0;
10560         const char *cline;
10561         
10562         FENTRY;
10563         lineHead = lineCurr = NULL;
10564         
10565         pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10566         addpBlock(pb);
10567         
10568         /* if debug information required */
10569         if (options.debug && debugFile && currFunc) { 
10570                 debugFile->writeFunction (currFunc, lic);
10571         }
10572         
10573         
10574         for (ic = lic ; ic ; ic = ic->next ) {
10575                 
10576                 //DEBUGpic14_emitcode(";ic","");
10577                 //fprintf (stderr, "in ic loop\n");
10578                 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10579                 //ic->lineno, printCLine(ic->filename, ic->lineno));
10580                 
10581                 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10582                   cln = ic->lineno;
10583                   //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10584                   cline = printCLine (ic->filename, ic->lineno);
10585                   if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10586                   addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10587                   //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10588                 }
10589                 
10590                 if (options.iCodeInAsm) {
10591                   char *iLine = printILine(ic);
10592                   emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10593                   dbuf_free(iLine);
10594                 }
10595                 /* if the result is marked as
10596                 spilt and rematerializable or code for
10597                 this has already been generated then
10598                 do nothing */
10599                 if (resultRemat(ic) || ic->generated ) 
10600                         continue ;
10601                 
10602                 /* depending on the operation */
10603                 switch (ic->op) {
10604                 case '!' :
10605                         genNot(ic);
10606                         break;
10607                         
10608                 case '~' :
10609                         genCpl(ic);
10610                         break;
10611                         
10612                 case UNARYMINUS:
10613                         genUminus (ic);
10614                         break;
10615                         
10616                 case IPUSH:
10617                         genIpush (ic);
10618                         break;
10619                         
10620                 case IPOP:
10621                         /* IPOP happens only when trying to restore a 
10622                         spilt live range, if there is an ifx statement
10623                         following this pop then the if statement might
10624                         be using some of the registers being popped which
10625                         would destory the contents of the register so
10626                         we need to check for this condition and handle it */
10627                         if (ic->next            && 
10628                                 ic->next->op == IFX &&
10629                                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10630                                 genIfx (ic->next,ic);
10631                         else
10632                                 genIpop (ic);
10633                         break; 
10634                         
10635                 case CALL:
10636                         genCall (ic);
10637                         break;
10638                         
10639                 case PCALL:
10640                         genPcall (ic);
10641                         break;
10642                         
10643                 case FUNCTION:
10644                         genFunction (ic);
10645                         break;
10646                         
10647                 case ENDFUNCTION:
10648                         genEndFunction (ic);
10649                         break;
10650                         
10651                 case RETURN:
10652                         genRet (ic);
10653                         break;
10654                         
10655                 case LABEL:
10656                         genLabel (ic);
10657                         break;
10658                         
10659                 case GOTO:
10660                         genGoto (ic);
10661                         break;
10662                         
10663                 case '+' :
10664                         genPlus (ic) ;
10665                         break;
10666                         
10667                 case '-' :
10668                         if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10669                                 genMinus (ic);
10670                         break;
10671                         
10672                 case '*' :
10673                         genMult (ic);
10674                         break;
10675                         
10676                 case '/' :
10677                         genDiv (ic) ;
10678                         break;
10679                         
10680                 case '%' :
10681                         genMod (ic);
10682                         break;
10683                         
10684                 case '>' :
10685                         genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));         
10686                         break;
10687                         
10688                 case '<' :
10689                         genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10690                         break;
10691                         
10692                 case LE_OP:
10693                 case GE_OP:
10694                 case NE_OP:
10695                         
10696                         /* note these two are xlated by algebraic equivalence
10697                         during parsing SDCC.y */
10698                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10699                                 "got '>=' or '<=' shouldn't have come here");
10700                         break;  
10701                         
10702                 case EQ_OP:
10703                         genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10704                         break;      
10705                         
10706                 case AND_OP:
10707                         genAndOp (ic);
10708                         break;
10709                         
10710                 case OR_OP:
10711                         genOrOp (ic);
10712                         break;
10713                         
10714                 case '^' :
10715                         genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10716                         break;
10717                         
10718                 case '|' :
10719                         genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10720                         break;
10721                         
10722                 case BITWISEAND:
10723                         genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10724                         break;
10725                         
10726                 case INLINEASM:
10727                         genInline (ic);
10728                         break;
10729                         
10730                 case RRC:
10731                         genRRC (ic);
10732                         break;
10733                         
10734                 case RLC:
10735                         genRLC (ic);
10736                         break;
10737                         
10738                 case GETHBIT:
10739                         genGetHbit (ic);
10740                         break;
10741                         
10742                 case LEFT_OP:
10743                         genLeftShift (ic);
10744                         break;
10745                         
10746                 case RIGHT_OP:
10747                         genRightShift (ic);
10748                         break;
10749                         
10750                 case GET_VALUE_AT_ADDRESS:
10751                         genPointerGet(ic);
10752                         break;
10753                         
10754                 case '=' :
10755                         if (POINTER_SET(ic))
10756                                 genPointerSet(ic);
10757                         else
10758                                 genAssign(ic);
10759                         break;
10760                         
10761                 case IFX:
10762                         genIfx (ic,NULL);
10763                         break;
10764                         
10765                 case ADDRESS_OF:
10766                         genAddrOf (ic);
10767                         break;
10768                         
10769                 case JUMPTABLE:
10770                         genJumpTab (ic);
10771                         break;
10772                         
10773                 case CAST:
10774                         genCast (ic);
10775                         break;
10776                         
10777                 case RECEIVE:
10778                         genReceive(ic);
10779                         break;
10780                         
10781                 case SEND:
10782                         addSet(&_G.sendSet,ic);
10783                         break;
10784                         
10785                 case DUMMY_READ_VOLATILE:
10786                         genDummyRead (ic);
10787                         break;
10788                         
10789                 default :
10790                         fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10791                         ic = ic;
10792                         break;
10793                 }
10794         }
10795
10796         
10797         /* now we are ready to call the
10798         peep hole optimizer */
10799         if (!options.nopeep) {
10800                 peepHole (&lineHead);
10801         }
10802         /* now do the actual printing */
10803         printLine (lineHead,codeOutBuf);
10804         
10805 #ifdef PCODE_DEBUG
10806         DFPRINTF((stderr,"printing pBlock\n\n"));
10807         printpBlock(stdout,pb);
10808 #endif
10809         
10810         return;
10811 }
10812
10813 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10814  * (meaning: representing its own address) or not (referencing its contents).
10815  * This can only be decided based on the operand's type. */
10816 int
10817 aop_isLitLike (asmop *aop)
10818 {
10819   assert (aop);
10820   if (aop->type == AOP_LIT) return 1;
10821 if (aop->type == AOP_IMMD) return 1;
10822   if ((aop->type == AOP_PCODE) &&
10823                 ((aop->aopu.pcop->type == PO_LITERAL)))
10824   {
10825     /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10826      * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10827     return 1;
10828   }
10829   return 0;
10830 }
10831
10832 int
10833 op_isLitLike (operand *op)
10834 {
10835   assert (op);
10836   if (aop_isLitLike (AOP(op))) return 1;
10837   if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10838   if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;
10839   return 0;
10840 }
10841