507d386d9b8b50f7010d3ebc788e71f48bb52399
[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 /*
34  * This is the down and dirty file with all kinds of
35  * kludgy & hacky stuff. This is what it is all about
36  * CODE GENERATION for a specific MCU . some of the
37  * routines may be reusable, will have to see.
38  */
39
40 #include "gen.h"
41 #include "glue.h"
42
43 /*
44  * Imports
45  */
46 extern struct dbuf_s *codeOutBuf;
47 extern set *externs;
48
49
50 static pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
51 static pCodeOp *popRegFromString(char *str, int size, int offset);
52 static int aop_isLitLike(asmop *aop);
53
54 /* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
55 #define PIC_IS_DATA_PTR(x)  (IS_DATA_PTR(x) || IS_FARPTR(x))
56
57 /*
58  * max_key keeps track of the largest label number used in
59  * a function. This is then used to adjust the label offset
60  * for the next function.
61  */
62 static int max_key = 0;
63 static int labelOffset = 0;
64 static int GpsuedoStkPtr = 0;
65 static int pic14_inISR = 0;
66
67 static char *zero = "0x00";
68 static char *one  = "0x01";
69 static char *spname = "sp";
70
71 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
72 static char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
73 static char **fReturn = fReturnpic14;
74
75 static struct {
76     short accInUse;
77     short inLine;
78     short debugLine;
79     short nRegsSaved;
80     set *sendSet;
81 } _G;
82
83 /*
84  * Resolved ifx structure. This structure stores information
85  * about an iCode ifx that makes it easier to generate code.
86  */
87 typedef struct resolvedIfx {
88     symbol *lbl;     /* pointer to a label */
89     int condition;   /* true or false ifx */
90     int generated;   /* set true when the code associated with the ifx
91                       * is generated */
92 } resolvedIfx;
93
94 static lineNode *lineHead = NULL;
95 static lineNode *lineCurr = NULL;
96 static pBlock *pb;
97
98 /*-----------------------------------------------------------------*/
99 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
100 /*                 exponent of 2 is returned, otherwise -1 is      */
101 /*                 returned.                                       */
102 /* note that this is similar to the function `powof2' in SDCCsymt  */
103 /* if(n == 2^y)                                                    */
104 /*   return y;                                                     */
105 /* return -1;                                                      */
106 /*-----------------------------------------------------------------*/
107 static int my_powof2 (unsigned long num)
108 {
109     if(num) {
110         if( (num & (num-1)) == 0) {
111             int nshifts = -1;
112             while(num) {
113                 num>>=1;
114                 nshifts++;
115             }
116             return nshifts;
117         }
118     }
119
120     return -1;
121 }
122
123 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
124 {
125
126     DEBUGpic14_emitcode ("; ","line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
127         line_no,
128         ((result) ? AopType(AOP_TYPE(result)) : "-"),
129         ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
130         ((result) ? AOP_SIZE(result) : 0),
131         ((left)   ? AopType(AOP_TYPE(left)) : "-"),
132         ((left)   ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
133         ((left)   ? AOP_SIZE(left) : 0),
134         ((right)  ? AopType(AOP_TYPE(right)) : "-"),
135         ((right)  ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
136         ((right)  ? AOP_SIZE(right) : 0));
137
138 }
139
140 static void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
141 {
142
143     DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
144         line_no,
145         ((result) ? AopType(AOP_TYPE(result)) : "-"),
146         ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
147         ((left)   ? AopType(AOP_TYPE(left)) : "-"),
148         ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
149         ((right)  ? AopType(AOP_TYPE(right)) : "-"),
150         ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
151
152 }
153
154 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
155 {
156     va_list ap;
157     char lb[INITIAL_INLINEASM];
158     unsigned char *lbp = (unsigned char *)lb;
159
160     if(!debug_verbose && !options.debug)
161         return;
162
163     va_start(ap,fmt);
164
165     if (inst && *inst) {
166         if (fmt && *fmt)
167             sprintf(lb,"%s\t",inst);
168         else
169             sprintf(lb,"%s",inst);
170         vsprintf(lb+(strlen(lb)),fmt,ap);
171     }  else
172         vsprintf(lb,fmt,ap);
173
174     while (isspace(*lbp)) lbp++;
175
176     if (lbp && *lbp)
177         lineCurr = (lineCurr ?
178         connectLine(lineCurr,newLineNode(lb)) :
179     (lineHead = newLineNode(lb)));
180     lineCurr->isInline = _G.inLine;
181     lineCurr->isDebug  = _G.debugLine;
182
183     addpCode2pBlock(pb,newpCodeCharP(lb));
184
185     va_end(ap);
186 }
187
188 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
189 {
190 #if defined (HAVE_VSNPRINTF)
191   vsnprintf (buf, size, fmt, ap);
192 #elif defined (HAVE_VSPRINTF)
193   vsprintf (buf, size, fmt, ap);
194   if (strlen (buf) >= size)
195   {
196     fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
197   }
198 #elif defined (HAVE_SNPRINTF)
199   snprintf (buf, size, "vs(n)printf required");
200 #elif defined (HAVE_SRINTF)
201   sprintf (buf, "vs(n)printf required");
202   if (strlen (buf) >= size)
203   {
204     fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
205   }
206 #else
207   assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
208 #endif
209 }
210
211 void emitpComment (const char *fmt, ...)
212 {
213   va_list va;
214   char buffer[4096];
215
216   va_start (va, fmt);
217   if (pb) {
218     Safe_vsnprintf (buffer, 4096, fmt, va);
219     //fprintf (stderr, "%s\n" ,buffer);
220     addpCode2pBlock (pb, newpCodeCharP (buffer));
221 #if 0
222   } else {
223     Safe_vsnprintf (buffer, 4096, fmt, va);
224     fprintf (stderr, "No current pBlock -- discarding comment [%s]\n", buffer);
225 #endif
226   }
227   va_end (va);
228 }
229
230 void emitpLabel(int key)
231 {
232     addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
233 }
234
235 /* gen.h defines a macro emitpcode that should be used to call emitpcode
236  * as this allows for easy debugging (ever asked the question: where was
237  * this instruction geenrated? Here is the answer... */
238 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
239 {
240     if(pcop)
241         addpCode2pBlock(pb,newpCode(poc,pcop));
242     else {
243         static int has_warned = 0;
244
245         DEBUGpic14_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
246         if (!has_warned) {
247             has_warned = 1;
248             fprintf( stderr, "WARNING: encountered NULL pcop--this is probably a compiler bug...\n" );
249         }
250     }
251 }
252
253 static void emitpcodeNULLop(PIC_OPCODE poc)
254 {
255
256     addpCode2pBlock(pb,newpCode(poc,NULL));
257
258 }
259
260
261 /*-----------------------------------------------------------------*/
262 /* pic14_emitcode - writes the code into a file : for now it is simple    */
263 /*-----------------------------------------------------------------*/
264 void pic14_emitcode (char *inst,char *fmt, ...)
265 {
266     va_list ap;
267     char lb[INITIAL_INLINEASM];
268     char *lbp = lb;
269
270     va_start(ap,fmt);
271
272     if (inst && *inst) {
273         if (fmt && *fmt)
274             sprintf(lb,"%s\t",inst);
275         else
276             sprintf(lb,"%s",inst);
277         vsprintf(lb+(strlen(lb)),fmt,ap);
278     }  else
279         vsprintf(lb,fmt,ap);
280
281     while (isspace(*lbp)) lbp++;
282
283     if (lbp && *lbp)
284         lineCurr = (lineCurr ?
285         connectLine(lineCurr,newLineNode(lb)) :
286     (lineHead = newLineNode(lb)));
287     lineCurr->isInline = _G.inLine;
288     lineCurr->isDebug  = _G.debugLine;
289     lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
290
291     if(debug_verbose)
292         addpCode2pBlock(pb,newpCodeCharP(lb));
293
294     va_end(ap);
295 }
296
297 /*-----------------------------------------------------------------*/
298 /* pic14_emitDebuggerSymbol - associate the current code location  */
299 /*   with a debugger symbol                                        */
300 /*-----------------------------------------------------------------*/
301 void
302 pic14_emitDebuggerSymbol (char * debugSym)
303 {
304     _G.debugLine = 1;
305     pic14_emitcode ("", ";%s ==.", debugSym);
306     _G.debugLine = 0;
307 }
308
309 /*-----------------------------------------------------------------*/
310 /* newAsmop - creates a new asmOp                                  */
311 /*-----------------------------------------------------------------*/
312 static asmop *newAsmop (short type)
313 {
314     asmop *aop;
315
316     aop = Safe_calloc(1,sizeof(asmop));
317     aop->type = type;
318     return aop;
319 }
320
321 /*-----------------------------------------------------------------*/
322 /* resolveIfx - converts an iCode ifx into a form more useful for  */
323 /*              generating code                                    */
324 /*-----------------------------------------------------------------*/
325 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
326 {
327     if(!resIfx)
328         return;
329
330     //  DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
331
332     resIfx->condition = 1;  /* assume that the ifx is true */
333     resIfx->generated = 0;  /* indicate that the ifx has not been used */
334
335     if(!ifx) {
336         resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL);  / * oops, there is no ifx. so create a label */
337                                             /*
338                                             DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
339                                             __FUNCTION__,__LINE__,resIfx->lbl->key);
340         */
341     } else {
342         if(IC_TRUE(ifx)) {
343             resIfx->lbl = IC_TRUE(ifx);
344         } else {
345             resIfx->lbl = IC_FALSE(ifx);
346             resIfx->condition = 0;
347         }
348         /*
349         if(IC_TRUE(ifx))
350         DEBUGpic14_emitcode("; ***","ifx true is non-null");
351         if(IC_FALSE(ifx))
352         DEBUGpic14_emitcode("; ***","ifx false is non-null");
353         */
354     }
355
356     //  DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
357
358 }
359 /*-----------------------------------------------------------------*/
360 /* pointerCode - returns the code for a pointer type               */
361 /*-----------------------------------------------------------------*/
362 #if 0
363 static int pointerCode (sym_link *etype)
364 {
365
366     return PTR_TYPE(SPEC_OCLS(etype));
367
368 }
369 #endif
370
371 /*-----------------------------------------------------------------*/
372 /* aopForSym - for a true symbol                                   */
373 /*-----------------------------------------------------------------*/
374 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
375 {
376     asmop *aop;
377     memmap *space= SPEC_OCLS(sym->etype);
378
379     DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
380     /* if already has one */
381     if (sym->aop)
382         return sym->aop;
383
384     //DEBUGpic14_emitcode(";","%d",__LINE__);
385     /* if it is in direct space */
386     if (IN_DIRSPACE(space)) {
387         sym->aop = aop = newAsmop (AOP_DIR);
388         aop->aopu.aop_dir = sym->rname ;
389         aop->size = getSize(sym->type);
390         DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
391         return aop;
392     }
393
394     /* special case for a function */
395     if (IS_FUNC(sym->type)) {
396
397         sym->aop = aop = newAsmop(AOP_PCODE);
398         aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
399         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
400         PCOI(aop->aopu.pcop)->_function = 1;
401         PCOI(aop->aopu.pcop)->index = 0;
402         aop->size = FPTRSIZE;
403         /*
404         sym->aop = aop = newAsmop(AOP_IMMD);
405         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
406         strcpy(aop->aopu.aop_immd,sym->rname);
407         aop->size = FPTRSIZE;
408         */
409         DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
410         return aop;
411     }
412
413     if (IS_ARRAY(sym->type)) {
414         sym->aop = aop = newAsmop(AOP_PCODE);
415         aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
416         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
417         PCOI(aop->aopu.pcop)->_function = 0;
418         PCOI(aop->aopu.pcop)->index = 0;
419         aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
420
421         DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
422         return aop;
423     }
424
425     /* only remaining is far space */
426     /* in which case DPTR gets the address */
427     sym->aop = aop = newAsmop(AOP_PCODE);
428
429     aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
430     PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
431     PCOI(aop->aopu.pcop)->index = 0;
432
433     DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
434         __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
435
436     allocDirReg (IC_LEFT(ic));
437
438     aop->size = FPTRSIZE;
439
440     /* if it is in code space */
441     if (IN_CODESPACE(space))
442         aop->code = 1;
443
444     return aop;
445 }
446
447 /*-----------------------------------------------------------------*/
448 /* aopForRemat - rematerialzes an object                           */
449 /*-----------------------------------------------------------------*/
450 static asmop *aopForRemat (operand *op) // x symbol *sym)
451 {
452     symbol *sym = OP_SYMBOL(op);
453     iCode *ic = NULL;
454     asmop *aop = newAsmop(AOP_PCODE);
455     int val = 0;
456     int offset = 0;
457
458     ic = sym->rematiCode;
459
460     DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
461     if(IS_OP_POINTER(op)) {
462         DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
463     }
464     for (;;) {
465         if (ic->op == '+') {
466             val += (int) operandLitValue(IC_RIGHT(ic));
467         } else if (ic->op == '-') {
468             val -= (int) operandLitValue(IC_RIGHT(ic));
469         } else
470             break;
471
472         ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
473     }
474
475     offset = OP_SYMBOL(IC_LEFT(ic))->offset;
476     aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
477     PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
478     PCOI(aop->aopu.pcop)->index = val;
479
480     DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
481         __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
482         val, IS_PTR_CONST(operandType(op)));
483
484     //  DEBUGpic14_emitcode(";","aop type  %s",AopType(AOP_TYPE(IC_LEFT(ic))));
485
486     allocDirReg (IC_LEFT(ic));
487
488     return aop;
489 }
490
491 static int aopIdx (asmop *aop, int offset)
492 {
493     if(!aop)
494         return -1;
495
496     if(aop->type !=  AOP_REG)
497         return -2;
498
499     return aop->aopu.aop_reg[offset]->rIdx;
500
501 }
502 /*-----------------------------------------------------------------*/
503 /* regsInCommon - two operands have some registers in common       */
504 /*-----------------------------------------------------------------*/
505 static bool regsInCommon (operand *op1, operand *op2)
506 {
507     symbol *sym1, *sym2;
508     int i;
509
510     /* if they have registers in common */
511     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
512         return FALSE ;
513
514     sym1 = OP_SYMBOL(op1);
515     sym2 = OP_SYMBOL(op2);
516
517     if (sym1->nRegs == 0 || sym2->nRegs == 0)
518         return FALSE ;
519
520     for (i = 0 ; i < sym1->nRegs ; i++) {
521         int j;
522         if (!sym1->regs[i])
523             continue ;
524
525         for (j = 0 ; j < sym2->nRegs ;j++ ) {
526             if (!sym2->regs[j])
527                 continue ;
528
529             if (sym2->regs[j] == sym1->regs[i])
530                 return TRUE ;
531         }
532     }
533
534     return FALSE ;
535 }
536
537 /*-----------------------------------------------------------------*/
538 /* operandsEqu - equivalent                                        */
539 /*-----------------------------------------------------------------*/
540 static bool operandsEqu ( operand *op1, operand *op2)
541 {
542     symbol *sym1, *sym2;
543
544     /* if they not symbols */
545     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
546         return FALSE;
547
548     sym1 = OP_SYMBOL(op1);
549     sym2 = OP_SYMBOL(op2);
550
551     /* if both are itemps & one is spilt
552     and the other is not then false */
553     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
554         sym1->isspilt != sym2->isspilt )
555         return FALSE ;
556
557     /* if they are the same */
558     if (sym1 == sym2)
559         return TRUE ;
560
561     if (sym1->rname[0] && sym2->rname[0]
562         && strcmp (sym1->rname, sym2->rname) == 0)
563         return TRUE;
564
565
566     /* if left is a tmp & right is not */
567     if (IS_ITEMP(op1)  &&
568         !IS_ITEMP(op2) &&
569         sym1->isspilt  &&
570         (sym1->usl.spillLoc == sym2))
571         return TRUE;
572
573     if (IS_ITEMP(op2)  &&
574         !IS_ITEMP(op1) &&
575         sym2->isspilt  &&
576         sym1->level > 0 &&
577         (sym2->usl.spillLoc == sym1))
578         return TRUE ;
579
580     return FALSE ;
581 }
582
583 /*-----------------------------------------------------------------*/
584 /* pic14_sameRegs - two asmops have the same registers             */
585 /*-----------------------------------------------------------------*/
586 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
587 {
588     int i;
589
590     if (aop1 == aop2)
591         return TRUE ;
592
593     if (aop1->type != AOP_REG ||
594         aop2->type != AOP_REG )
595         return FALSE ;
596
597     if (aop1->size != aop2->size )
598         return FALSE ;
599
600     for (i = 0 ; i < aop1->size ; i++ )
601         if (aop1->aopu.aop_reg[i] !=
602             aop2->aopu.aop_reg[i] )
603             return FALSE ;
604
605         return TRUE ;
606 }
607
608 /*-----------------------------------------------------------------*/
609 /* aopOp - allocates an asmop for an operand  :                    */
610 /*-----------------------------------------------------------------*/
611 void aopOp (operand *op, iCode *ic, bool result)
612 {
613     asmop *aop;
614     symbol *sym;
615     int i;
616
617     if (!op)
618         return ;
619
620     /* if this a literal */
621     if (IS_OP_LITERAL(op)) {
622         op->aop = aop = newAsmop(AOP_LIT);
623         aop->aopu.aop_lit = op->operand.valOperand;
624         aop->size = getSize(operandType(op));
625         return;
626     }
627
628     {
629         sym_link *type = operandType(op);
630         if(IS_PTR_CONST(type))
631             DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
632     }
633
634     /* if already has a asmop then continue */
635     if (op->aop)
636         return ;
637
638     /* if the underlying symbol has a aop */
639     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
640         DEBUGpic14_emitcode(";","%d",__LINE__);
641         op->aop = OP_SYMBOL(op)->aop;
642         return;
643     }
644
645     /* if this is a true symbol */
646     if (IS_TRUE_SYMOP(op)) {
647         //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
648         op->aop = aopForSym(ic,OP_SYMBOL(op),result);
649         return ;
650     }
651
652     /* this is a temporary : this has
653     only four choices :
654     a) register
655     b) spillocation
656     c) rematerialize
657     d) conditional
658     e) can be a return use only */
659
660     sym = OP_SYMBOL(op);
661
662
663     /* if the type is a conditional */
664     if (sym->regType == REG_CND) {
665         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
666         aop->size = 0;
667         return;
668     }
669
670     /* if it is spilt then two situations
671     a) is rematerialize
672     b) has a spill location */
673     if (sym->isspilt || sym->nRegs == 0) {
674
675         DEBUGpic14_emitcode(";","%d",__LINE__);
676         /* rematerialize it NOW */
677         if (sym->remat) {
678
679             sym->aop = op->aop = aop = aopForRemat (op);
680             aop->size = getSize(sym->type);
681             //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
682             return;
683         }
684
685         if (sym->ruonly ) {
686             if(sym->isptr) {    // && sym->uptr
687                 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
688                 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
689
690                 //PCOI(aop->aopu.pcop)->_const = 0;
691                 //PCOI(aop->aopu.pcop)->index = 0;
692                 /*
693                 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
694                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
695                 */
696                 //allocDirReg (IC_LEFT(ic));
697
698                 aop->size = getSize(sym->type);
699                 DEBUGpic14_emitcode(";","%d",__LINE__);
700                 return;
701
702             } else {
703
704                 unsigned i;
705
706                 aop = op->aop = sym->aop = newAsmop(AOP_STR);
707                 aop->size = getSize(sym->type);
708                 for ( i = 0 ; i < fReturnSizePic ; i++ )
709                     aop->aopu.aop_str[i] = fReturn[i];
710
711                 DEBUGpic14_emitcode(";","%d",__LINE__);
712                 return;
713             }
714         }
715
716         /* else spill location  */
717         if (sym->usl.spillLoc)
718         {
719             asmop *oldAsmOp = NULL;
720
721             if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
722             {
723                 /* force a new aop if sizes differ */
724                 oldAsmOp = sym->usl.spillLoc->aop;
725                 sym->usl.spillLoc->aop = NULL;
726             }
727             DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
728                 __FUNCTION__,__LINE__,
729                 sym->usl.spillLoc->rname,
730                 sym->rname, sym->usl.spillLoc->offset);
731
732             sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
733             if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
734             {
735                 /* Don't reuse the new aop, go with the last one */
736                 sym->usl.spillLoc->aop = oldAsmOp;
737             }
738             //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
739             aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname,
740                 getSize(sym->type),
741                 sym->usl.spillLoc->offset);
742             aop->size = getSize(sym->type);
743
744             return;
745         }
746     }
747
748     {
749         sym_link *type = operandType(op);
750         if(IS_PTR_CONST(type))
751             DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
752     }
753
754     /* must be in a register */
755     DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
756     sym->aop = op->aop = aop = newAsmop(AOP_REG);
757     aop->size = sym->nRegs;
758     for ( i = 0 ; i < sym->nRegs ;i++)
759         aop->aopu.aop_reg[i] = sym->regs[i];
760 }
761
762 /*-----------------------------------------------------------------*/
763 /* freeAsmop - free up the asmop given to an operand               */
764 /*----------------------------------------------------------------*/
765 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
766 {
767     asmop *aop ;
768
769     if (!op)
770         aop = aaop;
771     else
772         aop = op->aop;
773
774     if (!aop)
775         return ;
776
777     aop->freed = 1;
778
779     /* all other cases just dealloc */
780     if (op) {
781         op->aop = NULL;
782         if (IS_SYMOP(op)) {
783             OP_SYMBOL(op)->aop = NULL;
784             /* if the symbol has a spill */
785             if (SPIL_LOC(op))
786                 SPIL_LOC(op)->aop = NULL;
787         }
788     }
789 }
790
791 /*-----------------------------------------------------------------*/
792 /* pic14aopLiteral - string from a literal value                   */
793 /*-----------------------------------------------------------------*/
794 static unsigned int pic14aopLiteral (value *val, int offset)
795 {
796         union {
797                 float f;
798                 unsigned char c[4];
799         } fl;
800
801         /* if it is a float then it gets tricky */
802         /* otherwise it is fairly simple */
803         if (!IS_FLOAT(val->type)) {
804                 unsigned long v = ulFromVal (val);
805
806                 return ( (v >> (offset * 8)) & 0xff);
807         }
808
809         /* it is type float */
810         fl.f = (float) floatFromVal(val);
811 #ifdef WORDS_BIGENDIAN
812         return fl.c[3-offset];
813 #else
814         return fl.c[offset];
815 #endif
816 }
817
818 /*-----------------------------------------------------------------*/
819 /* aopGet - for fetching value of the aop                          */
820 /*-----------------------------------------------------------------*/
821 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
822 {
823     char *s = buffer ;
824     char *rs;
825
826     //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
827     /* offset is greater than
828     size then zero */
829     assert(aop);
830     if (offset > (aop->size - 1) &&
831         aop->type != AOP_LIT)
832         return zero;
833
834     /* depending on type */
835     switch (aop->type) {
836
837     case AOP_IMMD:
838         if (bit16)
839             sprintf (s,"%s",aop->aopu.aop_immd);
840         else
841             if (offset)
842                 sprintf(s,"(%s >> %d)",
843                 aop->aopu.aop_immd,
844                 offset*8);
845             else
846                 sprintf(s,"%s",
847                 aop->aopu.aop_immd);
848             DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
849             rs = Safe_calloc(1,strlen(s)+1);
850             strcpy(rs,s);
851             return rs;
852
853     case AOP_DIR:
854         if (offset) {
855             sprintf(s,"(%s + %d)",
856                 aop->aopu.aop_dir,
857                 offset);
858             DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
859         } else
860             sprintf(s,"%s",aop->aopu.aop_dir);
861         rs = Safe_calloc(1,strlen(s)+1);
862         strcpy(rs,s);
863         return rs;
864
865     case AOP_REG:
866         //if (dname)
867         //    return aop->aopu.aop_reg[offset]->dname;
868         //else
869         return aop->aopu.aop_reg[offset]->name;
870
871     case AOP_CRY:
872         //pic14_emitcode(";","%d",__LINE__);
873         return aop->aopu.aop_dir;
874
875     case AOP_LIT:
876         sprintf(s, "0x%02x", pic14aopLiteral (aop->aopu.aop_lit, offset));
877         rs = Safe_strdup(s);
878         return rs;
879
880     case AOP_STR:
881         aop->coff = offset ;
882         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
883             dname)
884             return "acc";
885         DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
886
887         return aop->aopu.aop_str[offset];
888
889     case AOP_PCODE:
890         {
891             pCodeOp *pcop = aop->aopu.pcop;
892             DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
893             if(pcop->name) {
894                 if (pcop->type == PO_IMMEDIATE) {
895                     offset += PCOI(pcop)->index;
896                 }
897                 if (offset) {
898                     DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
899                     sprintf(s,"(%s+%d)", pcop->name,offset);
900                 } else {
901                     DEBUGpic14_emitcode(";","%s",pcop->name);
902                     sprintf(s,"%s", pcop->name);
903                 }
904             } else
905                 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
906
907         }
908         rs = Safe_calloc(1,strlen(s)+1);
909         strcpy(rs,s);
910         return rs;
911
912   }
913
914   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
915       "aopget got unsupported aop->type");
916   exit(0);
917 }
918
919
920 /*-----------------------------------------------------------------*/
921 /* popGetTempReg - create a new temporary pCodeOp                  */
922 /*-----------------------------------------------------------------*/
923 static pCodeOp *popGetTempReg(void)
924 {
925
926     pCodeOp *pcop;
927
928     pcop = newpCodeOp(NULL, PO_GPR_TEMP);
929     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
930         PCOR(pcop)->r->wasUsed=1;
931         PCOR(pcop)->r->isFree=0;
932     }
933
934     return pcop;
935 }
936
937 /*-----------------------------------------------------------------*/
938 /* popReleaseTempReg - create a new temporary pCodeOp                  */
939 /*-----------------------------------------------------------------*/
940 static void popReleaseTempReg(pCodeOp *pcop)
941 {
942
943     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
944         PCOR(pcop)->r->isFree = 1;
945
946 }
947 /*-----------------------------------------------------------------*/
948 /* popGetLabel - create a new pCodeOp of type PO_LABEL             */
949 /*-----------------------------------------------------------------*/
950 pCodeOp *popGetLabel(unsigned int key)
951 {
952
953     DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
954
955     if(key>(unsigned int)max_key)
956         max_key = key;
957
958     return newpCodeOpLabel(NULL,key+100+labelOffset);
959 }
960
961 /*-------------------------------------------------------------------*/
962 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
963 /*-------------------------------------------------------------------*/
964 static pCodeOp *popGetHighLabel(unsigned int key)
965 {
966     pCodeOp *pcop;
967     pcop = popGetLabel(key);
968     PCOLAB(pcop)->offset = 1;
969     return pcop;
970 }
971
972 /*-----------------------------------------------------------------*/
973 /* popGetLit - asm operator to pcode operator conversion               */
974 /*-----------------------------------------------------------------*/
975 pCodeOp *popGetLit(unsigned int lit)
976 {
977
978     return newpCodeOpLit((unsigned char)lit);
979 }
980
981 /*-----------------------------------------------------------------*/
982 /* popGetImmd - asm operator to pcode immediate conversion         */
983 /*-----------------------------------------------------------------*/
984 static pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
985 {
986
987     return newpCodeOpImmd(name, offset,index, 0, is_func);
988 }
989
990 /*-----------------------------------------------------------------*/
991 /* popGetWithString - asm operator to pcode operator conversion            */
992 /*-----------------------------------------------------------------*/
993 static pCodeOp *popGetWithString(char *str, int isExtern)
994 {
995     pCodeOp *pcop;
996
997
998     if(!str) {
999         fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1000         exit (1);
1001     }
1002
1003     pcop = newpCodeOp(str,PO_STR);
1004     PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1005
1006     return pcop;
1007 }
1008
1009 pCodeOp *popGetExternal (char *str, int isReg)
1010 {
1011     pCodeOp *pcop;
1012
1013     if (isReg) {
1014         pcop = newpCodeOpRegFromStr(str);
1015     } else {
1016         pcop = popGetWithString (str, 1);
1017     }
1018
1019     if (str) {
1020       symbol *sym;
1021
1022       for (sym = setFirstItem (externs); sym; sym = setNextItem (externs))
1023       {
1024         if (!strcmp (str, sym->rname)) break;
1025       }
1026
1027       if (!sym)
1028       {
1029         sym = newSymbol(str, 0);
1030         strncpy(sym->rname, str, SDCC_NAME_MAX);
1031         addSet (&externs, sym);
1032       } // if
1033       sym->used++;
1034     }
1035     return pcop;
1036 }
1037
1038 /*-----------------------------------------------------------------*/
1039 /* popRegFromString -                                              */
1040 /*-----------------------------------------------------------------*/
1041 static pCodeOp *popRegFromString(char *str, int size, int offset)
1042 {
1043
1044     pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1045     pcop->type = PO_DIR;
1046
1047     DEBUGpic14_emitcode(";","%d",__LINE__);
1048
1049     if(!str)
1050         str = "BAD_STRING";
1051
1052     pcop->name = Safe_calloc(1,strlen(str)+1);
1053     strcpy(pcop->name,str);
1054
1055     //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1056
1057     PCOR(pcop)->r = dirregWithName(pcop->name);
1058     if(PCOR(pcop)->r == NULL) {
1059         //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1060         PCOR(pcop)->r = allocRegByName (pcop->name,size);
1061         DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1062     } else {
1063         DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1064     }
1065     PCOR(pcop)->instance = offset;
1066
1067     return pcop;
1068 }
1069
1070 /*-----------------------------------------------------------------*/
1071 /*-----------------------------------------------------------------*/
1072 static pCodeOp *popRegFromIdx(int rIdx)
1073 {
1074     pCodeOp *pcop;
1075
1076     DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1077         __FUNCTION__,__LINE__,rIdx);
1078
1079     pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1080
1081     PCOR(pcop)->rIdx = rIdx;
1082     PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1083     PCOR(pcop)->r->isFree = 0;
1084     PCOR(pcop)->r->wasUsed = 1;
1085
1086     pcop->type = PCOR(pcop)->r->pc_type;
1087
1088
1089     return pcop;
1090 }
1091
1092 /*-----------------------------------------------------------------*/
1093 /* popGet - asm operator to pcode operator conversion              */
1094 /*-----------------------------------------------------------------*/
1095 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1096 {
1097     //char *s = buffer ;
1098     //char *rs;
1099
1100     pCodeOp *pcop;
1101
1102     //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1103     /* offset is greater than
1104     size then zero */
1105
1106     assert (aop);
1107
1108
1109     /* XXX: still needed for BIT operands (AOP_CRY) */
1110     if (offset > (aop->size - 1) &&
1111         aop->type != AOP_LIT &&
1112         aop->type != AOP_PCODE)
1113     {
1114         printf( "%s: (offset[%d] > AOP_SIZE(op)[%d]-1) && AOP_TYPE(op) != AOP_LIT)\n", __FUNCTION__, offset, aop->size);
1115         return NULL;  //zero;
1116     }
1117
1118     /* depending on type */
1119     switch (aop->type) {
1120
1121     case AOP_IMMD:
1122         DEBUGpic14_emitcode(";","%d",__LINE__);
1123         return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1124
1125     case AOP_DIR:
1126         return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1127 #if 0
1128         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1129         pcop->type = PO_DIR;
1130
1131         pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1132         strcpy(pcop->name,aop->aopu.aop_dir);
1133         PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1134         if(PCOR(pcop)->r == NULL) {
1135             //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1136             PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1137             DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1138         } else {
1139             DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1140         }
1141         PCOR(pcop)->instance = offset;
1142
1143         return pcop;
1144 #endif
1145
1146     case AOP_REG:
1147         {
1148             int rIdx;
1149             assert (offset < aop->size);
1150             rIdx = aop->aopu.aop_reg[offset]->rIdx;
1151
1152             pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1153             PCOR(pcop)->rIdx = rIdx;
1154             PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1155             PCOR(pcop)->r->wasUsed=1;
1156             PCOR(pcop)->r->isFree=0;
1157
1158             PCOR(pcop)->instance = offset;
1159             pcop->type = PCOR(pcop)->r->pc_type;
1160             //rs = aop->aopu.aop_reg[offset]->name;
1161             DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1162             return pcop;
1163         }
1164
1165     case AOP_CRY:
1166         pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1167         PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1168         //if(PCOR(pcop)->r == NULL)
1169         //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1170         return pcop;
1171
1172     case AOP_LIT:
1173         return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1174
1175     case AOP_STR:
1176         DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1177         return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1178         /*
1179         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1180         PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1181         PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1182         pcop->type = PCOR(pcop)->r->pc_type;
1183         pcop->name = PCOR(pcop)->r->name;
1184
1185           return pcop;
1186         */
1187
1188     case AOP_PCODE:
1189         pcop = NULL;
1190         DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1191             __LINE__,
1192             ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1193         //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1194         switch (aop->aopu.pcop->type)
1195         {
1196         case PO_IMMEDIATE:
1197           pcop = pCodeOpCopy (aop->aopu.pcop);
1198           /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1199            * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1200           PCOI(pcop)->index += offset;
1201           //PCOI(pcop)->offset = 0;
1202           break;
1203         case PO_DIR:
1204           pcop = pCodeOpCopy (aop->aopu.pcop);
1205           PCOR(pcop)->instance = offset;
1206           break;
1207         default:
1208           assert ( !"unhandled pCode type" );
1209           break;
1210         } // switch
1211         return pcop;
1212     }
1213
1214     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1215         "popGet got unsupported aop->type");
1216     exit(0);
1217 }
1218
1219 /*-----------------------------------------------------------------*/
1220 /* popGetAddr - access the low/high word of a symbol (immediate)   */
1221 /*              (for non-PO_IMMEDIATEs this is the same as popGet) */
1222 /*-----------------------------------------------------------------*/
1223 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1224 {
1225   if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1226   {
1227     pCodeOp *pcop = aop->aopu.pcop;
1228     assert (offset <= GPTRSIZE);
1229
1230     /* special case: index >= 2 should return GPOINTER-style values */
1231     if (offset == 2)
1232     {
1233       pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1234       return pcop;
1235     }
1236
1237     pcop = pCodeOpCopy (pcop);
1238     /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1239      * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1240     PCOI(pcop)->offset += offset;
1241     PCOI(pcop)->index += index;
1242     //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);
1243     return pcop;
1244   } else {
1245     return popGet (aop, offset + index);
1246   }
1247 }
1248
1249 /*-----------------------------------------------------------------*/
1250 /* aopPut - puts a string for a aop                                */
1251 /*-----------------------------------------------------------------*/
1252 void aopPut (asmop *aop, char *s, int offset)
1253 {
1254     char *d = buffer ;
1255     symbol *lbl ;
1256
1257     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1258
1259     if (aop->size && offset > ( aop->size - 1)) {
1260         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1261             "aopPut got offset > aop->size");
1262         exit(0);
1263     }
1264
1265     /* will assign value to value */
1266     /* depending on where it is ofcourse */
1267     switch (aop->type) {
1268     case AOP_DIR:
1269         if (offset) {
1270             sprintf(d,"(%s + %d)",
1271                 aop->aopu.aop_dir,offset);
1272             fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1273
1274         } else
1275             sprintf(d,"%s",aop->aopu.aop_dir);
1276
1277         if (strcmp(d,s)) {
1278             DEBUGpic14_emitcode(";","%d",__LINE__);
1279             if(strcmp(s,"W"))
1280                 pic14_emitcode("movf","%s,w",s);
1281             pic14_emitcode("movwf","%s",d);
1282
1283             if(strcmp(s,"W")) {
1284                 pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1285                 if(offset >= aop->size) {
1286                     emitpcode(POC_CLRF,popGet(aop,offset));
1287                     break;
1288                 } else {
1289                     emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1290                 }
1291             }
1292             emitpcode(POC_MOVWF,popGet(aop,offset));
1293
1294         }
1295         break;
1296
1297     case AOP_REG:
1298         if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1299             /*
1300             if (*s == '@'         ||
1301             strcmp(s,"r0") == 0 ||
1302             strcmp(s,"r1") == 0 ||
1303             strcmp(s,"r2") == 0 ||
1304             strcmp(s,"r3") == 0 ||
1305             strcmp(s,"r4") == 0 ||
1306             strcmp(s,"r5") == 0 ||
1307             strcmp(s,"r6") == 0 ||
1308             strcmp(s,"r7") == 0 )
1309             pic14_emitcode("mov","%s,%s  ; %d",
1310             aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1311             else
1312             */
1313
1314             if(strcmp(s,"W")==0 )
1315                 pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1316
1317             pic14_emitcode("movwf","%s",
1318                 aop->aopu.aop_reg[offset]->name);
1319
1320             if(strcmp(s,zero)==0) {
1321                 emitpcode(POC_CLRF,popGet(aop,offset));
1322
1323             } else if(strcmp(s,"W")==0) {
1324                 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1325                 pcop->type = PO_GPR_REGISTER;
1326
1327                 PCOR(pcop)->rIdx = -1;
1328                 PCOR(pcop)->r = NULL;
1329
1330                 DEBUGpic14_emitcode(";","%d",__LINE__);
1331                 pcop->name = Safe_strdup(s);
1332                 emitpcode(POC_MOVFW,pcop);
1333                 emitpcode(POC_MOVWF,popGet(aop,offset));
1334             } else if(strcmp(s,one)==0) {
1335                 emitpcode(POC_CLRF,popGet(aop,offset));
1336                 emitpcode(POC_INCF,popGet(aop,offset));
1337             } else {
1338                 emitpcode(POC_MOVWF,popGet(aop,offset));
1339             }
1340         }
1341         break;
1342
1343     case AOP_STK:
1344         if (strcmp(s,"a") == 0)
1345             pic14_emitcode("push","acc");
1346         else
1347             pic14_emitcode("push","%s",s);
1348
1349         break;
1350
1351     case AOP_CRY:
1352         /* if bit variable */
1353         if (!aop->aopu.aop_dir) {
1354             pic14_emitcode("clr","a");
1355             pic14_emitcode("rlc","a");
1356         } else {
1357             if (s == zero)
1358                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1359             else
1360                 if (s == one)
1361                     pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1362                 else
1363                     if (!strcmp(s,"c"))
1364                         pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1365                     else {
1366                         lbl = newiTempLabel(NULL);
1367
1368                         if (strcmp(s,"a")) {
1369                             MOVA(s);
1370                         }
1371                         pic14_emitcode("clr","c");
1372                         pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1373                         pic14_emitcode("cpl","c");
1374                         pic14_emitcode("","%05d_DS_:",lbl->key+100);
1375                         pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1376                     }
1377         }
1378         break;
1379
1380     case AOP_STR:
1381         aop->coff = offset;
1382         if (strcmp(aop->aopu.aop_str[offset],s))
1383             pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1384         break;
1385
1386     default :
1387         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1388             "aopPut got unsupported aop->type");
1389         exit(0);
1390     }
1391
1392 }
1393
1394 /*-----------------------------------------------------------------*/
1395 /* mov2w_op - generate either a MOVLW or MOVFW based operand type  */
1396 /*-----------------------------------------------------------------*/
1397 static void mov2w_op (operand *op, int offset)
1398 {
1399     assert (op);
1400     FENTRY;
1401
1402     /* for PO_IMMEDIATEs: use address or value? */
1403     if (op_isLitLike (op))
1404     {
1405         /* access address of op */
1406         if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1407         if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1408         {
1409             if (offset == GPTRSIZE-1)
1410                 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1411             else
1412                 emitpcode (POC_MOVLW, popGetLit (0));
1413         }
1414         else
1415             emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1416     } else {
1417         /* access value stored in op */
1418         mov2w (AOP(op), offset);
1419     }
1420 }
1421
1422
1423 /*-----------------------------------------------------------------*/
1424 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1425 /*-----------------------------------------------------------------*/
1426 void mov2w (asmop *aop, int offset)
1427 {
1428
1429     if(!aop)
1430         return;
1431
1432     DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1433
1434     if ( aop_isLitLike (aop) )
1435         emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1436     else
1437         emitpcode(POC_MOVFW,popGet(aop,offset));
1438
1439 }
1440
1441 static void movwf (asmop *op, int offset)
1442 {
1443     emitpcode (POC_MOVWF, popGet(op, offset));
1444 }
1445
1446 static pCodeOp *get_argument_pcop (int idx)
1447 {
1448     assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1449     return popRegFromIdx (Gstack_base_addr - (idx - 1));
1450 }
1451
1452 static pCodeOp *get_return_val_pcop (int offset)
1453 {
1454     assert (offset > 0 && "the most significant byte is returned via WREG");
1455     return popRegFromIdx (Gstack_base_addr - (offset - 1));
1456 }
1457
1458 static void pass_argument (operand *op, int offset, int idx)
1459 {
1460     if (op)
1461         mov2w_op (op, offset);
1462     if (idx != 0)
1463         emitpcode(POC_MOVWF, get_argument_pcop (idx));
1464 }
1465
1466 static void get_returnvalue (operand *op, int offset, int idx)
1467 {
1468     if (idx != 0)
1469         emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1470     movwf(AOP(op), offset);
1471 }
1472
1473 static void call_libraryfunc (char *name)
1474 {
1475     symbol *sym;
1476
1477     /* library code might reside in different page... */
1478     emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1479     /* call the library function */
1480     emitpcode (POC_CALL, popGetExternal (name, 0));
1481     /* might return from different page... */
1482     emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1483
1484     /* create symbol, mark it as `extern' */
1485     sym = findSym(SymbolTab, NULL, name);
1486     if (!sym) {
1487     sym = newSymbol(name, 0);
1488     strncpy(sym->rname, name, SDCC_NAME_MAX);
1489     addSym(SymbolTab, sym, sym->rname, 0, 0, 0);
1490     addSet(&externs, sym);
1491     } // if
1492     sym->used++;
1493 }
1494
1495 /*-----------------------------------------------------------------*/
1496 /* pic14_getDataSize - get the operand data size                   */
1497 /*-----------------------------------------------------------------*/
1498 int pic14_getDataSize(operand *op)
1499 {
1500     int size;
1501
1502     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1503
1504 #if 0
1505     size = getSize(OP_SYM_ETYPE(op));
1506     return size;
1507     //return AOP_SIZE(op);
1508
1509     // tsd- in the pic port, the genptr size is 1, so this code here
1510     // fails. ( in the 8051 port, the size was 4).
1511 #else
1512     size = AOP_SIZE(op);
1513     if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)))
1514     {
1515         sym_link *type = operandType(op);
1516         if (IS_GENPTR(type))
1517         {
1518             /* generic pointer; arithmetic operations
1519             * should ignore the high byte (pointer type).
1520             */
1521             size--;
1522             DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1523         }
1524     }
1525     return size;
1526 #endif
1527 }
1528
1529 /*-----------------------------------------------------------------*/
1530 /* pic14_outAcc - output Acc                                       */
1531 /*-----------------------------------------------------------------*/
1532 void pic14_outAcc(operand *result)
1533 {
1534     int size,offset;
1535     DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1536     DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1537
1538
1539     size = pic14_getDataSize(result);
1540     if(size){
1541         emitpcode(POC_MOVWF,popGet(AOP(result),0));
1542         size--;
1543         offset = 1;
1544         /* unsigned or positive */
1545         while(size--)
1546             emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1547     }
1548
1549 }
1550
1551 /*-----------------------------------------------------------------*/
1552 /* pic14_outBitC - output a bit C                                  */
1553 /*-----------------------------------------------------------------*/
1554 static void pic14_outBitC(operand *result)
1555 {
1556
1557     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1558     /* if the result is bit */
1559     if (AOP_TYPE(result) == AOP_CRY)
1560         aopPut(AOP(result),"c",0);
1561     else {
1562         pic14_emitcode("clr","a  ; %d", __LINE__);
1563         pic14_emitcode("rlc","a");
1564         pic14_outAcc(result);
1565     }
1566 }
1567
1568 /*-----------------------------------------------------------------*/
1569 /* pic14_toBoolean - emit code for orl a,operator(sizeop)          */
1570 /*-----------------------------------------------------------------*/
1571 static void pic14_toBoolean(operand *oper)
1572 {
1573     int size = AOP_SIZE(oper);
1574     int offset = 0;
1575
1576     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1577
1578     assert (size > 0);
1579
1580     if (size == 1) {
1581         /* MOVFW does not load the flags... */
1582         emitpcode(POC_MOVLW, popGetLit(0));
1583         offset = 0;
1584     } else {
1585         emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1586         offset = 1;
1587     }
1588
1589     while (offset < size) {
1590         emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1591     }
1592     /* Z is set iff (oper == 0) */
1593 }
1594
1595
1596 /*-----------------------------------------------------------------*/
1597 /* genNot - generate code for ! operation                          */
1598 /*-----------------------------------------------------------------*/
1599 static void genNot (iCode *ic)
1600 {
1601     //symbol *tlbl;
1602     int size;
1603
1604     FENTRY;
1605
1606     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1607     /* assign asmOps to operand & result */
1608     aopOp (IC_LEFT(ic),ic,FALSE);
1609     aopOp (IC_RESULT(ic),ic,TRUE);
1610
1611     DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1612     /* if in bit space then a special case */
1613     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1614         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1615             emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
1616             emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
1617         } else {
1618             emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
1619             emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
1620             emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
1621         }
1622         goto release;
1623     }
1624
1625     size = AOP_SIZE(IC_LEFT(ic));
1626     mov2w (AOP(IC_LEFT(ic)),0);
1627     while (--size > 0)
1628     {
1629       if (op_isLitLike (IC_LEFT(ic)))
1630         emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
1631       else
1632         emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
1633     }
1634     emitpcode(POC_MOVLW, popGetLit (0));
1635     emitSKPNZ;
1636     emitpcode(POC_MOVLW, popGetLit (1));
1637     movwf(AOP(IC_RESULT(ic)), 0);
1638
1639     for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
1640     {
1641       emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
1642     }
1643     goto release;
1644
1645 release:
1646     /* release the aops */
1647     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1648     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1649 }
1650
1651
1652 /*-----------------------------------------------------------------*/
1653 /* genCpl - generate code for complement                           */
1654 /*-----------------------------------------------------------------*/
1655 static void genCpl (iCode *ic)
1656 {
1657     operand *left, *result;
1658     int size, offset=0;
1659
1660     FENTRY;
1661
1662     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1663     aopOp((left = IC_LEFT(ic)),ic,FALSE);
1664     aopOp((result=IC_RESULT(ic)),ic,TRUE);
1665
1666     /* if both are in bit space then
1667     a special case */
1668     if (AOP_TYPE(result) == AOP_CRY &&
1669         AOP_TYPE(left) == AOP_CRY ) {
1670
1671         pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir);
1672         pic14_emitcode("cpl","c");
1673         pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir);
1674         goto release;
1675     }
1676
1677     size = AOP_SIZE(result);
1678     if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
1679     while (size--) {
1680         emitpcode(POC_COMFW,popGet(AOP(left),offset));
1681         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
1682         offset++;
1683     }
1684     addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
1685
1686
1687 release:
1688     /* release the aops */
1689     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1690     freeAsmop(result,NULL,ic,TRUE);
1691 }
1692
1693 /*-----------------------------------------------------------------*/
1694 /* genUminusFloat - unary minus for floating points                */
1695 /*-----------------------------------------------------------------*/
1696 static void genUminusFloat(operand *op,operand *result)
1697 {
1698     int size ,offset =0 ;
1699     char *l;
1700
1701     FENTRY;
1702
1703     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1704     /* for this we just need to flip the
1705     first it then copy the rest in place */
1706     size = AOP_SIZE(op) - 1;
1707     l = aopGet(AOP(op),3,FALSE,FALSE);
1708
1709     MOVA(l);
1710
1711     pic14_emitcode("cpl","acc.7");
1712     aopPut(AOP(result),"a",3);
1713
1714     while(size--) {
1715         aopPut(AOP(result),
1716             aopGet(AOP(op),offset,FALSE,FALSE),
1717             offset);
1718         offset++;
1719     }
1720 }
1721
1722 /*-----------------------------------------------------------------*/
1723 /* genUminus - unary minus code generation                         */
1724 /*-----------------------------------------------------------------*/
1725 static void genUminus (iCode *ic)
1726 {
1727     int size, i;
1728     sym_link *optype, *rtype;
1729
1730     FENTRY;
1731
1732     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1733     /* assign asmops */
1734     aopOp(IC_LEFT(ic),ic,FALSE);
1735     aopOp(IC_RESULT(ic),ic,TRUE);
1736
1737     /* if both in bit space then special
1738     case */
1739     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1740         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1741
1742         emitpcode(POC_BCF,   popGet(AOP(IC_RESULT(ic)),0));
1743         emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
1744         emitpcode(POC_BSF,   popGet(AOP(IC_RESULT(ic)),0));
1745
1746         goto release;
1747     }
1748
1749     optype = operandType(IC_LEFT(ic));
1750     rtype = operandType(IC_RESULT(ic));
1751
1752     /* if float then do float stuff */
1753     if (IS_FLOAT(optype)) {
1754         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1755         goto release;
1756     }
1757
1758     /* otherwise subtract from zero by taking the 2's complement */
1759     size = AOP_SIZE(IC_LEFT(ic));
1760
1761     for(i=0; i<size; i++) {
1762         if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
1763             emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
1764         else {
1765             emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
1766             emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
1767         }
1768     }
1769
1770     emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
1771     for(i=1; i<size; i++) {
1772         emitSKPNZ;
1773         emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
1774     }
1775
1776 release:
1777     /* release the aops */
1778     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1779     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1780 }
1781
1782 /*-----------------------------------------------------------------*/
1783 /* saverbank - saves an entire register bank on the stack          */
1784 /*-----------------------------------------------------------------*/
1785 static void saverbank (int bank, iCode *ic, bool pushPsw)
1786 {
1787     FENTRY;
1788
1789     DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
1790 #if 0
1791     int i;
1792     asmop *aop ;
1793     regs *r = NULL;
1794
1795     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1796     if (options.useXstack) {
1797
1798         aop = newAsmop(0);
1799         r = getFreePtr(ic,&aop,FALSE);
1800         pic14_emitcode("mov","%s,_spx",r->name);
1801
1802     }
1803
1804     for (i = 0 ; i < pic14_nRegs ;i++) {
1805         if (options.useXstack) {
1806             pic14_emitcode("inc","%s",r->name);
1807             //pic14_emitcode("mov","a,(%s+%d)",
1808             //       regspic14[i].base,8*bank+regspic14[i].offset);
1809             pic14_emitcode("movx","@%s,a",r->name);
1810         } else
1811             pic14_emitcode("push","");// "(%s+%d)",
1812         //regspic14[i].base,8*bank+regspic14[i].offset);
1813     }
1814
1815     if (pushPsw) {
1816         if (options.useXstack) {
1817             pic14_emitcode("mov","a,psw");
1818             pic14_emitcode("movx","@%s,a",r->name);
1819             pic14_emitcode("inc","%s",r->name);
1820             pic14_emitcode("mov","_spx,%s",r->name);
1821             freeAsmop (NULL,aop,ic,TRUE);
1822
1823         } else
1824             pic14_emitcode("push","psw");
1825
1826         pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1827     }
1828     ic->bankSaved = 1;
1829 #endif
1830 }
1831
1832 /*-----------------------------------------------------------------*/
1833 /* saveRegisters - will look for a call and save the registers     */
1834 /*-----------------------------------------------------------------*/
1835 static void saveRegisters(iCode *lic)
1836 {
1837     iCode *ic;
1838     bitVect *rsave;
1839     sym_link *dtype;
1840
1841     FENTRY;
1842
1843     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1844     /* look for call */
1845     for (ic = lic ; ic ; ic = ic->next)
1846         if (ic->op == CALL || ic->op == PCALL)
1847             break;
1848
1849         if (!ic) {
1850             fprintf(stderr,"found parameter push with no function call\n");
1851             return ;
1852         }
1853
1854         /* if the registers have been saved already then
1855         do nothing */
1856         if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
1857             return ;
1858
1859             /* find the registers in use at this time
1860         and push them away to safety */
1861         rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1862             ic->rUsed);
1863
1864         ic->regsSaved = 1;
1865
1866         //fprintf(stderr, "ERROR: saveRegisters did not do anything to save registers, please report this as a bug.\n");
1867
1868         dtype = operandType(IC_LEFT(ic));
1869         if (currFunc && dtype &&
1870             (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
1871             IFFUNC_ISISR(currFunc->type) &&
1872             !ic->bankSaved)
1873
1874             saverbank(FUNC_REGBANK(dtype),ic,TRUE);
1875
1876 }
1877 /*-----------------------------------------------------------------*/
1878 /* unsaveRegisters - pop the pushed registers                      */
1879 /*-----------------------------------------------------------------*/
1880 static void unsaveRegisters (iCode *ic)
1881 {
1882     int i;
1883     bitVect *rsave;
1884
1885     FENTRY;
1886
1887     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1888     /* find the registers in use at this time
1889     and push them away to safety */
1890     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1891         ic->rUsed);
1892
1893     if (options.useXstack) {
1894         pic14_emitcode("mov","r0,%s",spname);
1895         for (i =  pic14_nRegs ; i >= 0 ; i--) {
1896             if (bitVectBitValue(rsave,i)) {
1897                 pic14_emitcode("dec","r0");
1898                 pic14_emitcode("movx","a,@r0");
1899                 pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
1900             }
1901
1902         }
1903         pic14_emitcode("mov","%s,r0",spname);
1904     } //else
1905     //for (i =  pic14_nRegs ; i >= 0 ; i--) {
1906     //  if (bitVectBitValue(rsave,i))
1907     //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
1908     //}
1909
1910 }
1911
1912
1913 /*-----------------------------------------------------------------*/
1914 /* pushSide -                */
1915 /*-----------------------------------------------------------------*/
1916 static void pushSide(operand * oper, int size)
1917 {
1918 #if 0
1919     int offset = 0;
1920     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1921     while (size--) {
1922         char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1923         if (AOP_TYPE(oper) != AOP_REG &&
1924             AOP_TYPE(oper) != AOP_DIR &&
1925             strcmp(l,"a") ) {
1926             pic14_emitcode("mov","a,%s",l);
1927             pic14_emitcode("push","acc");
1928         } else
1929             pic14_emitcode("push","%s",l);
1930     }
1931 #endif
1932 }
1933
1934 /*-----------------------------------------------------------------*/
1935 /* assignResultValue -               */
1936 /*-----------------------------------------------------------------*/
1937 static void assignResultValue(operand * oper)
1938 {
1939     int size = AOP_SIZE(oper);
1940     int offset = 0;
1941
1942     FENTRY;
1943
1944     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1945
1946     DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
1947
1948     /* assign MSB first (passed via WREG) */
1949     while (size--) {
1950         get_returnvalue (oper, size, offset + GpsuedoStkPtr);
1951         GpsuedoStkPtr++;
1952     }
1953 }
1954
1955
1956 /*-----------------------------------------------------------------*/
1957 /* genIpush - genrate code for pushing this gets a little complex  */
1958 /*-----------------------------------------------------------------*/
1959 static void genIpush (iCode *ic)
1960 {
1961     FENTRY;
1962
1963     DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
1964 #if 0
1965     int size, offset = 0 ;
1966     char *l;
1967
1968
1969     /* if this is not a parm push : ie. it is spill push
1970     and spill push is always done on the local stack */
1971     if (!ic->parmPush) {
1972
1973         /* and the item is spilt then do nothing */
1974         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1975             return ;
1976
1977         aopOp(IC_LEFT(ic),ic,FALSE);
1978         size = AOP_SIZE(IC_LEFT(ic));
1979         /* push it on the stack */
1980         while(size--) {
1981             l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1982             if (*l == '#') {
1983                 MOVA(l);
1984                 l = "acc";
1985             }
1986             pic14_emitcode("push","%s",l);
1987         }
1988         return ;
1989     }
1990
1991     /* this is a paramter push: in this case we call
1992     the routine to find the call and save those
1993     registers that need to be saved */
1994     saveRegisters(ic);
1995
1996     /* then do the push */
1997     aopOp(IC_LEFT(ic),ic,FALSE);
1998
1999
2000     // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2001     size = AOP_SIZE(IC_LEFT(ic));
2002
2003     while (size--) {
2004         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2005         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2006             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2007             strcmp(l,"a") ) {
2008             pic14_emitcode("mov","a,%s",l);
2009             pic14_emitcode("push","acc");
2010         } else
2011             pic14_emitcode("push","%s",l);
2012     }
2013
2014     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2015 #endif
2016 }
2017
2018 /*-----------------------------------------------------------------*/
2019 /* genIpop - recover the registers: can happen only for spilling   */
2020 /*-----------------------------------------------------------------*/
2021 static void genIpop (iCode *ic)
2022 {
2023     FENTRY;
2024
2025     DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2026     assert (!"genIpop -- unimplemented");
2027 #if 0
2028     int size,offset ;
2029
2030
2031     /* if the temp was not pushed then */
2032     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2033         return ;
2034
2035     aopOp(IC_LEFT(ic),ic,FALSE);
2036     size = AOP_SIZE(IC_LEFT(ic));
2037     offset = (size-1);
2038     while (size--)
2039         pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2040         FALSE,TRUE));
2041
2042     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2043 #endif
2044 }
2045
2046 /*-----------------------------------------------------------------*/
2047 /* unsaverbank - restores the resgister bank from stack            */
2048 /*-----------------------------------------------------------------*/
2049 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2050 {
2051     FENTRY;
2052
2053     DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2054 #if 0
2055     int i;
2056     asmop *aop ;
2057     regs *r = NULL;
2058
2059     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2060     if (popPsw) {
2061         if (options.useXstack) {
2062             aop = newAsmop(0);
2063             r = getFreePtr(ic,&aop,FALSE);
2064
2065
2066             pic14_emitcode("mov","%s,_spx",r->name);
2067             pic14_emitcode("movx","a,@%s",r->name);
2068             pic14_emitcode("mov","psw,a");
2069             pic14_emitcode("dec","%s",r->name);
2070
2071         }else
2072             pic14_emitcode ("pop","psw");
2073     }
2074
2075     for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2076         if (options.useXstack) {
2077             pic14_emitcode("movx","a,@%s",r->name);
2078             //pic14_emitcode("mov","(%s+%d),a",
2079             //     regspic14[i].base,8*bank+regspic14[i].offset);
2080             pic14_emitcode("dec","%s",r->name);
2081
2082         } else
2083             pic14_emitcode("pop",""); //"(%s+%d)",
2084         //regspic14[i].base,8*bank); //+regspic14[i].offset);
2085     }
2086
2087     if (options.useXstack) {
2088
2089         pic14_emitcode("mov","_spx,%s",r->name);
2090         freeAsmop(NULL,aop,ic,TRUE);
2091
2092     }
2093 #endif
2094 }
2095
2096 /*-----------------------------------------------------------------*/
2097 /* genCall - generates a call statement                            */
2098 /*-----------------------------------------------------------------*/
2099 static void genCall (iCode *ic)
2100 {
2101     sym_link *dtype;
2102     symbol *sym;
2103     char *name;
2104     int isExtern;
2105
2106     FENTRY;
2107
2108     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2109
2110     /* if caller saves & we have not saved then */
2111     if (!ic->regsSaved)
2112         saveRegisters(ic);
2113
2114         /* if we are calling a function that is not using
2115         the same register bank then we need to save the
2116     destination registers on the stack */
2117     dtype = operandType(IC_LEFT(ic));
2118     if (currFunc && dtype &&
2119         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2120         IFFUNC_ISISR(currFunc->type) &&
2121         !ic->bankSaved)
2122
2123         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2124
2125     /* if send set is not empty the assign */
2126     if (_G.sendSet) {
2127         iCode *sic;
2128         /* For the Pic port, there is no data stack.
2129         * So parameters passed to functions are stored
2130         * in registers. (The pCode optimizer will get
2131         * rid of most of these :).
2132         */
2133         int psuedoStkPtr=-1;
2134         int firstTimeThruLoop = 1;
2135
2136         _G.sendSet = reverseSet(_G.sendSet);
2137
2138         /* First figure how many parameters are getting passed */
2139         for (sic = setFirstItem(_G.sendSet) ; sic ;
2140         sic = setNextItem(_G.sendSet)) {
2141
2142             aopOp(IC_LEFT(sic),sic,FALSE);
2143             psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2144             freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2145         }
2146
2147         for (sic = setFirstItem(_G.sendSet) ; sic ;
2148         sic = setNextItem(_G.sendSet)) {
2149             int size, offset = 0;
2150
2151             aopOp(IC_LEFT(sic),sic,FALSE);
2152             size = AOP_SIZE(IC_LEFT(sic));
2153
2154             while (size--) {
2155                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2156                     AopType(AOP_TYPE(IC_LEFT(sic))));
2157
2158                 if(!firstTimeThruLoop) {
2159                     /* If this is not the first time we've been through the loop
2160                     * then we need to save the parameter in a temporary
2161                     * register. The last byte of the last parameter is
2162                     * passed in W. */
2163                     emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2164
2165                 }
2166                 firstTimeThruLoop=0;
2167
2168                 mov2w_op (IC_LEFT(sic),  offset);
2169                 offset++;
2170             }
2171             freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2172         }
2173         _G.sendSet = NULL;
2174     }
2175     /* make the call */
2176     sym = OP_SYMBOL(IC_LEFT(ic));
2177     name = sym->rname[0] ? sym->rname : sym->name;
2178     /*
2179      * As SDCC emits code as soon as it reaches the end of each
2180      * function's definition, prototyped functions that are implemented
2181      * after the current one are always considered EXTERN, which
2182      * introduces many unneccessary PAGESEL instructions.
2183      * XXX: Use a post pass to iterate over all `CALL _name' statements
2184      * and insert `PAGESEL _name' and `PAGESEL $' around the CALL
2185      * only iff there is no definition of the function in the whole
2186      * file (might include this in the PAGESEL pass).
2187      */
2188     isExtern = IS_EXTERN(sym->etype) || pic14_inISR;
2189     if (isExtern) {
2190         /* Extern functions and ISRs maybe on a different page;
2191          * must call pagesel */
2192         emitpcode(POC_PAGESEL,popGetWithString(name,1));
2193     }
2194     emitpcode(POC_CALL,popGetWithString(name,isExtern));
2195     if (isExtern) {
2196         /* May have returned from a different page;
2197          * must use pagesel to restore PCLATH before next
2198          * goto or call instruction */
2199         emitpcode(POC_PAGESEL,popGetWithString("$",0));
2200     }
2201     GpsuedoStkPtr=0;
2202     /* if we need assign a result value */
2203     if ((IS_ITEMP(IC_RESULT(ic)) &&
2204         (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2205         OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2206         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2207
2208         _G.accInUse++;
2209         aopOp(IC_RESULT(ic),ic,FALSE);
2210         _G.accInUse--;
2211
2212         assignResultValue(IC_RESULT(ic));
2213
2214         DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2215             AopType(AOP_TYPE(IC_RESULT(ic))));
2216
2217         freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2218     }
2219
2220     /* if register bank was saved then pop them */
2221     if (ic->bankSaved)
2222         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2223
2224     /* if we hade saved some registers then unsave them */
2225     if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2226         unsaveRegisters (ic);
2227
2228
2229 }
2230
2231 /*-----------------------------------------------------------------*/
2232 /* genPcall - generates a call by pointer statement                */
2233 /*-----------------------------------------------------------------*/
2234 static void genPcall (iCode *ic)
2235 {
2236     sym_link *dtype;
2237     symbol *albl = newiTempLabel(NULL);
2238     symbol *blbl = newiTempLabel(NULL);
2239     PIC_OPCODE poc;
2240     pCodeOp *pcop;
2241     operand *left;
2242
2243     FENTRY;
2244
2245     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2246     /* if caller saves & we have not saved then */
2247     if (!ic->regsSaved)
2248         saveRegisters(ic);
2249
2250         /* if we are calling a function that is not using
2251         the same register bank then we need to save the
2252     destination registers on the stack */
2253     dtype = operandType(IC_LEFT(ic));
2254     if (currFunc && dtype &&
2255         IFFUNC_ISISR(currFunc->type) &&
2256         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2257         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2258
2259     left = IC_LEFT(ic);
2260     aopOp(left,ic,FALSE);
2261     DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2262
2263     poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2264
2265     pushSide(IC_LEFT(ic), FPTRSIZE);
2266
2267     /* if send set is not empty, assign parameters */
2268     if (_G.sendSet) {
2269
2270         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2271         /* no way to pass args - W always gets used to make the call */
2272     }
2273     /* first idea - factor out a common helper function and call it.
2274     But don't know how to get it generated only once in its own block
2275
2276     if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2277         char *rname;
2278         char *buffer;
2279         rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2280         DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2281         buffer = Safe_calloc(1,strlen(rname)+16);
2282         sprintf(buffer, "%s_goto_helper", rname);
2283         addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2284         free(buffer);
2285     }
2286     */
2287     emitpcode(POC_CALL,popGetLabel(albl->key));
2288     pcop = popGetLabel(blbl->key);
2289     emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2290     emitpcode(POC_GOTO,pcop);
2291     emitpLabel(albl->key);
2292
2293     emitpcode(poc,popGetAddr(AOP(left),1,0));
2294     emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2295     emitpcode(poc,popGetAddr(AOP(left),0,0));
2296     emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2297
2298     emitpLabel(blbl->key);
2299
2300     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2301
2302     /* if we need to assign a result value */
2303     if ((IS_ITEMP(IC_RESULT(ic)) &&
2304         (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2305         OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2306         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2307
2308         _G.accInUse++;
2309         aopOp(IC_RESULT(ic),ic,FALSE);
2310         _G.accInUse--;
2311
2312         GpsuedoStkPtr = 0;
2313
2314         assignResultValue(IC_RESULT(ic));
2315
2316         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2317     }
2318
2319     /* if register bank was saved then unsave them */
2320     if (currFunc && dtype &&
2321         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2322         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2323
2324         /* if we hade saved some registers then
2325     unsave them */
2326     if (ic->regsSaved)
2327         unsaveRegisters (ic);
2328
2329 }
2330
2331 /*-----------------------------------------------------------------*/
2332 /* resultRemat - result  is rematerializable                       */
2333 /*-----------------------------------------------------------------*/
2334 static int resultRemat (iCode *ic)
2335 {
2336     //  DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2337     FENTRY;
2338
2339     if (SKIP_IC(ic) || ic->op == IFX)
2340         return 0;
2341
2342     if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2343         symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2344         if (sym->remat && !POINTER_SET(ic))
2345             return 1;
2346     }
2347
2348     return 0;
2349 }
2350
2351 #if 0
2352 /*-----------------------------------------------------------------*/
2353 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2354 /*-----------------------------------------------------------------*/
2355 static bool inExcludeList(char *s)
2356 {
2357     DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2358     int i =0;
2359
2360     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2361     if (options.excludeRegs[i] &&
2362         STRCASECMP(options.excludeRegs[i],"none") == 0)
2363         return FALSE ;
2364
2365     for ( i = 0 ; options.excludeRegs[i]; i++) {
2366         if (options.excludeRegs[i] &&
2367             STRCASECMP(s,options.excludeRegs[i]) == 0)
2368             return TRUE;
2369     }
2370     return FALSE ;
2371 }
2372 #endif
2373
2374 /*-----------------------------------------------------------------*/
2375 /* genFunction - generated code for function entry                 */
2376 /*-----------------------------------------------------------------*/
2377 static void genFunction (iCode *ic)
2378 {
2379     symbol *sym;
2380     sym_link *ftype;
2381
2382     FENTRY;
2383
2384     DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2385
2386     labelOffset += (max_key+4);
2387     max_key=0;
2388     GpsuedoStkPtr=0;
2389     _G.nRegsSaved = 0;
2390     /* create the function header */
2391     pic14_emitcode(";","-----------------------------------------");
2392     pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2393     pic14_emitcode(";","-----------------------------------------");
2394
2395     /* prevent this symbol from being emitted as 'extern' */
2396     pic14_stringInSet(sym->rname, &pic14_localFunctions, 1);
2397
2398     pic14_emitcode("","%s:",sym->rname);
2399     addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2400
2401     /* mark symbol as NOT extern (even if it was declared so previously) */
2402     assert(IS_SPEC(sym->etype));
2403     SPEC_EXTR(sym->etype) = 0;
2404     sym->cdef = 0;
2405     if (!SPEC_OCLS(sym->etype)) SPEC_OCLS(sym->etype) = code;
2406     addSetIfnotP(&SPEC_OCLS(sym->etype)->syms, sym);
2407
2408     ftype = operandType(IC_LEFT(ic));
2409
2410     /* if critical function then turn interrupts off */
2411     if (IFFUNC_ISCRITICAL(ftype))
2412         pic14_emitcode("clr","ea");
2413
2414         /* here we need to generate the equates for the
2415     register bank if required */
2416 #if 0
2417     if (FUNC_REGBANK(ftype) != rbank) {
2418         int i ;
2419
2420         rbank = FUNC_REGBANK(ftype);
2421         for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2422             if (strcmp(regspic14[i].base,"0") == 0)
2423                 pic14_emitcode("","%s = 0x%02x",
2424                 regspic14[i].dname,
2425                 8*rbank+regspic14[i].offset);
2426             else
2427                 pic14_emitcode ("","%s = %s + 0x%02x",
2428                 regspic14[i].dname,
2429                 regspic14[i].base,
2430                 8*rbank+regspic14[i].offset);
2431         }
2432     }
2433 #endif
2434
2435     /* if this is an interrupt service routine */
2436     pic14_inISR = 0;
2437     if (IFFUNC_ISISR(sym->type)) {
2438         pic14_inISR = 1;
2439         emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2440         emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2441         /* XXX: Why? Does this assume that ssave and psave reside
2442          * in a shared bank or bank0? We cannot guarantee the
2443          * latter...
2444          */
2445         emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2446         emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2447         //emitpcode(POC_MOVWF,  popGetExternal("___sdcc_saved_status",1 ));
2448         emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2449         /* during an interrupt PCLATH must be cleared before a goto or call statement */
2450         emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));
2451         emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2452         //emitpcode(POC_MOVWF,  popGetExternal("___sdcc_saved_pclath", 1));
2453         emitpcode(POC_MOVFW,  popCopyReg(&pc_fsr));
2454         emitpcode(POC_MOVWF,  popGetExternal("___sdcc_saved_fsr", 1));
2455
2456         pBlockConvert2ISR(pb);
2457         pic14_hasInterrupt = 1;
2458     } else {
2459     /* if callee-save to be used for this function
2460         then save the registers being used in this function */
2461         if (IFFUNC_CALLEESAVES(sym->type)) {
2462             int i;
2463
2464             /* if any registers used */
2465             if (sym->regsUsed) {
2466                 /* save the registers used */
2467                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2468                     if (bitVectBitValue(sym->regsUsed,i)) {
2469                         //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2470                         _G.nRegsSaved++;
2471                     }
2472                 }
2473             }
2474         }
2475     }
2476
2477     /* set the register bank to the desired value */
2478     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2479         pic14_emitcode("push","psw");
2480         pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);
2481     }
2482
2483     if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2484
2485         if (options.useXstack) {
2486             pic14_emitcode("mov","r0,%s",spname);
2487             pic14_emitcode("mov","a,_bp");
2488             pic14_emitcode("movx","@r0,a");
2489             pic14_emitcode("inc","%s",spname);
2490         }
2491         else
2492         {
2493             /* set up the stack */
2494             pic14_emitcode ("push","_bp");   /* save the callers stack  */
2495         }
2496         pic14_emitcode ("mov","_bp,%s",spname);
2497     }
2498
2499     /* adjust the stack for the function */
2500     if (sym->stack) {
2501
2502         int i = sym->stack;
2503         if (i > 256 )
2504             werror(W_STACK_OVERFLOW,sym->name);
2505
2506         if (i > 3 && sym->recvSize < 4) {
2507
2508             pic14_emitcode ("mov","a,sp");
2509             pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2510             pic14_emitcode ("mov","sp,a");
2511
2512         }
2513         else
2514             while(i--)
2515                 pic14_emitcode("inc","sp");
2516     }
2517
2518     if (sym->xstack) {
2519
2520         pic14_emitcode ("mov","a,_spx");
2521         pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2522         pic14_emitcode ("mov","_spx,a");
2523     }
2524
2525 }
2526
2527 /*-----------------------------------------------------------------*/
2528 /* genEndFunction - generates epilogue for functions               */
2529 /*-----------------------------------------------------------------*/
2530 static void genEndFunction (iCode *ic)
2531 {
2532     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2533
2534     FENTRY;
2535
2536     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2537
2538     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2539     {
2540         pic14_emitcode ("mov","%s,_bp",spname);
2541     }
2542
2543     /* if use external stack but some variables were
2544     added to the local stack then decrement the
2545     local stack */
2546     if (options.useXstack && sym->stack) {
2547         pic14_emitcode("mov","a,sp");
2548         pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2549         pic14_emitcode("mov","sp,a");
2550     }
2551
2552
2553     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2554         if (options.useXstack) {
2555             pic14_emitcode("mov","r0,%s",spname);
2556             pic14_emitcode("movx","a,@r0");
2557             pic14_emitcode("mov","_bp,a");
2558             pic14_emitcode("dec","%s",spname);
2559         }
2560         else
2561         {
2562             pic14_emitcode ("pop","_bp");
2563         }
2564     }
2565
2566     /* restore the register bank    */
2567     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2568         pic14_emitcode ("pop","psw");
2569
2570     if (IFFUNC_ISISR(sym->type)) {
2571
2572         /* now we need to restore the registers */
2573         /* if this isr has no bank i.e. is going to
2574         run with bank 0 , then we need to save more
2575 registers :-) */
2576         if (!FUNC_REGBANK(sym->type)) {
2577
2578         /* if this function does not call any other
2579         function then we can be economical and
2580             save only those registers that are used */
2581             if (! IFFUNC_HASFCALL(sym->type)) {
2582                 int i;
2583
2584                 /* if any registers used */
2585                 if (sym->regsUsed) {
2586                     /* save the registers used */
2587                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2588                         if (bitVectBitValue(sym->regsUsed,i)) {
2589                             pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2590                         }
2591                     }
2592                 }
2593
2594             } else {
2595                 /* this function has a function call; cannot
2596                    determines register usage so we will have the
2597                    entire bank */
2598                 unsaverbank(0,ic,FALSE);
2599             }
2600         }
2601
2602         /* if debug then send end of function */
2603         if (options.debug && debugFile && currFunc) {
2604             debugFile->writeEndFunction (currFunc, ic, 1);
2605         }
2606
2607         emitpcode(POC_MOVFW,  popGetExternal("___sdcc_saved_fsr", 1));
2608         emitpcode(POC_MOVWF,  popCopyReg(&pc_fsr));
2609         //emitpcode(POC_MOVFW,  popGetExternal("___sdcc_saved_pclath", 1));
2610         emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
2611         emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
2612         emitpcode(POC_CLRF,   popCopyReg(&pc_status)); // see genFunction
2613         //emitpcode(POC_SWAPFW, popGetExternal("___sdcc_saved_status", 1));
2614         emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
2615         emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
2616         emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
2617         emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
2618         addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
2619         emitpcodeNULLop(POC_RETFIE);
2620     }
2621     else {
2622         if (IFFUNC_ISCRITICAL(sym->type))
2623             pic14_emitcode("setb","ea");
2624
2625         if (IFFUNC_CALLEESAVES(sym->type)) {
2626             int i;
2627
2628             /* if any registers used */
2629             if (sym->regsUsed) {
2630                 /* save the registers used */
2631                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2632                     if (bitVectBitValue(sym->regsUsed,i)) {
2633                         pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2634                     }
2635                 }
2636             }
2637         }
2638
2639         /* if debug then send end of function */
2640         if (options.debug && debugFile && currFunc) {
2641             debugFile->writeEndFunction (currFunc, ic, 1);
2642         }
2643
2644         pic14_emitcode ("return","");
2645         emitpcodeNULLop(POC_RETURN);
2646
2647         /* Mark the end of a function */
2648         addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
2649     }
2650
2651 }
2652
2653 /*-----------------------------------------------------------------*/
2654 /* genRet - generate code for return statement                     */
2655 /*-----------------------------------------------------------------*/
2656 static void genRet (iCode *ic)
2657 {
2658     int size,offset = 0;
2659
2660     FENTRY;
2661
2662     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2663     /* if we have no return value then
2664     just generate the "ret" */
2665     if (!IC_LEFT(ic))
2666         goto jumpret;
2667
2668         /* we have something to return then
2669     move the return value into place */
2670     aopOp(IC_LEFT(ic),ic,FALSE);
2671     size = AOP_SIZE(IC_LEFT(ic));
2672
2673     for (offset = 0; offset < size; offset++)
2674     {
2675         pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
2676     }
2677
2678     freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2679
2680 jumpret:
2681     /* generate a jump to the return label
2682     if the next is not the return statement */
2683     if (!(ic->next && ic->next->op == LABEL &&
2684         IC_LABEL(ic->next) == returnLabel)) {
2685
2686         emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
2687     }
2688
2689 }
2690
2691 /*-----------------------------------------------------------------*/
2692 /* genLabel - generates a label                                    */
2693 /*-----------------------------------------------------------------*/
2694 static void genLabel (iCode *ic)
2695 {
2696     FENTRY;
2697
2698     /* special case never generate */
2699     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2700     if (IC_LABEL(ic) == entryLabel)
2701         return ;
2702
2703     emitpLabel(IC_LABEL(ic)->key);
2704     pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
2705 }
2706
2707 /*-----------------------------------------------------------------*/
2708 /* genGoto - generates a goto                                      */
2709 /*-----------------------------------------------------------------*/
2710 //tsd
2711 static void genGoto (iCode *ic)
2712 {
2713     FENTRY;
2714
2715     emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
2716     pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
2717 }
2718
2719
2720 /*-----------------------------------------------------------------*/
2721 /* genMultbits :- multiplication of bits                           */
2722 /*-----------------------------------------------------------------*/
2723 static void genMultbits (operand *left,
2724                          operand *right,
2725                          operand *result)
2726 {
2727     FENTRY;
2728     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2729
2730     if(!pic14_sameRegs(AOP(result),AOP(right)))
2731         emitpcode(POC_BSF,  popGet(AOP(result),0));
2732
2733     emitpcode(POC_BTFSC,popGet(AOP(right),0));
2734     emitpcode(POC_BTFSS,popGet(AOP(left),0));
2735     emitpcode(POC_BCF,  popGet(AOP(result),0));
2736
2737 }
2738
2739
2740 /*-----------------------------------------------------------------*/
2741 /* genMultOneByte : 8 bit multiplication & division                */
2742 /*-----------------------------------------------------------------*/
2743 static void genMultOneByte (operand *left,
2744                             operand *right,
2745                             operand *result)
2746 {
2747     char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
2748
2749     // symbol *lbl ;
2750     int size,offset,i;
2751
2752
2753     FENTRY;
2754
2755     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2756     DEBUGpic14_AopType(__LINE__,left,right,result);
2757     DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
2758
2759     /* (if two literals, the value is computed before) */
2760     /* if one literal, literal on the right */
2761     if (AOP_TYPE(left) == AOP_LIT){
2762         operand *t = right;
2763         right = left;
2764         left = t;
2765     }
2766
2767     assert (AOP_SIZE(left) == AOP_SIZE(right));
2768
2769     size = min(AOP_SIZE(result),AOP_SIZE(left));
2770     offset = Gstack_base_addr - (2*size - 1);
2771
2772     /* pass right operand as argument */
2773     for (i=0; i < size; i++)
2774     {
2775         mov2w (AOP(right), i);
2776         emitpcode(POC_MOVWF, popRegFromIdx (++offset));
2777     } // for
2778
2779     /* pass left operand as argument */
2780     for (i=0; i < size; i++)
2781     {
2782         mov2w (AOP(left), i);
2783         if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
2784     } // for
2785     assert (offset == Gstack_base_addr);
2786
2787     /* call library routine */
2788     assert (size > 0 && size <= 4);
2789     call_libraryfunc (func[size]);
2790
2791     /* assign result */
2792     movwf (AOP(result), size-1);
2793     for (i=0; i < size - 1; i++)
2794     {
2795         emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
2796         movwf (AOP(result), size - 2 - i);
2797     } // for
2798
2799     /* now (zero-/sign) extend the result to its size */
2800     addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2801 }
2802
2803 /*-----------------------------------------------------------------*/
2804 /* genMult - generates code for multiplication                     */
2805 /*-----------------------------------------------------------------*/
2806 static void genMult (iCode *ic)
2807 {
2808     operand *left = IC_LEFT(ic);
2809     operand *right = IC_RIGHT(ic);
2810     operand *result= IC_RESULT(ic);
2811
2812     FENTRY;
2813
2814     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2815     /* assign the amsops */
2816     aopOp (left,ic,FALSE);
2817     aopOp (right,ic,FALSE);
2818     aopOp (result,ic,TRUE);
2819
2820     DEBUGpic14_AopType(__LINE__,left,right,result);
2821
2822     /* special cases first */
2823     /* both are bits */
2824     if (AOP_TYPE(left) == AOP_CRY &&
2825         AOP_TYPE(right)== AOP_CRY) {
2826         genMultbits(left,right,result);
2827         goto release ;
2828     }
2829
2830     /* if both are of size == 1 */
2831     if (AOP_SIZE(left) == 1 &&
2832         AOP_SIZE(right) == 1 ) {
2833         genMultOneByte(left,right,result);
2834         goto release ;
2835     }
2836
2837     /* should have been converted to function call */
2838     assert(0) ;
2839
2840 release :
2841     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2842     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2843     freeAsmop(result,NULL,ic,TRUE);
2844 }
2845
2846 /*-----------------------------------------------------------------*/
2847 /* genDivbits :- division of bits                                  */
2848 /*-----------------------------------------------------------------*/
2849 static void genDivbits (operand *left,
2850                         operand *right,
2851                         operand *result)
2852 {
2853
2854     char *l;
2855
2856     FENTRY;
2857
2858     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2859     /* the result must be bit */
2860     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
2861     l = aopGet(AOP(left),0,FALSE,FALSE);
2862
2863     MOVA(l);
2864
2865     pic14_emitcode("div","ab");
2866     pic14_emitcode("rrc","a");
2867     aopPut(AOP(result),"c",0);
2868 }
2869
2870 /*-----------------------------------------------------------------*/
2871 /* genDivOneByte : 8 bit division                                  */
2872 /*-----------------------------------------------------------------*/
2873 static void genDivOneByte (operand *left,
2874                            operand *right,
2875                            operand *result)
2876 {
2877     int size;
2878     int sign;
2879
2880     FENTRY;
2881     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2882
2883     assert (AOP_SIZE(right) == 1);
2884     assert (AOP_SIZE(left) == 1);
2885
2886     size = min(AOP_SIZE(result),AOP_SIZE(left));
2887     sign = !(SPEC_USIGN(operandType(left))
2888         && SPEC_USIGN(operandType(right)));
2889
2890     if (AOP_TYPE(right) == AOP_LIT)
2891     {
2892         /* XXX: might add specialized code */
2893     }
2894
2895     if (!sign)
2896     {
2897         /* unsigned division */
2898     #if 1
2899         mov2w(AOP(right),0);
2900         emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
2901         mov2w(AOP(left),0);
2902         call_libraryfunc("__divuchar");
2903         movwf(AOP(result),0);
2904     #else
2905         pCodeOp *temp;
2906         symbol *lbl;
2907
2908         temp = popGetTempReg();
2909         lbl = newiTempLabel(NULL);
2910
2911         /* XXX: improve this naive approach:
2912            [result] = [a] / [b]
2913             ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
2914
2915            In PIC assembler:
2916            movf  left,W
2917            movwf temp       // temp <-- left
2918            movf  right,W    // W <-- right
2919            clrf  result
2920            label1:
2921            incf  result
2922            subwf temp,F     // temp <-- temp - W
2923            skipNC       // subwf clears CARRY (i.e. sets BORROW) if temp < W
2924            goto  label1
2925            decf result      // we just subtract once too often
2926          */
2927
2928         /* XXX: This loops endlessly on DIVIDE BY ZERO */
2929         /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
2930
2931         mov2w(AOP(left),0);
2932         emitpcode(POC_MOVWF, temp);
2933         mov2w(AOP(right),0);
2934         emitpcode(POC_CLRF, popGet(AOP(result),0));
2935
2936         emitpLabel(lbl->key);
2937         emitpcode(POC_INCF, popGet(AOP(result),0));
2938         emitpcode(POC_SUBWF, temp);
2939         emitSKPNC;
2940         emitpcode(POC_GOTO, popGetLabel(lbl->key));
2941         emitpcode(POC_DECF, popGet(AOP(result),0));
2942         popReleaseTempReg(temp);
2943     #endif
2944     }
2945     else
2946     {
2947         /* signed division */
2948         mov2w(AOP(right),0);
2949         emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
2950         mov2w(AOP(left),0);
2951         call_libraryfunc("__divschar");
2952         movwf(AOP(result),0);
2953     }
2954
2955     /* now performed the signed/unsigned division -- extend result */
2956     addSign(result, 1, sign);
2957 }
2958
2959 /*-----------------------------------------------------------------*/
2960 /* genDiv - generates code for division                */
2961 /*-----------------------------------------------------------------*/
2962 static void genDiv (iCode *ic)
2963 {
2964     operand *left = IC_LEFT(ic);
2965     operand *right = IC_RIGHT(ic);
2966     operand *result= IC_RESULT(ic);
2967
2968     FENTRY;
2969     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2970     /* assign the amsops */
2971     aopOp (left,ic,FALSE);
2972     aopOp (right,ic,FALSE);
2973     aopOp (result,ic,TRUE);
2974
2975     /* special cases first */
2976     /* both are bits */
2977     if (AOP_TYPE(left) == AOP_CRY &&
2978         AOP_TYPE(right)== AOP_CRY) {
2979         genDivbits(left,right,result);
2980         goto release ;
2981     }
2982
2983     /* if both are of size == 1 */
2984     if (AOP_SIZE(left) == 1 &&
2985         AOP_SIZE(right) == 1 ) {
2986         genDivOneByte(left,right,result);
2987         goto release ;
2988     }
2989
2990     /* should have been converted to function call */
2991     assert(0);
2992 release :
2993     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2994     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2995     freeAsmop(result,NULL,ic,TRUE);
2996 }
2997
2998 /*-----------------------------------------------------------------*/
2999 /* genModOneByte : 8 bit modulus                                   */
3000 /*-----------------------------------------------------------------*/
3001 static void genModOneByte (operand *left,
3002                            operand *right,
3003                            operand *result)
3004 {
3005     int size;
3006     int sign;
3007
3008     FENTRY;
3009     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3010
3011     assert (AOP_SIZE(right) == 1);
3012     assert (AOP_SIZE(left) == 1);
3013
3014     size = min(AOP_SIZE(result),AOP_SIZE(left));
3015     sign = !(SPEC_USIGN(operandType(left))
3016         && SPEC_USIGN(operandType(right)));
3017
3018     if (AOP_TYPE(right) == AOP_LIT)
3019     {
3020         /* XXX: might add specialized code */
3021     }
3022
3023     if (!sign)
3024     {
3025         /* unsigned division */
3026     #if 1
3027         mov2w(AOP(right),0);
3028         emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3029         mov2w(AOP(left),0);
3030         call_libraryfunc("__moduchar");
3031         movwf(AOP(result),0);
3032     #else
3033         pCodeOp *temp;
3034         symbol *lbl;
3035
3036         lbl = newiTempLabel(NULL);
3037
3038         assert(!pic14_sameRegs(AOP(right),AOP(result)));
3039
3040         /* XXX: improve this naive approach:
3041            [result] = [a] % [b]
3042             ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3043
3044            In PIC assembler:
3045            movf  left,W
3046            movwf result     // result <-- left
3047            movf  right,W    // W <-- right
3048            label1:
3049            subwf result,F   // result <-- result - W
3050            skipNC       // subwf clears CARRY (i.e. sets BORROW) if result < W
3051            goto  label1
3052            addwf result, F  // we just subtract once too often
3053          */
3054
3055         /* XXX: This loops endlessly on DIVIDE BY ZERO */
3056         /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3057
3058         if (!pic14_sameRegs(AOP(left), AOP(result)))
3059         {
3060             mov2w(AOP(left),0);
3061             emitpcode(POC_MOVWF, popGet(AOP(result),0));
3062         }
3063         mov2w(AOP(right),0);
3064
3065         emitpLabel(lbl->key);
3066         emitpcode(POC_SUBWF, popGet(AOP(result),0));
3067         emitSKPNC;
3068         emitpcode(POC_GOTO, popGetLabel(lbl->key));
3069         emitpcode(POC_ADDWF, popGet(AOP(result),0));
3070     #endif
3071     }
3072     else
3073     {
3074         /* signed division */
3075         mov2w(AOP(right),0);
3076         emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3077         mov2w(AOP(left),0);
3078         call_libraryfunc("__modschar");
3079         movwf(AOP(result),0);
3080     }
3081
3082     /* now we performed the signed/unsigned modulus -- extend result */
3083     addSign(result, 1, sign);
3084 }
3085
3086 /*-----------------------------------------------------------------*/
3087 /* genMod - generates code for division                            */
3088 /*-----------------------------------------------------------------*/
3089 static void genMod (iCode *ic)
3090 {
3091     operand *left = IC_LEFT(ic);
3092     operand *right = IC_RIGHT(ic);
3093     operand *result= IC_RESULT(ic);
3094
3095     FENTRY;
3096     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3097     /* assign the amsops */
3098     aopOp (left,ic,FALSE);
3099     aopOp (right,ic,FALSE);
3100     aopOp (result,ic,TRUE);
3101
3102     /* if both are of size == 1 */
3103     if (AOP_SIZE(left) == 1 &&
3104         AOP_SIZE(right) == 1 ) {
3105         genModOneByte(left,right,result);
3106         goto release ;
3107     }
3108
3109     /* should have been converted to function call */
3110     assert(0);
3111
3112 release :
3113     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3114     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3115     freeAsmop(result,NULL,ic,TRUE);
3116 }
3117
3118 /*-----------------------------------------------------------------*/
3119 /* genIfxJump :- will create a jump depending on the ifx           */
3120 /*-----------------------------------------------------------------*/
3121 /*
3122 note: May need to add parameter to indicate when a variable is in bit space.
3123 */
3124 static void genIfxJump (iCode *ic, char *jval)
3125 {
3126
3127     FENTRY;
3128     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3129     /* if true label then we jump if condition
3130     supplied is true */
3131     if ( IC_TRUE(ic) ) {
3132
3133         if(strcmp(jval,"a") == 0)
3134             emitSKPZ;
3135         else if (strcmp(jval,"c") == 0)
3136             emitSKPC;
3137         else {
3138             DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3139             emitpcode(POC_BTFSC,    newpCodeOpBit(jval,-1,1));
3140         }
3141
3142         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3143         pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3144
3145     }
3146     else {
3147         /* false label is present */
3148         if(strcmp(jval,"a") == 0)
3149             emitSKPNZ;
3150         else if (strcmp(jval,"c") == 0)
3151             emitSKPNC;
3152         else {
3153             DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3154             emitpcode(POC_BTFSS,    newpCodeOpBit(jval,-1,1));
3155         }
3156
3157         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3158         pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3159
3160     }
3161
3162
3163     /* mark the icode as generated */
3164     ic->generated = 1;
3165 }
3166
3167 #if 0
3168 /*-----------------------------------------------------------------*/
3169 /* genSkip                                                         */
3170 /*-----------------------------------------------------------------*/
3171 static void genSkip(iCode *ifx,int status_bit)
3172 {
3173     FENTRY;
3174     if(!ifx)
3175         return;
3176
3177     if ( IC_TRUE(ifx) ) {
3178         switch(status_bit) {
3179         case 'z':
3180             emitSKPNZ;
3181             break;
3182
3183         case 'c':
3184             emitSKPNC;
3185             break;
3186
3187         case 'd':
3188             emitSKPDC;
3189             break;
3190
3191         }
3192
3193         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3194         pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3195
3196     } else {
3197
3198         switch(status_bit) {
3199
3200         case 'z':
3201             emitSKPZ;
3202             break;
3203
3204         case 'c':
3205             emitSKPC;
3206             break;
3207
3208         case 'd':
3209             emitSKPDC;
3210             break;
3211         }
3212         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3213         pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3214
3215     }
3216
3217 }
3218 #endif
3219
3220 /*-----------------------------------------------------------------*/
3221 /* genSkipc                                                        */
3222 /*-----------------------------------------------------------------*/
3223 static void genSkipc(resolvedIfx *rifx)
3224 {
3225     FENTRY;
3226     if(!rifx)
3227         return;
3228
3229     if(rifx->condition)
3230         emitSKPNC;
3231     else
3232         emitSKPC;
3233
3234     emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3235     emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3236     rifx->generated = 1;
3237 }
3238
3239 #if 0
3240 /*-----------------------------------------------------------------*/
3241 /* genSkipz2                                                       */
3242 /*-----------------------------------------------------------------*/
3243 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3244 {
3245     FENTRY;
3246     if(!rifx)
3247         return;
3248
3249     if( (rifx->condition ^ invert_condition) & 1)
3250         emitSKPZ;
3251     else
3252         emitSKPNZ;
3253
3254     emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3255     rifx->generated = 1;
3256 }
3257 #endif
3258
3259 #if 0
3260 /*-----------------------------------------------------------------*/
3261 /* genSkipz                                                        */
3262 /*-----------------------------------------------------------------*/
3263 static void genSkipz(iCode *ifx, int condition)
3264 {
3265     FENTRY;
3266     assert (ifx != NULL);
3267
3268     if(condition)
3269         emitSKPNZ;
3270     else
3271         emitSKPZ;
3272
3273     if ( IC_TRUE(ifx) )
3274         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3275     else
3276         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3277
3278     if ( IC_TRUE(ifx) )
3279         pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3280     else
3281         pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3282
3283 }
3284 #endif
3285
3286 #if 0
3287 /*-----------------------------------------------------------------*/
3288 /* genSkipCond                                                     */
3289 /*-----------------------------------------------------------------*/
3290 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3291 {
3292     FENTRY;
3293     if(!rifx)
3294         return;
3295
3296     if(rifx->condition)
3297         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3298     else
3299         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3300
3301
3302     emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3303     rifx->generated = 1;
3304 }
3305 #endif
3306
3307 #if 0
3308 /*-----------------------------------------------------------------*/
3309 /* genChkZeroes :- greater or less than comparison                 */
3310 /*     For each byte in a literal that is zero, inclusive or the   */
3311 /*     the corresponding byte in the operand with W                */
3312 /*     returns true if any of the bytes are zero                   */
3313 /*-----------------------------------------------------------------*/
3314 static int genChkZeroes(operand *op, int lit,  int size)
3315 {
3316
3317     int i;
3318     int flag =1;
3319
3320     while(size--) {
3321         i = (lit >> (size*8)) & 0xff;
3322
3323         if(i==0) {
3324             if(flag)
3325                 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3326             else
3327                 emitpcode(POC_IORFW, popGet(AOP(op),size));
3328             flag = 0;
3329         }
3330     }
3331
3332     return (flag==0);
3333 }
3334 #endif
3335
3336
3337 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3338 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
3339 #define DEBUGpc           emitpComment
3340
3341 /*-----------------------------------------------------------------*/
3342 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
3343 /*                  aop (if it's NOT a literal) or from lit (if    */
3344 /*                  aop is a literal)                              */
3345 /*-----------------------------------------------------------------*/
3346 static void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset)
3347 {
3348   if (aop->type == AOP_LIT) {
3349     emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3350   } else {
3351     emitpcode (POC_MOVFW, popGet (aop, offset));
3352   }
3353 }
3354
3355 /* genCmp performs a left < right comparison, stores
3356  * the outcome in result (if != NULL) and generates
3357  * control flow code for the ifx (if != NULL).
3358  *
3359  * This version leaves in sequences like
3360  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3361  * which should be optmized by the peephole
3362  * optimizer - RN 2005-01-01 */
3363 static void genCmp (operand *left,operand *right,
3364                     operand *result, iCode *ifx, int sign)
3365 {
3366   resolvedIfx rIfx;
3367   int size;
3368   int offs;
3369   symbol *templbl;
3370   operand *dummy;
3371   unsigned long lit;
3372   unsigned long mask;
3373   int performedLt;
3374   int invert_result = 0;
3375
3376   FENTRY;
3377
3378   assert (AOP_SIZE(left) == AOP_SIZE(right));
3379   assert (left && right);
3380
3381   size = AOP_SIZE(right) - 1;
3382   mask = (0x100UL << (size*8)) - 1;
3383   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3384   performedLt = 1;
3385   templbl = NULL;
3386   lit = 0;
3387
3388   resolveIfx (&rIfx, ifx);
3389
3390   /**********************************************************************
3391    * handle bits - bit compares are promoted to int compares seemingly! *
3392    **********************************************************************/
3393 #if 0
3394   // THIS IS COMPLETELY UNTESTED!
3395   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3396     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3397     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3398     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3399
3400     emitSETC;
3401     // 1 < {0,1} is false --> clear C by skipping the next instruction
3402     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3403     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3404     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3405     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3406     emitCLRC; // only skipped for left=0 && right=1
3407
3408     goto correct_result_in_carry;
3409   } // if
3410 #endif
3411
3412   /*************************************************
3413    * make sure that left is register (or the like) *
3414    *************************************************/
3415   if (!isAOP_REGlike(left)) {
3416     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3417     assert (isAOP_LIT(left));
3418     assert (isAOP_REGlike(right));
3419     // swap left and right
3420     // left < right <==> right > left <==> (right >= left + 1)
3421     lit = ulFromVal(AOP(left)->aopu.aop_lit);
3422
3423     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
3424       // MAXVALUE < right? always false
3425       if (performedLt) emitCLRC; else emitSETC;
3426       goto correct_result_in_carry;
3427     } // if
3428
3429     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
3430     // that's why we handled it above.
3431     lit++;
3432
3433     dummy = left;
3434     left = right;
3435     right = dummy;
3436
3437     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
3438   } else if (isAOP_LIT(right)) {
3439     lit = ulFromVal(AOP(right)->aopu.aop_lit);
3440   } // if
3441
3442   assert (isAOP_REGlike(left)); // left must be register or the like
3443   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
3444
3445   /*************************************************
3446    * special cases go here                         *
3447    *************************************************/
3448
3449   if (isAOP_LIT(right)) {
3450     if (!sign) {
3451       // unsigned comparison to a literal
3452       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
3453       if (lit == 0) {
3454     // unsigned left < 0? always false
3455     if (performedLt) emitCLRC; else emitSETC;
3456     goto correct_result_in_carry;
3457       }
3458     } else {
3459       // signed comparison to a literal
3460       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
3461       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
3462     // signed left < 0x80000000? always false
3463     if (performedLt) emitCLRC; else emitSETC;
3464     goto correct_result_in_carry;
3465       } else if (lit == 0) {
3466     // compare left < 0; set CARRY if SIGNBIT(left) is set
3467     if (performedLt) emitSETC; else emitCLRC;
3468     emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
3469     if (performedLt) emitCLRC; else emitSETC;
3470     goto correct_result_in_carry;
3471       }
3472     } // if (!sign)
3473   } // right is literal
3474
3475   /*************************************************
3476    * perform a general case comparison             *
3477    * make sure we get CARRY==1 <==> left >= right  *
3478    *************************************************/
3479   // compare most significant bytes
3480   //DEBUGpc ("comparing bytes at offset %d", size);
3481   if (!sign) {
3482     // unsigned comparison
3483     pic14_mov2w_regOrLit (AOP(right), lit, size);
3484     emitpcode (POC_SUBFW, popGet (AOP(left), size));
3485   } else {
3486     // signed comparison
3487     // (add 2^n to both operands then perform an unsigned comparison)
3488     if (isAOP_LIT(right)) {
3489       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
3490       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
3491
3492       if (litbyte == 0x80) {
3493     // left >= 0x80 -- always true, but more bytes to come
3494     mov2w (AOP(left), size);
3495     emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
3496     emitSETC;
3497       } else {
3498     // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
3499     mov2w (AOP(left), size);
3500     emitpcode (POC_ADDLW, popGetLit (0x80));
3501     emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
3502       } // if
3503     } else {
3504       pCodeOp *pctemp = popGetTempReg();
3505       mov2w (AOP(left), size);
3506       emitpcode (POC_ADDLW, popGetLit (0x80));
3507       emitpcode (POC_MOVWF, pctemp);
3508       mov2w (AOP(right), size);
3509       emitpcode (POC_ADDLW, popGetLit (0x80));
3510       emitpcode (POC_SUBFW, pctemp);
3511       popReleaseTempReg(pctemp);
3512     }
3513   } // if (!sign)
3514
3515   // compare remaining bytes (treat as unsigned case from above)
3516   templbl = newiTempLabel ( NULL );
3517   offs = size;
3518   while (offs--) {
3519     //DEBUGpc ("comparing bytes at offset %d", offs);
3520     emitSKPZ;
3521     emitpcode (POC_GOTO, popGetLabel (templbl->key));
3522     pic14_mov2w_regOrLit (AOP(right), lit, offs);
3523     emitpcode (POC_SUBFW, popGet (AOP(left), offs));
3524   } // while (offs)
3525   emitpLabel (templbl->key);
3526   goto result_in_carry;
3527
3528 result_in_carry:
3529
3530   /****************************************************
3531    * now CARRY contains the result of the comparison: *
3532    * SUBWF sets CARRY iff                             *
3533    * F-W >= 0 <==> F >= W <==> !(F < W)               *
3534    * (F=left, W=right)                                *
3535    ****************************************************/
3536
3537   if (performedLt) {
3538     invert_result = 1;
3539     // value will be used in the following genSkipc()
3540     rIfx.condition ^= 1;
3541   } // if
3542
3543 correct_result_in_carry:
3544
3545   // assign result to variable (if neccessary)
3546   if (result && AOP_TYPE(result) != AOP_CRY) {
3547     //DEBUGpc ("assign result");
3548     size = AOP_SIZE(result);
3549     while (size--) {
3550       emitpcode (POC_CLRF, popGet (AOP(result), size));
3551     } // while
3552     if (invert_result) {
3553       emitSKPC;
3554       emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
3555     } else {
3556       emitpcode (POC_RLF, popGet (AOP(result), 0));
3557     }
3558   } // if (result)
3559
3560   // perform conditional jump
3561   if (ifx) {
3562     //DEBUGpc ("generate control flow");
3563     genSkipc (&rIfx);
3564     ifx->generated = 1;
3565   } // if
3566 }
3567
3568
3569 #if 0
3570 /* OLD VERSION -- BUGGY, DO NOT USE */
3571
3572 /*-----------------------------------------------------------------*/
3573 /* genCmp :- greater or less than comparison                       */
3574 /*-----------------------------------------------------------------*/
3575 static void genCmp (operand *left,operand *right,
3576                     operand *result, iCode *ifx, int sign)
3577 {
3578     int size; //, offset = 0 ;
3579     unsigned long lit = 0L,i = 0;
3580     resolvedIfx rFalseIfx;
3581     //  resolvedIfx rTrueIfx;
3582     symbol *truelbl;
3583
3584     FENTRY;
3585     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3586     /*
3587     if(ifx) {
3588     DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3589     DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3590     }
3591     */
3592
3593     resolveIfx(&rFalseIfx,ifx);
3594     truelbl  = newiTempLabel(NULL);
3595     size = max(AOP_SIZE(left),AOP_SIZE(right));
3596
3597     DEBUGpic14_AopType(__LINE__,left,right,result);
3598
3599 #define _swapp
3600
3601     /* if literal is on the right then swap with left */
3602     if ((AOP_TYPE(right) == AOP_LIT)) {
3603         operand *tmp = right ;
3604         unsigned long mask = (0x100 << (8*(size-1))) - 1;
3605         lit = ulFromVal(AOP(right)->aopu.aop_lit);
3606 #ifdef _swapp
3607
3608         lit = (lit - 1) & mask;
3609         right = left;
3610         left = tmp;
3611         rFalseIfx.condition ^= 1;
3612 #endif
3613
3614     } else if ((AOP_TYPE(left) == AOP_LIT)) {
3615         lit = ulFromVal(AOP(left)->aopu.aop_lit);
3616     }
3617
3618
3619     //if(IC_TRUE(ifx) == NULL)
3620     /* if left & right are bit variables */
3621     if (AOP_TYPE(left) == AOP_CRY &&
3622         AOP_TYPE(right) == AOP_CRY ) {
3623         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3624         pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3625     } else {
3626     /* subtract right from left if at the
3627     end the carry flag is set then we know that
3628         left is greater than right */
3629
3630         symbol *lbl  = newiTempLabel(NULL);
3631
3632 #ifndef _swapp
3633         if(AOP_TYPE(right) == AOP_LIT) {
3634
3635             //lit = ulFromVal(AOP(right)->aopu.aop_lit);
3636
3637             DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3638
3639             /* special cases */
3640
3641             if(lit == 0) {
3642
3643                 if(sign != 0)
3644                     genSkipCond(&rFalseIfx,left,size-1,7);
3645                 else
3646                     /* no need to compare to 0...*/
3647                     /* NOTE: this is a de-generate compare that most certainly
3648                     *       creates some dead code. */
3649                     emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3650
3651                 if(ifx) ifx->generated = 1;
3652                 return;
3653
3654             }
3655             size--;
3656
3657             if(size == 0) {
3658                 //i = (lit >> (size*8)) & 0xff;
3659                 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3660
3661                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3662
3663                 i = ((0-lit) & 0xff);
3664                 if(sign) {
3665                     if( i == 0x81) {
3666                     /* lit is 0x7f, all signed chars are less than
3667                         * this except for 0x7f itself */
3668                         emitpcode(POC_XORLW, popGetLit(0x7f));
3669                         genSkipz2(&rFalseIfx,0);
3670                     } else {
3671                         emitpcode(POC_ADDLW, popGetLit(0x80));
3672                         emitpcode(POC_ADDLW, popGetLit(i^0x80));
3673                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3674                     }
3675
3676                 } else {
3677                     if(lit == 1) {
3678                         genSkipz2(&rFalseIfx,1);
3679                     } else {
3680                         emitpcode(POC_ADDLW, popGetLit(i));
3681                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3682                     }
3683                 }
3684
3685                 if(ifx) ifx->generated = 1;
3686                 return;
3687             }
3688
3689             /* chars are out of the way. now do ints and longs */
3690
3691
3692             DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3693
3694             /* special cases */
3695
3696             if(sign) {
3697
3698                 if(lit == 0) {
3699                     genSkipCond(&rFalseIfx,left,size,7);
3700                     if(ifx) ifx->generated = 1;
3701                     return;
3702                 }
3703
3704                 if(lit <0x100) {
3705                     DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3706
3707                     //rFalseIfx.condition ^= 1;
3708                     //genSkipCond(&rFalseIfx,left,size,7);
3709                     //rFalseIfx.condition ^= 1;
3710
3711                     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3712                     if(rFalseIfx.condition)
3713                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3714                     else
3715                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3716
3717                     emitpcode(POC_MOVLW, popGetLit(0x100-lit));
3718                     emitpcode(POC_ADDFW, popGet(AOP(left),0));
3719                     emitpcode(POC_MOVFW, popGet(AOP(left),1));
3720
3721                     while(size > 1)
3722                         emitpcode(POC_IORFW, popGet(AOP(left),size--));
3723
3724                     if(rFalseIfx.condition) {
3725                         emitSKPZ;
3726                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3727
3728                     } else {
3729                         emitSKPNZ;
3730                     }
3731
3732                     genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3733                     emitpLabel(truelbl->key);
3734                     if(ifx) ifx->generated = 1;
3735                     return;
3736
3737                 }
3738
3739                 if(size == 1) {
3740
3741                     if( (lit & 0xff) == 0) {
3742                         /* lower byte is zero */
3743                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3744                         i = ((lit >> 8) & 0xff) ^0x80;
3745                         emitpcode(POC_MOVFW, popGet(AOP(left),size));
3746                         emitpcode(POC_ADDLW, popGetLit( 0x80));
3747                         emitpcode(POC_ADDLW, popGetLit(0x100-i));
3748                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3749
3750
3751                         if(ifx) ifx->generated = 1;
3752                         return;
3753
3754                     }
3755                 } else {
3756                     /* Special cases for signed longs */
3757                     if( (lit & 0xffffff) == 0) {
3758                         /* lower byte is zero */
3759                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3760                         i = ((lit >> 8*3) & 0xff) ^0x80;
3761                         emitpcode(POC_MOVFW, popGet(AOP(left),size));
3762                         emitpcode(POC_ADDLW, popGetLit( 0x80));
3763                         emitpcode(POC_ADDLW, popGetLit(0x100-i));
3764                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3765
3766
3767                         if(ifx) ifx->generated = 1;
3768                         return;
3769
3770                     }
3771
3772                 }
3773
3774
3775                 if(lit & (0x80 << (size*8))) {
3776                     /* lit is negative */
3777                     DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3778
3779                     //genSkipCond(&rFalseIfx,left,size,7);
3780
3781                     emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3782
3783                     if(rFalseIfx.condition)
3784                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3785                     else
3786                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3787
3788
3789                 } else {
3790                     /* lit is positive */
3791                     DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3792                     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3793                     if(rFalseIfx.condition)
3794                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3795                     else
3796                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3797
3798                 }
3799
3800                 /* There are no more special cases, so perform a general compare */
3801
3802                 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3803                 emitpcode(POC_SUBFW, popGet(AOP(left),size));
3804
3805                 while(size--) {
3806
3807                     emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3808                     emitSKPNZ;
3809                     emitpcode(POC_SUBFW, popGet(AOP(left),size));
3810                 }
3811                 //rFalseIfx.condition ^= 1;
3812                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3813
3814                 emitpLabel(truelbl->key);
3815
3816                 if(ifx) ifx->generated = 1;
3817                 return;
3818
3819
3820             }
3821
3822
3823             /* sign is out of the way. So now do an unsigned compare */
3824             DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
3825
3826
3827             /* General case - compare to an unsigned literal on the right.*/
3828
3829             i = (lit >> (size*8)) & 0xff;
3830             emitpcode(POC_MOVLW, popGetLit(i));
3831             emitpcode(POC_SUBFW, popGet(AOP(left),size));
3832             while(size--) {
3833                 i = (lit >> (size*8)) & 0xff;
3834
3835                 if(i) {
3836                     emitpcode(POC_MOVLW, popGetLit(i));
3837                     emitSKPNZ;
3838                     emitpcode(POC_SUBFW, popGet(AOP(left),size));
3839                 } else {
3840                 /* this byte of the lit is zero,
3841                     *if it's not the last then OR in the variable */
3842                     if(size)
3843                         emitpcode(POC_IORFW, popGet(AOP(left),size));
3844                 }
3845             }
3846
3847
3848         emitpLabel(lbl->key);
3849         //if(emitFinalCheck)
3850         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3851         if(sign)
3852             emitpLabel(truelbl->key);
3853
3854         if(ifx) ifx->generated = 1;
3855         return;
3856
3857
3858         }
3859 #endif  // _swapp
3860
3861         if(AOP_TYPE(left) == AOP_LIT) {
3862             //symbol *lbl = newiTempLabel(NULL);
3863
3864             //EXPERIMENTAL lit = ulFromVal(AOP(left)->aopu.aop_lit);
3865
3866
3867             DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
3868
3869             /* Special cases */
3870             if((lit == 0) && (sign == 0)){
3871
3872                 size--;
3873                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
3874                 while(size)
3875                     emitpcode(POC_IORFW, popGet(AOP(right),--size));
3876
3877                 genSkipz2(&rFalseIfx,0);
3878                 if(ifx) ifx->generated = 1;
3879                 return;
3880             }
3881
3882             if(size==1) {
3883                 /* Special cases */
3884                 lit &= 0xff;
3885                 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
3886                     /* degenerate compare can never be true */
3887                     if(rFalseIfx.condition == 0)
3888                         emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3889
3890                     if(ifx) ifx->generated = 1;
3891                     return;
3892                 }
3893
3894                 if(sign) {
3895                     /* signed comparisons to a literal byte */
3896
3897                     int lp1 = (lit+1) & 0xff;
3898
3899                     DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
3900                     switch (lp1) {
3901                     case 0:
3902                         rFalseIfx.condition ^= 1;
3903                         genSkipCond(&rFalseIfx,right,0,7);
3904                         break;
3905                     case 0x7f:
3906                         emitpcode(POC_MOVFW, popGet(AOP(right),0));
3907                         emitpcode(POC_XORLW, popGetLit(0x7f));
3908                         genSkipz2(&rFalseIfx,1);
3909                         break;
3910                     default:
3911                         emitpcode(POC_MOVFW, popGet(AOP(right),0));
3912                         emitpcode(POC_ADDLW, popGetLit(0x80));
3913                         emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
3914                         rFalseIfx.condition ^= 1;
3915                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3916                         break;
3917                     }
3918                     if(ifx) ifx->generated = 1;
3919                 } else {
3920                     /* unsigned comparisons to a literal byte */
3921
3922                     switch(lit & 0xff ) {
3923                     case 0:
3924                         emitpcode(POC_MOVFW, popGet(AOP(right),0));
3925                         genSkipz2(&rFalseIfx,0);
3926                         if(ifx) ifx->generated = 1;
3927                         break;
3928                     case 0x7f:
3929                         genSkipCond(&rFalseIfx,right,0,7);
3930                         if(ifx) ifx->generated = 1;
3931                         break;
3932
3933                     default:
3934                         emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
3935                         emitpcode(POC_SUBFW, popGet(AOP(right),0));
3936                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3937                         rFalseIfx.condition ^= 1;
3938                         if (AOP_TYPE(result) == AOP_CRY) {
3939                             genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
3940                             if(ifx) ifx->generated = 1;
3941                         } else {
3942                             DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
3943                             emitpcode(POC_CLRF, popGet(AOP(result),0));
3944                             emitpcode(POC_RLF, popGet(AOP(result),0));
3945                             emitpcode(POC_MOVLW, popGetLit(0x01));
3946                             emitpcode(POC_XORWF, popGet(AOP(result),0));
3947                         }
3948                         break;
3949                     }
3950                 }
3951
3952                 //goto check_carry;
3953                 return;
3954
3955             } else {
3956
3957                 /* Size is greater than 1 */
3958
3959                 if(sign) {
3960                     int lp1 = lit+1;
3961
3962                     size--;
3963
3964                     if(lp1 == 0) {
3965                         /* this means lit = 0xffffffff, or -1 */
3966
3967
3968                         DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
3969                         rFalseIfx.condition ^= 1;
3970                         genSkipCond(&rFalseIfx,right,size,7);
3971                         if(ifx) ifx->generated = 1;
3972                         return;
3973                     }
3974
3975                     if(lit == 0) {
3976                         int s = size;
3977
3978                         if(rFalseIfx.condition) {
3979                             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
3980                             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3981                         }
3982
3983                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
3984                         while(size--)
3985                             emitpcode(POC_IORFW, popGet(AOP(right),size));
3986
3987
3988                         emitSKPZ;
3989                         if(rFalseIfx.condition) {
3990                             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3991                             emitpLabel(truelbl->key);
3992                         }else {
3993                             rFalseIfx.condition ^= 1;
3994                             genSkipCond(&rFalseIfx,right,s,7);
3995                         }
3996
3997                         if(ifx) ifx->generated = 1;
3998                         return;
3999                     }
4000
4001                     if((size == 1) &&  (0 == (lp1&0xff))) {
4002                         /* lower byte of signed word is zero */
4003                         DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4004                         i = ((lp1 >> 8) & 0xff) ^0x80;
4005                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4006                         emitpcode(POC_ADDLW, popGetLit( 0x80));
4007                         emitpcode(POC_ADDLW, popGetLit(0x100-i));
4008                         rFalseIfx.condition ^= 1;
4009                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4010
4011
4012                         if(ifx) ifx->generated = 1;
4013                         return;
4014                     }
4015
4016                     if(lit & (0x80 << (size*8))) {
4017                         /* Lit is less than zero */
4018                         DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4019                         //rFalseIfx.condition ^= 1;
4020                         //genSkipCond(&rFalseIfx,left,size,7);
4021                         //rFalseIfx.condition ^= 1;
4022                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4023                         //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4024
4025                         if(rFalseIfx.condition)
4026                             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4027                         else
4028                             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4029
4030
4031                     } else {
4032                         /* Lit is greater than or equal to zero */
4033                         DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4034                         //rFalseIfx.condition ^= 1;
4035                         //genSkipCond(&rFalseIfx,right,size,7);
4036                         //rFalseIfx.condition ^= 1;
4037
4038                         //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4039                         //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4040
4041                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4042                         if(rFalseIfx.condition)
4043                             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4044                         else
4045                             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4046
4047                     }
4048
4049
4050                     emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4051                     emitpcode(POC_SUBFW, popGet(AOP(right),size));
4052
4053                     while(size--) {
4054
4055                         emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4056                         emitSKPNZ;
4057                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4058                     }
4059                     rFalseIfx.condition ^= 1;
4060                     //rFalseIfx.condition = 1;
4061                     genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4062
4063                     emitpLabel(truelbl->key);
4064
4065                     if(ifx) ifx->generated = 1;
4066                     return;
4067                     // end of if (sign)
4068                 } else {
4069
4070                     /* compare word or long to an unsigned literal on the right.*/
4071
4072
4073                     size--;
4074                     if(lit < 0xff) {
4075                         DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4076                         switch (lit) {
4077                         case 0:
4078                             break; /* handled above */
4079                         /*
4080                         case 0xff:
4081                             emitpcode(POC_MOVFW, popGet(AOP(right),size));
4082                             while(size--)
4083                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4084                             genSkipz2(&rFalseIfx,0);
4085                             break;
4086                         */
4087                         default:
4088                             emitpcode(POC_MOVFW, popGet(AOP(right),size));
4089                             while(--size)
4090                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4091
4092                             emitSKPZ;
4093                             if(rFalseIfx.condition)
4094                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4095                             else
4096                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4097
4098
4099                             emitpcode(POC_MOVLW, popGetLit(lit+1));
4100                             emitpcode(POC_SUBFW, popGet(AOP(right),0));
4101
4102                             rFalseIfx.condition ^= 1;
4103                             genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4104                         }
4105
4106                         emitpLabel(truelbl->key);
4107
4108                         if(ifx) ifx->generated = 1;
4109                         return;
4110                     }
4111
4112
4113                     lit++;
4114                     DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4115                     i = (lit >> (size*8)) & 0xff;
4116
4117                     emitpcode(POC_MOVLW, popGetLit(i));
4118                     emitpcode(POC_SUBFW, popGet(AOP(right),size));
4119
4120                     while(size--) {
4121                         i = (lit >> (size*8)) & 0xff;
4122
4123                         if(i) {
4124                             emitpcode(POC_MOVLW, popGetLit(i));
4125                             emitSKPNZ;
4126                             emitpcode(POC_SUBFW, popGet(AOP(right),size));
4127                         } else {
4128                         /* this byte of the lit is zero,
4129                             *if it's not the last then OR in the variable */
4130                             if(size)
4131                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4132                         }
4133                     }
4134
4135
4136                     emitpLabel(lbl->key);
4137
4138                     rFalseIfx.condition ^= 1;
4139                     genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4140                 }
4141
4142                 if(sign)
4143                     emitpLabel(truelbl->key);
4144                 if(ifx) ifx->generated = 1;
4145                 return;
4146             }
4147         }
4148         /* Compare two variables */
4149
4150         DEBUGpic14_emitcode(";sign","%d",sign);
4151
4152         size--;
4153         if(sign) {
4154             /* Sigh. thus sucks... */
4155             if(size) {
4156                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4157                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4158                 emitpcode(POC_MOVLW, popGetLit(0x80));
4159                 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4160                 emitpcode(POC_XORFW, popGet(AOP(right),size));
4161                 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4162             } else {
4163                 /* Signed char comparison */
4164                 /* Special thanks to Nikolai Golovchenko for this snippet */
4165                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4166                 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4167                 emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4168                 emitpcode(POC_XORFW, popGet(AOP(left),0));
4169                 emitpcode(POC_XORFW, popGet(AOP(right),0));
4170                 emitpcode(POC_ADDLW, popGetLit(0x80));
4171
4172                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4173                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4174
4175                 if(ifx) ifx->generated = 1;
4176                 return;
4177             }
4178
4179         } else {
4180
4181             emitpcode(POC_MOVFW, popGet(AOP(right),size));
4182             emitpcode(POC_SUBFW, popGet(AOP(left),size));
4183         }
4184
4185
4186         /* The rest of the bytes of a multi-byte compare */
4187         while (size) {
4188
4189             emitSKPZ;
4190             emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4191             size--;
4192
4193             emitpcode(POC_MOVFW, popGet(AOP(right),size));
4194             emitpcode(POC_SUBFW, popGet(AOP(left),size));
4195
4196
4197         }
4198
4199         emitpLabel(lbl->key);
4200
4201         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4202         if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
4203             (AOP_TYPE(result) == AOP_REG)) {
4204             emitpcode(POC_CLRF, popGet(AOP(result),0));
4205             emitpcode(POC_RLF, popGet(AOP(result),0));
4206         } else {
4207             genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4208         }
4209         //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4210         if(ifx) ifx->generated = 1;
4211
4212         return;
4213
4214     }
4215
4216     // check_carry:
4217     if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4218         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4219         pic14_outBitC(result);
4220     } else {
4221         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4222         /* if the result is used in the next
4223         ifx conditional branch then generate
4224         code a little differently */
4225         if (ifx )
4226             genIfxJump (ifx,"c");
4227         else
4228             pic14_outBitC(result);
4229         /* leave the result in acc */
4230     }
4231
4232 }
4233 #endif
4234
4235 /*-----------------------------------------------------------------*/
4236 /* genCmpGt :- greater than comparison                             */
4237 /*-----------------------------------------------------------------*/
4238 static void genCmpGt (iCode *ic, iCode *ifx)
4239 {
4240     operand *left, *right, *result;
4241     sym_link *letype , *retype;
4242     int sign ;
4243
4244     FENTRY;
4245     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4246     left = IC_LEFT(ic);
4247     right= IC_RIGHT(ic);
4248     result = IC_RESULT(ic);
4249
4250     letype = getSpec(operandType(left));
4251     retype =getSpec(operandType(right));
4252     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4253     /* assign the amsops */
4254     aopOp (left,ic,FALSE);
4255     aopOp (right,ic,FALSE);
4256     aopOp (result,ic,TRUE);
4257
4258     genCmp(right, left, result, ifx, sign);
4259
4260     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4261     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4262     freeAsmop(result,NULL,ic,TRUE);
4263 }
4264
4265 /*-----------------------------------------------------------------*/
4266 /* genCmpLt - less than comparisons                                */
4267 /*-----------------------------------------------------------------*/
4268 static void genCmpLt (iCode *ic, iCode *ifx)
4269 {
4270     operand *left, *right, *result;
4271     sym_link *letype , *retype;
4272     int sign ;
4273
4274     FENTRY;
4275     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4276     left = IC_LEFT(ic);
4277     right= IC_RIGHT(ic);
4278     result = IC_RESULT(ic);
4279
4280     letype = getSpec(operandType(left));
4281     retype =getSpec(operandType(right));
4282     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4283
4284     /* assign the amsops */
4285     aopOp (left,ic,FALSE);
4286     aopOp (right,ic,FALSE);
4287     aopOp (result,ic,TRUE);
4288
4289     genCmp(left, right, result, ifx, sign);
4290
4291     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4292     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4293     freeAsmop(result,NULL,ic,TRUE);
4294 }
4295
4296 /*-----------------------------------------------------------------*/
4297 /* genCmpEq - generates code for equal to                          */
4298 /*-----------------------------------------------------------------*/
4299 static void genCmpEq (iCode *ic, iCode *ifx)
4300 {
4301   operand *left, *right, *result;
4302   int size;
4303   symbol *false_label;
4304
4305   FENTRY;
4306   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4307
4308   if(ifx)
4309     DEBUGpic14_emitcode ("; ifx is non-null","");
4310   else
4311     DEBUGpic14_emitcode ("; ifx is null","");
4312
4313   aopOp((left=IC_LEFT(ic)),ic,FALSE);
4314   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4315   aopOp((result=IC_RESULT(ic)),ic,TRUE);
4316
4317   DEBUGpic14_AopType(__LINE__,left,right,result);
4318
4319   /* if literal, move literal to right */
4320   if (op_isLitLike (IC_LEFT(ic))) {
4321     operand *tmp = right ;
4322     right = left;
4323     left = tmp;
4324   }
4325
4326   false_label = NULL;
4327   if (ifx && !IC_TRUE(ifx))
4328   {
4329     assert (IC_FALSE(ifx));
4330     false_label = IC_FALSE(ifx);
4331   }
4332
4333   size = min(AOP_SIZE(left),AOP_SIZE(right));
4334   assert(!pic14_sameRegs(AOP(result),AOP(left)));
4335   assert(!pic14_sameRegs(AOP(result),AOP(right)));
4336
4337   /* assume left != right */
4338   {
4339     int i;
4340     for (i=0; i < AOP_SIZE(result); i++)
4341     {
4342       emitpcode(POC_CLRF, popGet(AOP(result),i));
4343     }
4344   }
4345
4346   if (AOP_TYPE(right) == AOP_LIT)
4347   {
4348     unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
4349     int i;
4350     size = AOP_SIZE(left);
4351     assert(!op_isLitLike(left));
4352
4353     switch (lit)
4354     {
4355       case 0:
4356         mov2w(AOP(left), 0);
4357     for (i=1; i < size; i++)
4358       emitpcode(POC_IORFW,popGet(AOP(left),i));
4359     /* now Z is set iff `left == right' */
4360     emitSKPZ;
4361     if (!false_label) false_label = newiTempLabel(NULL);
4362     emitpcode(POC_GOTO, popGetLabel(false_label->key));
4363     break;
4364
4365       default:
4366     for (i=0; i < size; i++)
4367     {
4368       mov2w(AOP(left),i);
4369       emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
4370       /* now Z is cleared if `left != right' */
4371       emitSKPZ;
4372       if (!false_label) false_label = newiTempLabel(NULL);
4373       emitpcode(POC_GOTO, popGetLabel(false_label->key));
4374     } // for i
4375     break;
4376     } // switch (lit)
4377   }
4378   else
4379   {
4380     /* right is no literal */
4381     int i;
4382
4383     for (i=0; i < size; i++)
4384     {
4385       mov2w(AOP(right),i);
4386       emitpcode(POC_XORFW,popGet(AOP(left),i));
4387       /* now Z is cleared if `left != right' */
4388       emitSKPZ;
4389       if (!false_label) false_label = newiTempLabel(NULL);
4390       emitpcode(POC_GOTO, popGetLabel(false_label->key));
4391     } // for i
4392   }
4393
4394   /* if we reach here, left == right */
4395
4396   if (AOP_SIZE(result) > 0)
4397   {
4398     emitpcode(POC_INCF, popGet(AOP(result),0));
4399   }
4400
4401   if (ifx && IC_TRUE(ifx))
4402   {
4403     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4404   }
4405
4406   if (false_label && (!ifx || IC_TRUE(ifx)))
4407     emitpLabel(false_label->key);
4408
4409   if (ifx) ifx->generated = 1;
4410
4411   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4412   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4413   freeAsmop(result,NULL,ic,TRUE);
4414 }
4415
4416 /*-----------------------------------------------------------------*/
4417 /* ifxForOp - returns the icode containing the ifx for operand     */
4418 /*-----------------------------------------------------------------*/
4419 static iCode *ifxForOp ( operand *op, iCode *ic )
4420 {
4421     FENTRY;
4422     /* if true symbol then needs to be assigned */
4423     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4424     if (IS_TRUE_SYMOP(op))
4425         return NULL ;
4426
4427     /* if this has register type condition and
4428     the next instruction is ifx with the same operand
4429     and live to of the operand is upto the ifx only then */
4430     if (ic->next &&
4431         ic->next->op == IFX &&
4432         IC_COND(ic->next)->key == op->key &&
4433         OP_SYMBOL(op)->liveTo <= ic->next->seq )
4434         return ic->next;
4435
4436     if (ic->next &&
4437         ic->next->op == IFX &&
4438         IC_COND(ic->next)->key == op->key) {
4439         DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
4440         return ic->next;
4441     }
4442
4443     DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
4444     if (ic->next &&
4445         ic->next->op == IFX)
4446         DEBUGpic14_emitcode ("; ic-next"," is an IFX");
4447
4448     if (ic->next &&
4449         ic->next->op == IFX &&
4450         IC_COND(ic->next)->key == op->key) {
4451         DEBUGpic14_emitcode ("; "," key is okay");
4452         DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
4453             OP_SYMBOL(op)->liveTo,
4454             ic->next->seq);
4455     }
4456
4457
4458     return NULL;
4459 }
4460 /*-----------------------------------------------------------------*/
4461 /* genAndOp - for && operation                                     */
4462 /*-----------------------------------------------------------------*/
4463 static void genAndOp (iCode *ic)
4464 {
4465     operand *left,*right, *result;
4466     /*     symbol *tlbl; */
4467
4468     FENTRY;
4469     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4470     /* note here that && operations that are in an
4471     if statement are taken away by backPatchLabels
4472     only those used in arthmetic operations remain */
4473     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4474     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4475     aopOp((result=IC_RESULT(ic)),ic,FALSE);
4476
4477     DEBUGpic14_AopType(__LINE__,left,right,result);
4478
4479     emitpcode(POC_MOVFW,popGet(AOP(left),0));
4480     emitpcode(POC_ANDFW,popGet(AOP(right),0));
4481     emitpcode(POC_MOVWF,popGet(AOP(result),0));
4482
4483     /* if both are bit variables */
4484     /*     if (AOP_TYPE(left) == AOP_CRY && */
4485     /*         AOP_TYPE(right) == AOP_CRY ) { */
4486     /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
4487     /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
4488     /*         pic14_outBitC(result); */
4489     /*     } else { */
4490     /*         tlbl = newiTempLabel(NULL); */
4491     /*         pic14_toBoolean(left);     */
4492     /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
4493     /*         pic14_toBoolean(right); */
4494     /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
4495     /*         pic14_outBitAcc(result); */
4496     /*     } */
4497
4498     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4499     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4500     freeAsmop(result,NULL,ic,TRUE);
4501 }
4502
4503
4504 /*-----------------------------------------------------------------*/
4505 /* genOrOp - for || operation                                      */
4506 /*-----------------------------------------------------------------*/
4507 /*
4508 tsd pic port -
4509 modified this code, but it doesn't appear to ever get called
4510 */
4511
4512 static void genOrOp (iCode *ic)
4513 {
4514     operand *left,*right, *result;
4515     symbol *tlbl;
4516     int i;
4517
4518     /* note here that || operations that are in an
4519     if statement are taken away by backPatchLabels
4520     only those used in arthmetic operations remain */
4521     FENTRY;
4522     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4523     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4524     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4525     aopOp((result=IC_RESULT(ic)),ic,FALSE);
4526
4527     DEBUGpic14_AopType(__LINE__,left,right,result);
4528
4529     for (i=0; i < AOP_SIZE(result); i++)
4530     {
4531         emitpcode(POC_CLRF, popGet(AOP(result), i));
4532     } // for i
4533
4534     tlbl = newiTempLabel(NULL);
4535     pic14_toBoolean(left);
4536     emitSKPZ;
4537     emitpcode(POC_GOTO, popGetLabel(tlbl->key));
4538     pic14_toBoolean(right);
4539     emitpLabel(tlbl->key);
4540     /* here Z is clear IFF `left || right' */
4541     emitSKPZ;
4542     emitpcode(POC_INCF, popGet(AOP(result), 0));
4543
4544     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4545     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4546     freeAsmop(result,NULL,ic,TRUE);
4547 }
4548
4549 /*-----------------------------------------------------------------*/
4550 /* isLiteralBit - test if lit == 2^n                               */
4551 /*-----------------------------------------------------------------*/
4552 static int isLiteralBit(unsigned long lit)
4553 {
4554     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4555         0x100L,0x200L,0x400L,0x800L,
4556         0x1000L,0x2000L,0x4000L,0x8000L,
4557         0x10000L,0x20000L,0x40000L,0x80000L,
4558         0x100000L,0x200000L,0x400000L,0x800000L,
4559         0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4560         0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4561     int idx;
4562
4563     FENTRY;
4564     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4565     for(idx = 0; idx < 32; idx++)
4566         if(lit == pw[idx])
4567             return idx+1;
4568         return 0;
4569 }
4570
4571 /*-----------------------------------------------------------------*/
4572 /* continueIfTrue -                                                */
4573 /*-----------------------------------------------------------------*/
4574 static void continueIfTrue (iCode *ic)
4575 {
4576     FENTRY;
4577     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4578     if(IC_TRUE(ic))
4579     {
4580         // Why +100?!?
4581         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
4582         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4583     }
4584     ic->generated = 1;
4585 }
4586
4587 /*-----------------------------------------------------------------*/
4588 /* jmpIfTrue -                                                     */
4589 /*-----------------------------------------------------------------*/
4590 static void jumpIfTrue (iCode *ic)
4591 {
4592     FENTRY;
4593     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4594     if(!IC_TRUE(ic))
4595     {
4596         // Why +100?!?
4597         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
4598         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4599     }
4600     ic->generated = 1;
4601 }
4602
4603 /*-----------------------------------------------------------------*/
4604 /* jmpTrueOrFalse -                                                */
4605 /*-----------------------------------------------------------------*/
4606 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4607 {
4608     FENTRY;
4609     // ugly but optimized by peephole
4610     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4611     if(IC_TRUE(ic)){
4612         symbol *nlbl = newiTempLabel(NULL);
4613         pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
4614         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4615         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4616         pic14_emitcode("","%05d_DS_:",nlbl->key+100);
4617     }
4618     else{
4619         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4620         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4621     }
4622     ic->generated = 1;
4623 }
4624
4625 /*-----------------------------------------------------------------*/
4626 /* genAnd  - code for and                                          */
4627 /*-----------------------------------------------------------------*/
4628 static void genAnd (iCode *ic, iCode *ifx)
4629 {
4630     operand *left, *right, *result;
4631     int size, offset=0;
4632     unsigned long lit = 0L;
4633     int bytelit = 0;
4634     resolvedIfx rIfx;
4635
4636     FENTRY;
4637     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4638     aopOp((left = IC_LEFT(ic)),ic,FALSE);
4639     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4640     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4641
4642     resolveIfx(&rIfx,ifx);
4643
4644     /* if left is a literal & right is not then exchange them */
4645     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4646         AOP_NEEDSACC(left)) {
4647         operand *tmp = right ;
4648         right = left;
4649         left = tmp;
4650     }
4651
4652     /* if result = right then exchange them */
4653     if(pic14_sameRegs(AOP(result),AOP(right))){
4654         operand *tmp = right ;
4655         right = left;
4656         left = tmp;
4657     }
4658
4659     /* if right is bit then exchange them */
4660     if (AOP_TYPE(right) == AOP_CRY &&
4661         AOP_TYPE(left) != AOP_CRY){
4662         operand *tmp = right ;
4663         right = left;
4664         left = tmp;
4665     }
4666     if(AOP_TYPE(right) == AOP_LIT)
4667         lit = ulFromVal (AOP(right)->aopu.aop_lit);
4668
4669     size = AOP_SIZE(result);
4670
4671     DEBUGpic14_AopType(__LINE__,left,right,result);
4672
4673     // if(bit & yy)
4674     // result = bit & yy;
4675     if (AOP_TYPE(left) == AOP_CRY){
4676         // c = bit & literal;
4677         if(AOP_TYPE(right) == AOP_LIT){
4678             if(lit & 1) {
4679                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
4680                     // no change
4681                     goto release;
4682                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4683             } else {
4684                 // bit(result) = 0;
4685                 if(size && (AOP_TYPE(result) == AOP_CRY)){
4686                     pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4687                     goto release;
4688                 }
4689                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4690                     jumpIfTrue(ifx);
4691                     goto release;
4692                 }
4693                 pic14_emitcode("clr","c");
4694             }
4695         } else {
4696             if (AOP_TYPE(right) == AOP_CRY){
4697                 // c = bit & bit;
4698                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4699                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4700             } else {
4701                 // c = bit & val;
4702                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
4703                 // c = lsb
4704                 pic14_emitcode("rrc","a");
4705                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4706             }
4707         }
4708         // bit = c
4709         // val = c
4710         if(size)
4711             pic14_outBitC(result);
4712         // if(bit & ...)
4713         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4714             genIfxJump(ifx, "c");
4715         goto release ;
4716     }
4717
4718     // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
4719     // bit = val & 0xZZ     - size = 1, ifx = FALSE -
4720     if((AOP_TYPE(right) == AOP_LIT) &&
4721         (AOP_TYPE(result) == AOP_CRY) &&
4722         (AOP_TYPE(left) != AOP_CRY)){
4723         int posbit = isLiteralBit(lit);
4724         /* left &  2^n */
4725         if(posbit){
4726             posbit--;
4727             //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
4728             // bit = left & 2^n
4729             if(size)
4730                 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
4731             // if(left &  2^n)
4732             else{
4733                 if(ifx){
4734                     int offset = 0;
4735                     while (posbit > 7) {
4736                         posbit -= 8;
4737                         offset++;
4738                     }
4739                     emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
4740                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
4741                     emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4742
4743                     ifx->generated = 1;
4744                 }
4745                 goto release;
4746             }
4747         } else {
4748             symbol *tlbl = newiTempLabel(NULL);
4749             int sizel = AOP_SIZE(left);
4750             if(size)
4751                 pic14_emitcode("setb","c");
4752             while(sizel--){
4753                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4754                     mov2w( AOP(left), offset);
4755                     // byte ==  2^n ?
4756                     if((posbit = isLiteralBit(bytelit)) != 0) {
4757                         emitpcode(rIfx.condition ? POC_BTFSC : POC_BTFSS, // XXX: or the other way round?
4758                             newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit - 1, 0));
4759                         pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
4760                     }
4761                     else{
4762                         emitpcode(POC_ANDLW, newpCodeOpLit(bytelit & 0x0ff));
4763                         if (rIfx.condition) emitSKPZ;
4764                         else emitSKPNZ;
4765
4766                         if(bytelit != 0x0FFL)
4767                         {
4768                             pic14_emitcode("anl","a,%s",
4769                             aopGet(AOP(right),offset,FALSE,TRUE));
4770                         }
4771                         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
4772                     }
4773
4774                     emitpcode(POC_GOTO, popGetLabel(rIfx.lbl->key));
4775                     ifx->generated = 1;
4776
4777                 }
4778                 offset++;
4779             }
4780             // bit = left & literal
4781             if(size){
4782                 pic14_emitcode("clr","c");
4783                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4784             }
4785             // if(left & literal)
4786             else{
4787                 if(ifx)
4788                     jmpTrueOrFalse(ifx, tlbl);
4789                 goto release ;
4790             }
4791         }
4792         pic14_outBitC(result);
4793         goto release ;
4794     }
4795
4796     /* if left is same as result */
4797     if(pic14_sameRegs(AOP(result),AOP(left))){
4798         int know_W = -1;
4799         for(;size--; offset++,lit>>=8) {
4800             if(AOP_TYPE(right) == AOP_LIT){
4801                 switch(lit & 0xff) {
4802                 case 0x00:
4803                     /*  and'ing with 0 has clears the result */
4804                     emitpcode(POC_CLRF,popGet(AOP(result),offset));
4805                     break;
4806                 case 0xff:
4807                     /* and'ing with 0xff is a nop when the result and left are the same */
4808                     break;
4809
4810                 default:
4811                     {
4812                         int p = my_powof2( (~lit) & 0xff );
4813                         if(p>=0) {
4814                             /* only one bit is set in the literal, so use a bcf instruction */
4815                             emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
4816
4817                         } else {
4818                             if(know_W != (int)(lit&0xff))
4819                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
4820                             know_W = lit &0xff;
4821                             emitpcode(POC_ANDWF,popGet(AOP(left),offset));
4822                         }
4823                     }
4824                 }
4825             } else {
4826                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
4827                 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
4828             }
4829         }
4830
4831     } else {
4832         // left & result in different registers
4833         if(AOP_TYPE(result) == AOP_CRY){
4834             // result = bit
4835             // if(size), result in bit
4836             // if(!size && ifx), conditional oper: if(left & right)
4837             symbol *tlbl = newiTempLabel(NULL);
4838             int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4839             if(size)
4840                 pic14_emitcode("setb","c");
4841             while(sizer--){
4842                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4843                 pic14_emitcode("anl","a,%s",
4844                     aopGet(AOP(left),offset,FALSE,FALSE));
4845                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
4846                 offset++;
4847             }
4848             if(size){
4849                 CLRC;
4850                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4851                 pic14_outBitC(result);
4852             } else if(ifx)
4853                 jmpTrueOrFalse(ifx, tlbl);
4854         } else {
4855             for(;(size--);offset++) {
4856                 // normal case
4857                 // result = left & right
4858                 if(AOP_TYPE(right) == AOP_LIT){
4859                     int t = (lit >> (offset*8)) & 0x0FFL;
4860                     switch(t) {
4861                     case 0x00:
4862                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
4863                         break;
4864                     case 0xff:
4865                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4866                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
4867                         break;
4868                     default:
4869                         emitpcode(POC_MOVLW, popGetLit(t));
4870                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
4871                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
4872                     }
4873                     continue;
4874                 }
4875
4876                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
4877                 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
4878                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
4879             }
4880         }
4881     }
4882
4883 release :
4884     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4885     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4886     freeAsmop(result,NULL,ic,TRUE);
4887 }
4888
4889 /*-----------------------------------------------------------------*/
4890 /* genOr  - code for or                                            */
4891 /*-----------------------------------------------------------------*/
4892 static void genOr (iCode *ic, iCode *ifx)
4893 {
4894     operand *left, *right, *result;
4895     int size, offset=0;
4896     unsigned long lit = 0L;
4897
4898     FENTRY;
4899     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4900
4901     aopOp((left = IC_LEFT(ic)),ic,FALSE);
4902     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4903     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4904
4905     DEBUGpic14_AopType(__LINE__,left,right,result);
4906
4907     /* if left is a literal & right is not then exchange them */
4908     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4909         AOP_NEEDSACC(left)) {
4910         operand *tmp = right ;
4911         right = left;
4912         left = tmp;
4913     }
4914
4915     /* if result = right then exchange them */
4916     if(pic14_sameRegs(AOP(result),AOP(right))){
4917         operand *tmp = right ;
4918         right = left;
4919         left = tmp;
4920     }
4921
4922     /* if right is bit then exchange them */
4923     if (AOP_TYPE(right) == AOP_CRY &&
4924         AOP_TYPE(left) != AOP_CRY){
4925         operand *tmp = right ;
4926         right = left;
4927         left = tmp;
4928     }
4929
4930     DEBUGpic14_AopType(__LINE__,left,right,result);
4931
4932     if(AOP_TYPE(right) == AOP_LIT)
4933         lit = ulFromVal (AOP(right)->aopu.aop_lit);
4934
4935     size = AOP_SIZE(result);
4936
4937     // if(bit | yy)
4938     // xx = bit | yy;
4939     if (AOP_TYPE(left) == AOP_CRY){
4940         if(AOP_TYPE(right) == AOP_LIT){
4941             // c = bit & literal;
4942             if(lit){
4943                 // lit != 0 => result = 1
4944                 if(AOP_TYPE(result) == AOP_CRY){
4945                     if(size)
4946                         emitpcode(POC_BSF, popGet(AOP(result),0));
4947                     //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
4948                     //   AOP(result)->aopu.aop_dir,
4949                     //   AOP(result)->aopu.aop_dir);
4950                     else if(ifx)
4951                         continueIfTrue(ifx);
4952                     goto release;
4953                 }
4954             } else {
4955                 // lit == 0 => result = left
4956                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
4957                     goto release;
4958                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
4959             }
4960         } else {
4961             if (AOP_TYPE(right) == AOP_CRY){
4962                 if(pic14_sameRegs(AOP(result),AOP(left))){
4963                     // c = bit | bit;
4964                     emitpcode(POC_BCF,   popGet(AOP(result),0));
4965                     emitpcode(POC_BTFSC, popGet(AOP(right),0));
4966                     emitpcode(POC_BSF,   popGet(AOP(result),0));
4967
4968                     pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
4969                         AOP(result)->aopu.aop_dir,
4970                         AOP(result)->aopu.aop_dir);
4971                     pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
4972                         AOP(right)->aopu.aop_dir,
4973                         AOP(right)->aopu.aop_dir);
4974                     pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
4975                         AOP(result)->aopu.aop_dir,
4976                         AOP(result)->aopu.aop_dir);
4977                 } else {
4978                         emitpcode(POC_BCF,   popGet(AOP(result),0));
4979                         emitpcode(POC_BTFSS, popGet(AOP(right),0));
4980                         emitpcode(POC_BTFSC, popGet(AOP(left),0));
4981                         emitpcode(POC_BSF,   popGet(AOP(result),0));
4982                 }
4983             } else {
4984                 // c = bit | val;
4985                 symbol *tlbl = newiTempLabel(NULL);
4986                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4987
4988
4989                 emitpcode(POC_BCF,   popGet(AOP(result),0));
4990
4991                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4992                     pic14_emitcode(";XXX setb","c");
4993                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
4994                     AOP(left)->aopu.aop_dir,tlbl->key+100);
4995                 pic14_toBoolean(right);
4996                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4997                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4998                     jmpTrueOrFalse(ifx, tlbl);
4999                     goto release;
5000                 } else {
5001                     CLRC;
5002                     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5003                 }
5004             }
5005         }
5006         // bit = c
5007         // val = c
5008         if(size)
5009             pic14_outBitC(result);
5010         // if(bit | ...)
5011         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5012             genIfxJump(ifx, "c");
5013         goto release ;
5014     }
5015
5016     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5017     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5018     if((AOP_TYPE(right) == AOP_LIT) &&
5019       (AOP_TYPE(result) == AOP_CRY) &&
5020       (AOP_TYPE(left) != AOP_CRY)){
5021         if(lit){
5022             pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5023             // result = 1
5024             if(size)
5025                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5026             else
5027                 continueIfTrue(ifx);
5028             goto release;
5029         } else {
5030             pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5031             // lit = 0, result = boolean(left)
5032             if(size)
5033                 pic14_emitcode(";XXX setb","c");
5034             pic14_toBoolean(right);
5035             if(size){
5036                 symbol *tlbl = newiTempLabel(NULL);
5037                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5038                 CLRC;
5039                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5040             } else {
5041                 genIfxJump (ifx,"a");
5042                 goto release;
5043             }
5044         }
5045         pic14_outBitC(result);
5046         goto release ;
5047     }
5048
5049     /* if left is same as result */
5050     if(pic14_sameRegs(AOP(result),AOP(left))){
5051         int know_W = -1;
5052         for(;size--; offset++,lit>>=8) {
5053             if(AOP_TYPE(right) == AOP_LIT){
5054                 if((lit & 0xff) == 0)
5055                     /*  or'ing with 0 has no effect */
5056                     continue;
5057                 else {
5058                     int p = my_powof2(lit & 0xff);
5059                     if(p>=0) {
5060                         /* only one bit is set in the literal, so use a bsf instruction */
5061                         emitpcode(POC_BSF,
5062                             newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5063                     } else {
5064                         if(know_W != (int)(lit & 0xff))
5065                             emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5066                         know_W = lit & 0xff;
5067                         emitpcode(POC_IORWF, popGet(AOP(left),offset));
5068                     }
5069
5070                 }
5071             } else {
5072                 emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5073                 emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5074             }
5075         }
5076     } else {
5077         // left & result in different registers
5078         if(AOP_TYPE(result) == AOP_CRY){
5079             // result = bit
5080             // if(size), result in bit
5081             // if(!size && ifx), conditional oper: if(left | right)
5082             symbol *tlbl = newiTempLabel(NULL);
5083             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5084             pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5085
5086
5087             if(size)
5088                 pic14_emitcode(";XXX setb","c");
5089             while(sizer--){
5090                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5091                 pic14_emitcode(";XXX orl","a,%s",
5092                     aopGet(AOP(left),offset,FALSE,FALSE));
5093                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5094                 offset++;
5095             }
5096             if(size){
5097                 CLRC;
5098                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5099                 pic14_outBitC(result);
5100             } else if(ifx)
5101                 jmpTrueOrFalse(ifx, tlbl);
5102         } else for(;(size--);offset++){
5103             // normal case
5104             // result = left | right
5105             if(AOP_TYPE(right) == AOP_LIT){
5106                 int t = (lit >> (offset*8)) & 0x0FFL;
5107                 switch(t) {
5108                 case 0x00:
5109                     emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
5110                     emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5111
5112                     break;
5113                 default:
5114                     emitpcode(POC_MOVLW,  popGetLit(t));
5115                     emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5116                     emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5117                 }
5118                 continue;
5119             }
5120
5121             // faster than result <- left, anl result,right
5122             // and better if result is SFR
5123             emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5124             emitpcode(POC_IORFW,popGet(AOP(left),offset));
5125             emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5126         }
5127     }
5128
5129 release :
5130     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5131     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5132     freeAsmop(result,NULL,ic,TRUE);
5133 }
5134
5135 /*-----------------------------------------------------------------*/
5136 /* genXor - code for xclusive or                                   */
5137 /*-----------------------------------------------------------------*/
5138 static void genXor (iCode *ic, iCode *ifx)
5139 {
5140     operand *left, *right, *result;
5141     int size, offset=0;
5142     unsigned long lit = 0L;
5143
5144     FENTRY;
5145     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5146
5147     aopOp((left = IC_LEFT(ic)),ic,FALSE);
5148     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5149     aopOp((result=IC_RESULT(ic)),ic,TRUE);
5150
5151     /* if left is a literal & right is not ||
5152     if left needs acc & right does not */
5153     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5154         (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5155         operand *tmp = right ;
5156         right = left;
5157         left = tmp;
5158     }
5159
5160     /* if result = right then exchange them */
5161     if(pic14_sameRegs(AOP(result),AOP(right))){
5162         operand *tmp = right ;
5163         right = left;
5164         left = tmp;
5165     }
5166
5167     /* if right is bit then exchange them */
5168     if (AOP_TYPE(right) == AOP_CRY &&
5169         AOP_TYPE(left) != AOP_CRY){
5170         operand *tmp = right ;
5171         right = left;
5172         left = tmp;
5173     }
5174     if(AOP_TYPE(right) == AOP_LIT)
5175         lit = ulFromVal (AOP(right)->aopu.aop_lit);
5176
5177     size = AOP_SIZE(result);
5178
5179     // if(bit ^ yy)
5180     // xx = bit ^ yy;
5181     if (AOP_TYPE(left) == AOP_CRY){
5182         if(AOP_TYPE(right) == AOP_LIT){
5183             // c = bit & literal;
5184             if(lit>>1){
5185                 // lit>>1  != 0 => result = 1
5186                 if(AOP_TYPE(result) == AOP_CRY){
5187                     if(size)
5188                     {emitpcode(POC_BSF,  popGet(AOP(result),offset));
5189                     pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
5190                     else if(ifx)
5191                         continueIfTrue(ifx);
5192                     goto release;
5193                 }
5194                 pic14_emitcode("setb","c");
5195             } else{
5196                 // lit == (0 or 1)
5197                 if(lit == 0){
5198                     // lit == 0, result = left
5199                     if(size && pic14_sameRegs(AOP(result),AOP(left)))
5200                         goto release;
5201                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5202                 } else{
5203                     // lit == 1, result = not(left)
5204                     if(size && pic14_sameRegs(AOP(result),AOP(left))){
5205                         emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
5206                         emitpcode(POC_XORWF,  popGet(AOP(result),offset));
5207                         pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5208                         goto release;
5209                     } else {
5210                         assert ( !"incomplete genXor" );
5211                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5212                         pic14_emitcode("cpl","c");
5213                     }
5214                 }
5215             }
5216
5217         } else {
5218             // right != literal
5219             symbol *tlbl = newiTempLabel(NULL);
5220             if (AOP_TYPE(right) == AOP_CRY){
5221                 // c = bit ^ bit;
5222                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5223             }
5224             else{
5225                 int sizer = AOP_SIZE(right);
5226                 // c = bit ^ val
5227                 // if val>>1 != 0, result = 1
5228                 pic14_emitcode("setb","c");
5229                 while(sizer){
5230                     MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5231                     if(sizer == 1)
5232                         // test the msb of the lsb
5233                         pic14_emitcode("anl","a,#0xfe");
5234                     pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5235                     sizer--;
5236                 }
5237                 // val = (0,1)
5238                 pic14_emitcode("rrc","a");
5239             }
5240             pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5241             pic14_emitcode("cpl","c");
5242             pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
5243         }
5244         // bit = c
5245         // val = c
5246         if(size)
5247             pic14_outBitC(result);
5248         // if(bit | ...)
5249         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5250             genIfxJump(ifx, "c");
5251         goto release ;
5252     }
5253
5254     if(pic14_sameRegs(AOP(result),AOP(left))){
5255         /* if left is same as result */
5256         for(;size--; offset++) {
5257             if(AOP_TYPE(right) == AOP_LIT){
5258                 int t  = (lit >> (offset*8)) & 0x0FFL;
5259                 if(t == 0x00L)
5260                     continue;
5261                 else {
5262                         emitpcode(POC_MOVLW, popGetLit(t));
5263                         emitpcode(POC_XORWF,popGet(AOP(left),offset));
5264                 }
5265             } else {
5266                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5267                 emitpcode(POC_XORWF,popGet(AOP(left),offset));
5268             }
5269         }
5270     } else {
5271         // left & result in different registers
5272         if(AOP_TYPE(result) == AOP_CRY){
5273             // result = bit
5274             // if(size), result in bit
5275             // if(!size && ifx), conditional oper: if(left ^ right)
5276             symbol *tlbl = newiTempLabel(NULL);
5277             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5278             if(size)
5279                 pic14_emitcode("setb","c");
5280             while(sizer--){
5281                 if((AOP_TYPE(right) == AOP_LIT) &&
5282                     (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5283                     MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5284                 } else {
5285                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5286                     pic14_emitcode("xrl","a,%s",
5287                         aopGet(AOP(left),offset,FALSE,FALSE));
5288                 }
5289                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5290                 offset++;
5291             }
5292             if(size){
5293                 CLRC;
5294                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5295                 pic14_outBitC(result);
5296             } else if(ifx)
5297                 jmpTrueOrFalse(ifx, tlbl);
5298         } else for(;(size--);offset++){
5299             // normal case
5300             // result = left & right
5301             if(AOP_TYPE(right) == AOP_LIT){
5302                 int t = (lit >> (offset*8)) & 0x0FFL;
5303                 switch(t) {
5304                 case 0x00:
5305                     emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5306                     emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5307                     break;
5308                 case 0xff:
5309                     emitpcode(POC_COMFW,popGet(AOP(left),offset));
5310                     emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5311                     break;
5312                 default:
5313                     emitpcode(POC_MOVLW, popGetLit(t));
5314                     emitpcode(POC_XORFW,popGet(AOP(left),offset));
5315                     emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5316                 }
5317                 continue;
5318             }
5319
5320             // faster than result <- left, anl result,right
5321             // and better if result is SFR
5322             emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5323             emitpcode(POC_XORFW,popGet(AOP(left),offset));
5324             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5325         }
5326     }
5327
5328 release :
5329     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5330     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5331     freeAsmop(result,NULL,ic,TRUE);
5332 }
5333
5334 /*-----------------------------------------------------------------*/
5335 /* genInline - write the inline code out                           */
5336 /*-----------------------------------------------------------------*/
5337 static void genInline (iCode *ic)
5338 {
5339   char *buffer, *bp, *bp1;
5340   bool inComment = FALSE;
5341
5342   FENTRY;
5343   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5344
5345   _G.inLine += (!options.asmpeep);
5346
5347   buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
5348
5349   while (*bp)
5350     {
5351       switch (*bp)
5352         {
5353         case ';':
5354           inComment = TRUE;
5355           ++bp;
5356           break;
5357
5358         case '\n':
5359           inComment = FALSE;
5360           *bp++ = '\0';
5361           if (*bp1)
5362             addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
5363           bp1 = bp;
5364           break;
5365
5366         default:
5367           /* Add \n for labels, not dirs such as c:\mydir */
5368           if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
5369             {
5370               ++bp;
5371               *bp = '\0';
5372               ++bp;
5373               /* print label, use this special format with NULL directive
5374                * to denote that the argument should not be indented with tab */
5375               addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
5376               bp1 = bp;
5377             }
5378           else
5379             ++bp;
5380           break;
5381         }
5382     }
5383   if ((bp1 != bp) && *bp1)
5384     addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
5385
5386   Safe_free (buffer);
5387
5388   _G.inLine -= (!options.asmpeep);
5389 }
5390
5391 /*-----------------------------------------------------------------*/
5392 /* genRRC - rotate right with carry                                */
5393 /*-----------------------------------------------------------------*/
5394 static void genRRC (iCode *ic)
5395 {
5396     operand *left , *result ;
5397     int size, offset = 0, same;
5398
5399     FENTRY;
5400     /* rotate right with carry */
5401     left = IC_LEFT(ic);
5402     result=IC_RESULT(ic);
5403     aopOp (left,ic,FALSE);
5404     aopOp (result,ic,FALSE);
5405
5406     DEBUGpic14_AopType(__LINE__,left,NULL,result);
5407
5408     same = pic14_sameRegs(AOP(result),AOP(left));
5409
5410     size = AOP_SIZE(result);
5411
5412     /* get the lsb and put it into the carry */
5413     emitpcode(POC_RRFW, popGet(AOP(left),size-1));
5414
5415     offset = 0 ;
5416
5417     while(size--) {
5418
5419         if(same) {
5420             emitpcode(POC_RRF, popGet(AOP(left),offset));
5421         } else {
5422             emitpcode(POC_RRFW, popGet(AOP(left),offset));
5423             emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5424         }
5425
5426         offset++;
5427     }
5428
5429     freeAsmop(left,NULL,ic,TRUE);
5430     freeAsmop(result,NULL,ic,TRUE);
5431 }
5432
5433 /*-----------------------------------------------------------------*/
5434 /* genRLC - generate code for rotate left with carry               */
5435 /*-----------------------------------------------------------------*/
5436 static void genRLC (iCode *ic)
5437 {
5438     operand *left , *result ;
5439     int size, offset = 0;
5440     int same;
5441
5442     FENTRY;
5443     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5444     /* rotate right with carry */
5445     left = IC_LEFT(ic);
5446     result=IC_RESULT(ic);
5447     aopOp (left,ic,FALSE);
5448     aopOp (result,ic,FALSE);
5449
5450     DEBUGpic14_AopType(__LINE__,left,NULL,result);
5451
5452     same = pic14_sameRegs(AOP(result),AOP(left));
5453
5454     /* move it to the result */
5455     size = AOP_SIZE(result);
5456
5457     /* get the msb and put it into the carry */
5458     emitpcode(POC_RLFW, popGet(AOP(left),size-1));
5459
5460     offset = 0 ;
5461
5462     while(size--) {
5463
5464         if(same) {
5465             emitpcode(POC_RLF, popGet(AOP(left),offset));
5466         } else {
5467             emitpcode(POC_RLFW, popGet(AOP(left),offset));
5468             emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5469         }
5470
5471         offset++;
5472     }
5473
5474
5475     freeAsmop(left,NULL,ic,TRUE);
5476     freeAsmop(result,NULL,ic,TRUE);
5477 }
5478
5479 /*-----------------------------------------------------------------*/
5480 /* genGetHbit - generates code get highest order bit               */
5481 /*-----------------------------------------------------------------*/
5482 static void genGetHbit (iCode *ic)
5483 {
5484     operand *left, *result;
5485     left = IC_LEFT(ic);
5486     result=IC_RESULT(ic);
5487     aopOp (left,ic,FALSE);
5488     aopOp (result,ic,FALSE);
5489
5490     FENTRY;
5491     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5492     /* get the highest order byte into a */
5493     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5494     if(AOP_TYPE(result) == AOP_CRY){
5495         pic14_emitcode("rlc","a");
5496         pic14_outBitC(result);
5497     }
5498     else{
5499         pic14_emitcode("rl","a");
5500         pic14_emitcode("anl","a,#0x01");
5501         pic14_outAcc(result);
5502     }
5503
5504
5505     freeAsmop(left,NULL,ic,TRUE);
5506     freeAsmop(result,NULL,ic,TRUE);
5507 }
5508
5509 /*-----------------------------------------------------------------*/
5510 /* AccLsh - shift left accumulator by known count                  */
5511 /* MARK: pic14 always rotates through CARRY!                       */
5512 /*-----------------------------------------------------------------*/
5513 static void AccLsh (pCodeOp *pcop,int shCount)
5514 {
5515     FENTRY;
5516     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5517     shCount &= 0x0007;              // shCount : 0..7
5518     switch(shCount){
5519     case 0 :
5520         return;
5521         break;
5522     case 1 :
5523         emitCLRC;
5524         emitpcode(POC_RLF,pcop);
5525         return;
5526         break;
5527     case 2 :
5528         emitpcode(POC_RLF,pcop);
5529         emitpcode(POC_RLF,pcop);
5530         break;
5531     case 3 :
5532         emitpcode(POC_RLF,pcop);
5533         emitpcode(POC_RLF,pcop);
5534         emitpcode(POC_RLF,pcop);
5535         break;
5536     case 4 :
5537         emitpcode(POC_SWAPF,pcop);
5538         break;
5539     case 5 :
5540         emitpcode(POC_SWAPF,pcop);
5541         emitpcode(POC_RLF,pcop);
5542         break;
5543     case 6 :
5544         emitpcode(POC_SWAPF,pcop);
5545         emitpcode(POC_RLF,pcop);
5546         emitpcode(POC_RLF,pcop);
5547         break;
5548     case 7 :
5549         emitpcode(POC_RRFW,pcop);
5550         emitpcode(POC_RRF,pcop);
5551         break;
5552     }
5553     /* clear invalid bits */
5554     emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
5555     emitpcode(POC_ANDWF, pcop);
5556 }
5557
5558 /*-----------------------------------------------------------------*/
5559 /* AccRsh - shift right accumulator by known count                 */
5560 /* MARK: pic14 always rotates through CARRY!                       */
5561 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
5562 /*            1: mask out invalid bits (zero-extend)               */
5563 /*            2: sign-extend result (pretty slow)                  */
5564 /*-----------------------------------------------------------------*/
5565 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
5566 {
5567     FENTRY;
5568     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5569     shCount &= 0x0007;              // shCount : 0..7
5570     switch(shCount){
5571     case 0 :
5572         return;
5573         break;
5574     case 1 :
5575         /* load sign if needed */
5576         if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
5577         else if (mask_mode == 1) emitCLRC;
5578         emitpcode(POC_RRF,pcop);
5579         return;
5580         break;
5581     case 2 :
5582         /* load sign if needed */
5583         if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
5584         emitpcode(POC_RRF,pcop);
5585         /* load sign if needed */
5586         if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
5587         emitpcode(POC_RRF,pcop);
5588         if (mask_mode == 2) return;
5589         break;
5590     case 3 :
5591         /* load sign if needed */
5592         if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
5593         emitpcode(POC_RRF,pcop);
5594         /* load sign if needed */
5595         if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
5596         emitpcode(POC_RRF,pcop);
5597         /* load sign if needed */
5598         if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
5599         emitpcode(POC_RRF,pcop);
5600         if (mask_mode == 2) return;
5601         break;
5602     case 4 :
5603         emitpcode(POC_SWAPF,pcop);
5604         break;
5605     case 5 :
5606         emitpcode(POC_SWAPF,pcop);
5607         emitpcode(POC_RRF,pcop);
5608         break;
5609     case 6 :
5610         emitpcode(POC_SWAPF,pcop);
5611         emitpcode(POC_RRF,pcop);
5612         emitpcode(POC_RRF,pcop);
5613         break;
5614     case 7 :
5615         if (mask_mode == 2)
5616         {
5617             /* load sign */
5618             emitpcode(POC_RLFW,pcop);
5619             emitpcode(POC_CLRF,pcop);
5620             emitSKPNC;
5621             emitpcode(POC_COMF,pcop);
5622             return;
5623         } else {
5624             emitpcode(POC_RLFW,pcop);
5625             emitpcode(POC_RLF,pcop);
5626         }
5627         break;
5628     }
5629
5630     if (mask_mode == 0)
5631     {
5632         /* leave invalid bits undefined */
5633         return;
5634     }
5635
5636     /* clear invalid bits -- zero-extend */
5637     emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
5638     emitpcode(POC_ANDWF, pcop);
5639
5640     if (mask_mode == 2) {
5641       /* sign-extend */
5642       emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
5643       emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
5644       emitpcode(POC_IORWF, pcop);
5645     }
5646 }
5647
5648 #if 0
5649 /*-----------------------------------------------------------------*/
5650 /* AccSRsh - signed right shift accumulator by known count                 */
5651 /*-----------------------------------------------------------------*/
5652 static void AccSRsh (int shCount)
5653 {
5654     symbol *tlbl ;
5655     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5656     if(shCount != 0){
5657         if(shCount == 1){
5658             pic14_emitcode("mov","c,acc.7");
5659             pic14_emitcode("rrc","a");
5660         } else if(shCount == 2){
5661             pic14_emitcode("mov","c,acc.7");
5662             pic14_emitcode("rrc","a");
5663             pic14_emitcode("mov","c,acc.7");
5664             pic14_emitcode("rrc","a");
5665         } else {
5666             tlbl = newiTempLabel(NULL);
5667             /* rotate right accumulator */
5668             AccRol(8 - shCount);
5669             /* and kill the higher order bits */
5670             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
5671             pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5672             pic14_emitcode("orl","a,#0x%02x",
5673                 (unsigned char)~SRMask[shCount]);
5674             pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5675         }
5676     }
5677 }
5678
5679 /*-----------------------------------------------------------------*/
5680 /* shiftR1Left2Result - shift right one byte from left to result   */
5681 /*-----------------------------------------------------------------*/
5682 static void shiftR1Left2ResultSigned (operand *left, int offl,
5683                                       operand *result, int offr,
5684                                       int shCount)
5685 {
5686     int same;
5687
5688     FENTRY;
5689     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5690
5691     same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
5692
5693     switch(shCount) {
5694     case 1:
5695         emitpcode(POC_RLFW, popGet(AOP(left),offl));
5696         if(same)
5697             emitpcode(POC_RRF, popGet(AOP(result),offr));
5698         else {
5699             emitpcode(POC_RRFW, popGet(AOP(left),offl));
5700             emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5701         }
5702
5703         break;
5704     case 2:
5705
5706         emitpcode(POC_RLFW, popGet(AOP(left),offl));
5707         if(same)
5708             emitpcode(POC_RRF, popGet(AOP(result),offr));
5709         else {
5710             emitpcode(POC_RRFW, popGet(AOP(left),offl));
5711             emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5712         }
5713         emitpcode(POC_RLFW, popGet(AOP(result),offr));
5714         emitpcode(POC_RRF,  popGet(AOP(result),offr));
5715
5716         break;
5717
5718     case 3:
5719         if(same)
5720             emitpcode(POC_SWAPF, popGet(AOP(result),offr));
5721         else {
5722             emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5723             emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5724         }
5725
5726         emitpcode(POC_RLFW,  popGet(AOP(result),offr));
5727         emitpcode(POC_RLFW,  popGet(AOP(result),offr));
5728         emitpcode(POC_ANDLW, popGetLit(0x1f));
5729
5730         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
5731         emitpcode(POC_IORLW, popGetLit(0xe0));
5732
5733         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5734         break;
5735
5736     case 4:
5737         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5738         emitpcode(POC_ANDLW,  popGetLit(0x0f));
5739         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
5740         emitpcode(POC_IORLW,  popGetLit(0xf0));
5741         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
5742         break;
5743     case 5:
5744         if(same) {
5745             emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
5746         } else {
5747             emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
5748             emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
5749         }
5750         emitpcode(POC_RRFW,   popGet(AOP(result),offr));
5751         emitpcode(POC_ANDLW,  popGetLit(0x07));
5752         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
5753         emitpcode(POC_IORLW,  popGetLit(0xf8));
5754         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
5755         break;
5756
5757     case 6:
5758         if(same) {
5759             emitpcode(POC_MOVLW, popGetLit(0x00));
5760             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
5761             emitpcode(POC_MOVLW, popGetLit(0xfe));
5762             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
5763             emitpcode(POC_IORLW, popGetLit(0x01));
5764             emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5765         } else {
5766             emitpcode(POC_CLRF,  popGet(AOP(result),offr));
5767             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
5768             emitpcode(POC_DECF,  popGet(AOP(result),offr));
5769             emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
5770             emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
5771         }
5772         break;
5773
5774     case 7:
5775         if(same) {
5776             emitpcode(POC_MOVLW, popGetLit(0x00));
5777             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
5778             emitpcode(POC_MOVLW, popGetLit(0xff));
5779             emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5780         } else {
5781             emitpcode(POC_CLRF,  popGet(AOP(result),offr));
5782             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
5783             emitpcode(POC_DECF,  popGet(AOP(result),offr));
5784         }
5785
5786     default:
5787         break;
5788     }
5789 }
5790
5791 /*-----------------------------------------------------------------*/
5792 /* shiftR1Left2Result - shift right one byte from left to result   */
5793 /*-----------------------------------------------------------------*/
5794 static void shiftR1Left2Result (operand *left, int offl,
5795                                 operand *result, int offr,
5796                                 int shCount, int sign)
5797 {
5798     int same;
5799
5800     FENTRY;
5801     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5802
5803     same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
5804
5805     /* Copy the msb into the carry if signed. */
5806     if(sign) {
5807         shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
5808         return;
5809     }
5810
5811
5812
5813     switch(shCount) {
5814     case 1:
5815         emitCLRC;
5816         if(same)
5817             emitpcode(POC_RRF, popGet(AOP(result),offr));
5818         else {
5819             emitpcode(POC_RRFW, popGet(AOP(left),offl));
5820             emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5821         }
5822         break;
5823     case 2:
5824         emitCLRC;
5825         if(same) {
5826             emitpcode(POC_RRF, popGet(AOP(result),offr));
5827         } else {
5828             emitpcode(POC_RRFW, popGet(AOP(left),offl));
5829             emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5830         }
5831         emitCLRC;
5832         emitpcode(POC_RRF, popGet(AOP(result),offr));
5833
5834         break;
5835     case 3:
5836         if(same)
5837             emitpcode(POC_SWAPF, popGet(AOP(result),offr));
5838         else {
5839             emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5840             emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5841         }
5842
5843         emitpcode(POC_RLFW,  popGet(AOP(result),offr));
5844         emitpcode(POC_RLFW,  popGet(AOP(result),offr));
5845         emitpcode(POC_ANDLW, popGetLit(0x1f));
5846         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5847         break;
5848
5849     case 4:
5850         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5851         emitpcode(POC_ANDLW, popGetLit(0x0f));
5852         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5853         break;
5854
5855     case 5:
5856         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5857         emitpcode(POC_ANDLW, popGetLit(0x0f));
5858         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5859         emitCLRC;
5860         emitpcode(POC_RRF, popGet(AOP(result),offr));
5861
5862         break;
5863     case 6:
5864
5865         emitpcode(POC_RLFW,  popGet(AOP(left),offl));
5866         emitpcode(POC_ANDLW, popGetLit(0x80));
5867         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5868         emitpcode(POC_RLF,   popGet(AOP(result),offr));
5869         emitpcode(POC_RLF,   popGet(AOP(result),offr));
5870         break;
5871
5872     case 7:
5873
5874         emitpcode(POC_RLFW, popGet(AOP(left),offl));
5875         emitpcode(POC_CLRF, popGet(AOP(result),offr));
5876         emitpcode(POC_RLF,  popGet(AOP(result),offr));
5877
5878         break;
5879
5880     default:
5881         break;
5882     }
5883 }
5884
5885 /*-----------------------------------------------------------------*/
5886 /* shiftL1Left2Result - shift left one byte from left to result    */
5887 /*-----------------------------------------------------------------*/
5888 static void shiftL1Left2Result (operand *left, int offl,
5889                                 operand *result, int offr, int shCount)
5890 {
5891     int same;
5892
5893     //    char *l;
5894     FENTRY;
5895     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5896
5897     same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
5898     DEBUGpic14_emitcode ("; ***","same =  %d",same);
5899     //    l = aopGet(AOP(left),offl,FALSE,FALSE);
5900     //    MOVA(l);
5901     /* shift left accumulator */
5902     //AccLsh(shCount); // don't comment out just yet...
5903     //    aopPut(AOP(result),"a",offr);
5904
5905     switch(shCount) {
5906     case 1:
5907         /* Shift left 1 bit position */
5908         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
5909         if(same) {
5910             emitpcode(POC_ADDWF, popGet(AOP(left),offl));
5911         } else {
5912             emitpcode(POC_ADDFW, popGet(AOP(left),offl));
5913             emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5914         }
5915         break;
5916     case 2:
5917         emitpcode(POC_RLFW, popGet(AOP(left),offl));
5918         emitpcode(POC_ANDLW,popGetLit(0x7e));
5919         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
5920         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
5921         break;
5922     case 3:
5923         emitpcode(POC_RLFW, popGet(AOP(left),offl));
5924         emitpcode(POC_ANDLW,popGetLit(0x3e));
5925         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
5926         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
5927         emitpcode(POC_RLF,  popGet(AOP(result),offr));
5928         break;
5929     case 4:
5930         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
5931         emitpcode(POC_ANDLW, popGetLit(0xf0));
5932         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
5933         break;
5934     case 5:
5935         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
5936         emitpcode(POC_ANDLW, popGetLit(0xf0));
5937         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
5938         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
5939         break;
5940     case 6:
5941         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
5942         emitpcode(POC_ANDLW, popGetLit(0x30));
5943         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
5944         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
5945         emitpcode(POC_RLF,  popGet(AOP(result),offr));
5946         break;
5947     case 7:
5948         emitpcode(POC_RRFW, popGet(AOP(left),offl));
5949         emitpcode(POC_CLRF, popGet(AOP(result),offr));
5950         emitpcode(POC_RRF,  popGet(AOP(result),offr));
5951         break;
5952
5953     default:
5954         DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
5955     }
5956
5957 }
5958 #endif
5959
5960 /*-----------------------------------------------------------------*/
5961 /* movLeft2Result - move byte from left to result                  */
5962 /*-----------------------------------------------------------------*/
5963 static void movLeft2Result (operand *left, int offl,
5964                             operand *result, int offr)
5965 {
5966     FENTRY;
5967     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5968     if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5969         aopGet(AOP(left),offl,FALSE,FALSE);
5970
5971         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
5972         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5973     }
5974 }
5975
5976 /*-----------------------------------------------------------------*/
5977 /* shiftLeft_Left2ResultLit - shift left by known count            */
5978 /*-----------------------------------------------------------------*/
5979
5980 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
5981 {
5982     int size, same, offr, i;
5983
5984     size = AOP_SIZE(left);
5985     if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
5986
5987     same = pic14_sameRegs (AOP(left), AOP(result));
5988
5989     offr = shCount / 8;
5990     shCount = shCount & 0x07;
5991
5992     size -= offr;
5993
5994     switch (shCount)
5995     {
5996     case 0: /* takes 0 or 2N cycles (for offr==0) */
5997         if (!same || offr) {
5998             for (i=size-1; i >= 0; i--)
5999                 movLeft2Result (left, i, result, offr + i);
6000         } // if
6001         break;
6002
6003     case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6004         if (same && offr) {
6005             shiftLeft_Left2ResultLit (left, result, 8 * offr);
6006             shiftLeft_Left2ResultLit (result, result, shCount);
6007             return; /* prevent clearing result again */
6008         } else {
6009             emitCLRC;
6010             for (i=0; i < size; i++) {
6011                 if (same && !offr) {
6012                     emitpcode (POC_RLF, popGet (AOP(left), i));
6013                 } else {
6014                     emitpcode (POC_RLFW, popGet (AOP(left), i));
6015                     emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6016                 } // if
6017             } // for
6018         } // if (offr)
6019         break;
6020
6021     case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6022         /* works in-place/with offr as well */
6023         emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6024         emitpcode (POC_ANDLW, popGetLit (0xF0));
6025         emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6026
6027         for (i = size - 2; i >= 0; i--)
6028         {
6029             emitpcode (POC_SWAPFW, popGet (AOP(left), i));
6030             emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6031             emitpcode (POC_ANDLW, popGetLit (0x0F));
6032             emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
6033             emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
6034         } // for i
6035         break;
6036
6037     case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
6038         /* works in-place/with offr as well */
6039         emitpcode (POC_RRFW, popGet (AOP(left), size-1));
6040         for (i = size-2; i >= 0; i--) {
6041             emitpcode (POC_RRFW, popGet (AOP(left), i));
6042             emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
6043         } // for i
6044         emitpcode (POC_CLRF, popGet (AOP(result), offr));
6045         emitpcode (POC_RRF, popGet (AOP(result), offr));
6046         break;
6047
6048     default:
6049         shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
6050         shiftLeft_Left2ResultLit (result, result, 1);
6051         return; /* prevent clearing result again */
6052         break;
6053     } // switch
6054
6055     while (0 < offr--)
6056     {
6057         emitpcode (POC_CLRF, popGet (AOP(result), offr));
6058     } // while
6059 }
6060
6061 /*-----------------------------------------------------------------*/
6062 /* shiftRight_Left2ResultLit - shift right by known count          */
6063 /*-----------------------------------------------------------------*/
6064
6065 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
6066 {
6067     int size, same, offr, i;
6068
6069     size = AOP_SIZE(left);
6070     if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6071
6072     same = pic14_sameRegs (AOP(left), AOP(result));
6073
6074     offr = shCount / 8;
6075     shCount = shCount & 0x07;
6076
6077     size -= offr;
6078
6079     if (size)
6080     {
6081         switch (shCount)
6082         {
6083         case 0: /* takes 0 or 2N cycles (for offr==0) */
6084             if (!same || offr) {
6085                 for (i=0; i < size; i++)
6086                     movLeft2Result (left, i + offr, result, i);
6087             } // if
6088             break;
6089
6090         case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
6091             emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
6092             if (same && offr) {
6093                 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
6094                 shiftRight_Left2ResultLit (result, result, shCount, sign);
6095                 return; /* prevent sign-extending result again */
6096             } else {
6097                 emitCLRC;
6098                 if (sign) {
6099                     emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
6100                     emitSETC;
6101                 }
6102                 for (i = size-1; i >= 0; i--) {
6103                     if (same && !offr) {
6104                         emitpcode (POC_RRF, popGet (AOP(left), i));
6105                     } else {
6106                         emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
6107                         emitpcode (POC_MOVWF, popGet (AOP(result), i));
6108                     }
6109                 } // for i
6110             } // if (offr)
6111             break;
6112
6113         case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
6114             /* works in-place/with offr as well */
6115             emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
6116             emitpcode (POC_ANDLW, popGetLit (0x0F));
6117             emitpcode (POC_MOVWF, popGet(AOP(result), 0));
6118
6119             for (i = 1; i < size; i++)
6120             {
6121                 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
6122                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
6123                 emitpcode (POC_ANDLW, popGetLit (0xF0));
6124                 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
6125                 emitpcode (POC_XORWF, popGet (AOP(result), i));
6126             } // for i
6127
6128             if (sign)
6129             {
6130                 emitpcode (POC_MOVLW, popGetLit (0xF0));
6131                 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
6132                 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
6133             } // if
6134             break;
6135
6136         case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
6137             /* works in-place/with offr as well */
6138             emitpcode (POC_RLFW, popGet (AOP(left), offr));
6139             for (i = 0; i < size-1; i++) {
6140                 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
6141                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
6142             } // for i
6143             emitpcode (POC_CLRF, popGet (AOP(result), size-1));
6144             if (!sign) {
6145                 emitpcode (POC_RLF, popGet (AOP(result), size-1));
6146             } else {
6147                 emitSKPNC;
6148                 emitpcode (POC_DECF, popGet (AOP(result), size-1));
6149             }
6150             break;
6151
6152         default:
6153             shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
6154             shiftRight_Left2ResultLit (result, result, 1, sign);
6155             return; /* prevent sign extending result again */
6156             break;
6157         } // switch
6158     } // if
6159
6160     addSign (result, size, sign);
6161 }
6162
6163 #if 0
6164 /*-----------------------------------------------------------------*/
6165 /* shiftL2Left2Result - shift left two bytes from left to result   */
6166 /*-----------------------------------------------------------------*/
6167 static void shiftL2Left2Result (operand *left, int offl,
6168                                 operand *result, int offr, int shCount)
6169 {
6170     FENTRY;
6171
6172     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6173
6174     if(pic14_sameRegs(AOP(result), AOP(left))) {
6175         switch(shCount) {
6176         case 0:
6177             break;
6178         case 1:
6179         case 2:
6180         case 3:
6181
6182             emitpcode(POC_MOVFW,popGet(AOP(result),offr));
6183             emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6184             emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6185
6186             while(--shCount) {
6187                 emitCLRC;
6188                 emitpcode(POC_RLF, popGet(AOP(result),offr));
6189                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6190             }
6191
6192             break;
6193         case 4:
6194         case 5:
6195             emitpcode(POC_MOVLW, popGetLit(0x0f));
6196             emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
6197             emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6198             emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6199             emitpcode(POC_ANDFW, popGet(AOP(result),offr));
6200             emitpcode(POC_XORWF, popGet(AOP(result),offr));
6201             emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6202             if(shCount >=5) {
6203                 emitpcode(POC_RLF, popGet(AOP(result),offr));
6204                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6205             }
6206             break;
6207         case 6:
6208             emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6209             emitpcode(POC_RRF,  popGet(AOP(result),offr));
6210             emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6211             emitpcode(POC_RRF,  popGet(AOP(result),offr));
6212             emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6213             emitpcode(POC_ANDLW,popGetLit(0xc0));
6214             emitpcode(POC_XORFW,popGet(AOP(result),offr));
6215             emitpcode(POC_XORWF,popGet(AOP(result),offr));
6216             emitpcode(POC_XORFW,popGet(AOP(result),offr));
6217             emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6218             break;
6219         case 7:
6220             emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6221             emitpcode(POC_RRFW, popGet(AOP(result),offr));
6222             emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6223             emitpcode(POC_CLRF, popGet(AOP(result),offr));
6224             emitpcode(POC_RRF,  popGet(AOP(result),offr));
6225         }
6226
6227     } else {
6228         switch(shCount) {
6229         case 0:
6230             break;
6231         case 1:
6232         case 2:
6233         case 3:
6234         /* note, use a mov/add for the shift since the mov has a
6235             chance of getting optimized out */
6236             emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6237             emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6238             emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6239             emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
6240             emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6241
6242             while(--shCount) {
6243                 emitCLRC;
6244                 emitpcode(POC_RLF, popGet(AOP(result),offr));
6245                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6246             }
6247             break;
6248
6249         case 4:
6250         case 5:
6251             emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6252             emitpcode(POC_ANDLW, popGetLit(0xF0));
6253             emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6254             emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6255             emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6256             emitpcode(POC_ANDLW, popGetLit(0xF0));
6257             emitpcode(POC_XORWF, popGet(AOP(result),offr));
6258             emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6259
6260
6261             if(shCount == 5) {
6262                 emitpcode(POC_RLF, popGet(AOP(result),offr));
6263                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6264             }
6265             break;
6266         case 6:
6267             emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6268             emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6269             emitpcode(POC_RRFW, popGet(AOP(result),offl));
6270             emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6271
6272             emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6273             emitpcode(POC_RRF,  popGet(AOP(result),offr));
6274             emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6275             emitpcode(POC_ANDLW,popGetLit(0xc0));
6276             emitpcode(POC_XORFW,popGet(AOP(result),offr));
6277             emitpcode(POC_XORWF,popGet(AOP(result),offr));
6278             emitpcode(POC_XORFW,popGet(AOP(result),offr));
6279             emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6280             break;
6281         case 7:
6282             emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6283             emitpcode(POC_RRFW, popGet(AOP(left),offl));
6284             emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6285             emitpcode(POC_CLRF, popGet(AOP(result),offr));
6286             emitpcode(POC_RRF,  popGet(AOP(result),offr));
6287         }
6288     }
6289
6290 }
6291
6292 /*-----------------------------------------------------------------*/
6293 /* shiftR2Left2Result - shift right two bytes from left to result  */
6294 /*-----------------------------------------------------------------*/
6295 static void shiftR2Left2Result (operand *left, int offl,
6296                                 operand *result, int offr,
6297                                 int shCount, int sign)
6298 {
6299     int same=0;
6300
6301     FENTRY;
6302     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6303     same = pic14_sameRegs(AOP(result), AOP(left));
6304
6305     if(same && ((offl + MSB16) == offr)){
6306         same=1;
6307         /* don't crash result[offr] */
6308         MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6309         pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6310     }
6311     /* else {
6312     movLeft2Result(left,offl, result, offr);
6313     MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6314     }
6315     */
6316     /* a:x >> shCount (x = lsb(result))*/
6317     switch(shCount) {
6318     case 0:
6319         break;
6320     case 1:
6321     case 2:
6322     case 3:
6323         if(sign)
6324             emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
6325         else
6326             emitCLRC;
6327
6328         if(same) {
6329             emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6330             emitpcode(POC_RRF,popGet(AOP(result),offr));
6331         } else {
6332             emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6333             emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6334             emitpcode(POC_RRFW, popGet(AOP(left),offl));
6335             emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6336         }
6337
6338         while(--shCount) {
6339             if(sign)
6340                 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
6341             else
6342                 emitCLRC;
6343             emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6344             emitpcode(POC_RRF,popGet(AOP(result),offr));
6345         }
6346         break;
6347     case 4:
6348     case 5:
6349         if(same) {
6350
6351             emitpcode(POC_MOVLW, popGetLit(0xf0));
6352             emitpcode(POC_ANDWF, popGet(AOP(result),offr));
6353             emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6354
6355             emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6356             emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
6357             emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6358             emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6359         } else {
6360             emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6361             emitpcode(POC_ANDLW, popGetLit(0x0f));
6362             emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6363
6364             emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6365             emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6366             emitpcode(POC_ANDLW, popGetLit(0xf0));
6367             emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6368             emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6369         }
6370
6371         if(shCount >=5) {
6372             emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6373             emitpcode(POC_RRF, popGet(AOP(result),offr));
6374         }
6375
6376         if(sign) {
6377             emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
6378             emitpcode(POC_BTFSC,
6379                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
6380             emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6381         }
6382
6383         break;
6384
6385     case 6:
6386         if(same) {
6387
6388             emitpcode(POC_RLF,  popGet(AOP(result),offr));
6389             emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6390
6391             emitpcode(POC_RLF,  popGet(AOP(result),offr));
6392             emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6393             emitpcode(POC_RLFW, popGet(AOP(result),offr));
6394             emitpcode(POC_ANDLW,popGetLit(0x03));
6395             if(sign) {
6396                 emitpcode(POC_BTFSC,
6397                     newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
6398                 emitpcode(POC_IORLW,popGetLit(0xfc));
6399             }
6400             emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6401             emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
6402             emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6403             emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6404         } else {
6405             emitpcode(POC_RLFW, popGet(AOP(left),offl));
6406             emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6407             emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6408             emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6409             emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6410             emitpcode(POC_RLF,  popGet(AOP(result),offr));
6411             emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
6412             emitpcode(POC_ANDLW,popGetLit(0x03));
6413             if(sign) {
6414                 emitpcode(POC_BTFSC,
6415                     newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
6416                 emitpcode(POC_IORLW,popGetLit(0xfc));
6417             }
6418             emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6419             //emitpcode(POC_RLF,  popGet(AOP(result),offr));
6420
6421
6422         }
6423
6424         break;
6425     case 7:
6426         emitpcode(POC_RLFW, popGet(AOP(left),offl));
6427         emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6428         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6429         emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
6430         if(sign) {
6431             emitSKPNC;
6432             emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
6433         } else
6434             emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6435   }
6436 }
6437
6438 /*-----------------------------------------------------------------*/
6439 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6440 /*-----------------------------------------------------------------*/
6441 static void shiftLLeftOrResult (operand *left, int offl,
6442                                 operand *result, int offr, int shCount)
6443 {
6444     FENTRY;
6445     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6446
6447     /* shift left accumulator */
6448     AccLsh(left,offl,shCount);
6449     /* or with result */
6450     emitpcode (POC_IORWF, popGet (AOP(result), offr));
6451     assert ( !"broken (modifies left, fails for left==result))" );
6452 }
6453
6454 /*-----------------------------------------------------------------*/
6455 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6456 /*-----------------------------------------------------------------*/
6457 static void shiftRLeftOrResult (operand *left, int offl,
6458                                 operand *result, int offr, int shCount)
6459 {
6460     FENTRY;
6461     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6462
6463     /* shift right accumulator */
6464     AccRsh(left,offl,shCount);
6465     /* or with result */
6466     emitpcode (POC_IORWF, popGet (AOP(result), offr));
6467     assert ( !"broken (modifies left, fails for left==result))" );
6468 }
6469
6470 /*-----------------------------------------------------------------*/
6471 /* genlshOne - left shift a one byte quantity by known count       */
6472 /*-----------------------------------------------------------------*/
6473 static void genlshOne (operand *result, operand *left, int shCount)
6474 {
6475     FENTRY;
6476     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6477     shiftL1Left2Result(left, LSB, result, LSB, shCount);
6478 }
6479
6480 /*-----------------------------------------------------------------*/
6481 /* genlshTwo - left shift two bytes by known amount != 0           */
6482 /*-----------------------------------------------------------------*/
6483 static void genlshTwo (operand *result,operand *left, int shCount)
6484 {
6485     int size;
6486
6487     FENTRY;
6488     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6489     size = pic14_getDataSize(result);
6490
6491     /* if shCount >= 8 */
6492     if (shCount >= 8) {
6493         shCount -= 8 ;
6494
6495         if (size > 1){
6496             if (shCount)
6497                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6498             else
6499                 movLeft2Result(left, LSB, result, MSB16);
6500         }
6501         emitpcode(POC_CLRF,popGet(AOP(result),LSB));
6502     }
6503
6504     /*  1 <= shCount <= 7 */
6505     else {
6506         if(size == 1)
6507             shiftL1Left2Result(left, LSB, result, LSB, shCount);
6508         else
6509             shiftL2Left2Result(left, LSB, result, LSB, shCount);
6510     }
6511 }
6512
6513 /*-----------------------------------------------------------------*/
6514 /* shiftLLong - shift left one long from left to result            */
6515 /* offl = LSB or MSB16                                             */
6516 /*-----------------------------------------------------------------*/
6517 static void shiftLLong (operand *left, operand *result, int offr )
6518 {
6519     char *l;
6520     int size = AOP_SIZE(result);
6521
6522     FENTRY;
6523     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6524     if(size >= LSB+offr){
6525         l = aopGet(AOP(left),LSB,FALSE,FALSE);
6526         MOVA(l);
6527         pic14_emitcode("add","a,acc");
6528         if (pic14_sameRegs(AOP(left),AOP(result)) &&
6529             size >= MSB16+offr && offr != LSB )
6530             pic14_emitcode("xch","a,%s",
6531             aopGet(AOP(left),LSB+offr,FALSE,FALSE));
6532         else
6533             aopPut(AOP(result),"a",LSB+offr);
6534     }
6535
6536     if(size >= MSB16+offr){
6537         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6538             l = aopGet(AOP(left),MSB16,FALSE,FALSE);
6539             MOVA(l);
6540         }
6541         pic14_emitcode("rlc","a");
6542         if (pic14_sameRegs(AOP(left),AOP(result)) &&
6543             size >= MSB24+offr && offr != LSB)
6544             pic14_emitcode("xch","a,%s",
6545             aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
6546         else
6547             aopPut(AOP(result),"a",MSB16+offr);
6548     }
6549
6550     if(size >= MSB24+offr){
6551         if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6552             l = aopGet(AOP(left),MSB24,FALSE,FALSE);
6553             MOVA(l);
6554         }
6555         pic14_emitcode("rlc","a");
6556         if (pic14_sameRegs(AOP(left),AOP(result)) &&
6557             size >= MSB32+offr && offr != LSB )
6558             pic14_emitcode("xch","a,%s",
6559             aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
6560         else
6561             aopPut(AOP(result),"a",MSB24+offr);
6562     }
6563
6564     if(size > MSB32+offr){
6565         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6566             l = aopGet(AOP(left),MSB32,FALSE,FALSE);
6567             MOVA(l);
6568         }
6569         pic14_emitcode("rlc","a");
6570         aopPut(AOP(result),"a",MSB32+offr);
6571     }
6572     if(offr != LSB)
6573         aopPut(AOP(result),zero,LSB);
6574 }
6575
6576 /*-----------------------------------------------------------------*/
6577 /* genlshFour - shift four byte by a known amount != 0             */
6578 /*-----------------------------------------------------------------*/
6579 static void genlshFour (operand *result, operand *left, int shCount)
6580 {
6581     int size;
6582
6583     FENTRY;
6584     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6585     size = AOP_SIZE(result);
6586
6587     /* if shifting more that 3 bytes */
6588     if (shCount >= 24 ) {
6589         shCount -= 24;
6590         if (shCount)
6591         /* lowest order of left goes to the highest
6592         order of the destination */
6593         shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6594         else
6595             movLeft2Result(left, LSB, result, MSB32);
6596         aopPut(AOP(result),zero,LSB);
6597         aopPut(AOP(result),zero,MSB16);
6598         aopPut(AOP(result),zero,MSB32);
6599         return;
6600     }
6601
6602     /* more than two bytes */
6603     else if ( shCount >= 16 ) {
6604         /* lower order two bytes goes to higher order two bytes */
6605         shCount -= 16;
6606         /* if some more remaining */
6607         if (shCount)
6608             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6609         else {
6610             movLeft2Result(left, MSB16, result, MSB32);
6611             movLeft2Result(left, LSB, result, MSB24);
6612         }
6613         aopPut(AOP(result),zero,MSB16);
6614         aopPut(AOP(result),zero,LSB);
6615         return;
6616     }
6617
6618     /* if more than 1 byte */
6619     else if ( shCount >= 8 ) {
6620         /* lower order three bytes goes to higher order  three bytes */
6621         shCount -= 8;
6622         if(size == 2){
6623             if(shCount)
6624                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6625             else
6626                 movLeft2Result(left, LSB, result, MSB16);
6627         }
6628         else{   /* size = 4 */
6629             if(shCount == 0){
6630                 movLeft2Result(left, MSB24, result, MSB32);
6631                 movLeft2Result(left, MSB16, result, MSB24);
6632                 movLeft2Result(left, LSB, result, MSB16);
6633                 aopPut(AOP(result),zero,LSB);
6634             }
6635             else if(shCount == 1)
6636                 shiftLLong(left, result, MSB16);
6637             else{
6638                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6639                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6640                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6641                 aopPut(AOP(result),zero,LSB);
6642             }
6643         }
6644     }
6645
6646     /* 1 <= shCount <= 7 */
6647     else if(shCount <= 2){
6648         shiftLLong(left, result, LSB);
6649         if(shCount == 2)
6650             shiftLLong(result, result, LSB);
6651     }
6652     /* 3 <= shCount <= 7, optimize */
6653     else{
6654         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6655         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6656         shiftL2Left2Result(left, LSB, result, LSB, shCount);
6657     }
6658 }
6659 #endif
6660
6661 #if 0
6662 /*-----------------------------------------------------------------*/
6663 /* genLeftShiftLiteral - left shifting by known count              */
6664 /*-----------------------------------------------------------------*/
6665 static void genLeftShiftLiteral (operand *left,
6666                                  operand *right,
6667                                  operand *result,
6668                                  iCode *ic)
6669 {
6670     int shCount = (int) ulFromVal (AOP(right)->aopu.aop_lit);
6671     //int size;
6672
6673     FENTRY;
6674     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6675     freeAsmop(right,NULL,ic,TRUE);
6676
6677     aopOp(left,ic,FALSE);
6678     aopOp(result,ic,FALSE);
6679
6680     size = getSize(operandType(result));
6681
6682 #if VIEW_SIZE
6683     pic14_emitcode("; shift left ","result %d, left %d",size,
6684         AOP_SIZE(left));
6685 #endif
6686
6687     /* I suppose that the left size >= result size */
6688     if(shCount == 0){
6689         while(size--){
6690             movLeft2Result(left, size, result, size);
6691         }
6692     }
6693
6694     else if(shCount >= (size * 8))
6695         while(size--)
6696             aopPut(AOP(result),zero,size);
6697         else{
6698             switch (size) {
6699             case 1:
6700                 genlshOne (result,left,shCount);
6701                 break;
6702
6703             case 2:
6704             case 3:
6705                 genlshTwo (result,left,shCount);
6706                 break;
6707
6708             case 4:
6709                 genlshFour (result,left,shCount);
6710                 break;
6711             }
6712         }
6713         freeAsmop(left,NULL,ic,TRUE);
6714         freeAsmop(result,NULL,ic,TRUE);
6715 }
6716 #endif
6717
6718 /*-----------------------------------------------------------------*
6719 * genMultiAsm - repeat assembly instruction for size of register.
6720 * if endian == 1, then the high byte (i.e base address + size of
6721 * register) is used first else the low byte is used first;
6722 *-----------------------------------------------------------------*/
6723 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
6724 {
6725
6726     int offset = 0;
6727
6728     FENTRY;
6729     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6730
6731     if(!reg)
6732         return;
6733
6734     if(!endian) {
6735         endian = 1;
6736     } else {
6737         endian = -1;
6738         offset = size-1;
6739     }
6740
6741     while(size--) {
6742         emitpcode(poc,    popGet(AOP(reg),offset));
6743         offset += endian;
6744     }
6745
6746 }
6747
6748 /*-----------------------------------------------------------------*/
6749 /* loadSignToC - load the operand's sign bit into CARRY            */
6750 /*-----------------------------------------------------------------*/
6751
6752 static void loadSignToC (operand *op)
6753 {
6754     FENTRY;
6755     assert (op && AOP(op) && AOP_SIZE(op));
6756
6757     emitCLRC;
6758     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
6759     emitSETC;
6760 }
6761
6762 /*-----------------------------------------------------------------*/
6763 /* genRightShift - generate code for right shifting                */
6764 /*-----------------------------------------------------------------*/
6765 static void genGenericShift (iCode *ic, int shiftRight)
6766 {
6767     operand *right, *left, *result;
6768     sym_link *retype ;
6769     int size;
6770     symbol *tlbl, *tlbl1, *inverselbl;
6771
6772     FENTRY;
6773     /* if signed then we do it the hard way preserve the
6774     sign bit moving it inwards */
6775     retype = getSpec(operandType(IC_RESULT(ic)));
6776     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6777
6778     /* signed & unsigned types are treated the same : i.e. the
6779     signed is NOT propagated inwards : quoting from the
6780     ANSI - standard : "for E1 >> E2, is equivalent to division
6781     by 2**E2 if unsigned or if it has a non-negative value,
6782     otherwise the result is implementation defined ", MY definition
6783     is that the sign does not get propagated */
6784
6785     right = IC_RIGHT(ic);
6786     left  = IC_LEFT(ic);
6787     result = IC_RESULT(ic);
6788
6789     aopOp(right,ic,FALSE);
6790     aopOp(left,ic,FALSE);
6791     aopOp(result,ic,FALSE);
6792
6793     /* if the shift count is known then do it
6794     as efficiently as possible */
6795     if (AOP_TYPE(right) == AOP_LIT) {
6796         int lit = (int) ulFromVal (AOP(right)->aopu.aop_lit);
6797         if (lit < 0)
6798         {
6799             lit = -lit;
6800             shiftRight = !shiftRight;
6801         }
6802
6803         if (shiftRight)
6804             shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
6805         else
6806             shiftLeft_Left2ResultLit (left, result, lit);
6807         //genRightShiftLiteral (left,right,result,ic, 0);
6808         return ;
6809     }
6810
6811     /* shift count is unknown then we have to form
6812     a loop get the loop count in B : Note: we take
6813     only the lower order byte since shifting
6814     more that 32 bits make no sense anyway, ( the
6815     largest size of an object can be only 32 bits ) */
6816
6817     /* we must not overwrite the shift counter */
6818     assert (!pic14_sameRegs(AOP(right),AOP(result)));
6819
6820     /* now move the left to the result if they are not the
6821     same */
6822     if (!pic14_sameRegs(AOP(left),AOP(result)))
6823     {
6824         size = min(AOP_SIZE(result), AOP_SIZE(left));
6825         while (size--) {
6826             mov2w(AOP(left), size);
6827             movwf(AOP(result), size);
6828         }
6829         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
6830     }
6831
6832     tlbl = newiTempLabel(NULL);
6833     tlbl1= newiTempLabel(NULL);
6834     inverselbl = NULL;
6835     size = AOP_SIZE(result);
6836
6837     mov2w(AOP(right),0);
6838     if (!SPEC_USIGN(operandType(right)))
6839     {
6840         inverselbl = newiTempLabel(NULL);
6841         /* signed shift count -- invert shift direction for c<0 */
6842         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
6843         emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
6844     } // if
6845     emitpcode(POC_SUBLW, popGetLit(0)); /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
6846     /* check for `a = b >> c' with `-c == 0' */
6847     emitSKPNZ;
6848     emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
6849     emitpLabel(tlbl->key);
6850     /* propagate the sign bit inwards for SIGNED result */
6851     if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
6852     genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
6853     emitpcode(POC_ADDLW,  popGetLit(1));    /* clears CARRY (unless W==0 afterwards) */
6854     emitSKPC;
6855     emitpcode(POC_GOTO,popGetLabel(tlbl->key));
6856
6857     if (!SPEC_USIGN(operandType(right)))
6858     {
6859         symbol *inv_loop = newiTempLabel(NULL);
6860
6861         shiftRight = !shiftRight;   /* invert shift direction */
6862
6863         /* we came here from the code above -- we are done */
6864         emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
6865
6866         /* emit code for shifting N<0 steps, count is already in W */
6867         emitpLabel(inverselbl->key);
6868         if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
6869         emitpLabel(inv_loop->key);
6870         /* propagate the sign bit inwards for SIGNED result */
6871         if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
6872         genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
6873         emitpcode(POC_ADDLW, popGetLit(1));
6874         emitSKPC;
6875         emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
6876     } // if
6877
6878     emitpLabel(tlbl1->key);
6879
6880     freeAsmop(left,NULL,ic,TRUE);
6881     freeAsmop (right,NULL,ic,TRUE);
6882     freeAsmop(result,NULL,ic,TRUE);
6883 }
6884
6885 static void genRightShift (iCode *ic)
6886 {
6887     genGenericShift(ic, 1);
6888 }
6889
6890 static void genLeftShift (iCode *ic)
6891 {
6892     genGenericShift(ic, 0);
6893 }
6894
6895 /*-----------------------------------------------------------------*/
6896 /* SetIrp - Set IRP bit                                            */
6897 /*-----------------------------------------------------------------*/
6898 static void SetIrp(operand *result)
6899 {
6900     FENTRY;
6901     if (AOP_TYPE(result) == AOP_LIT) {
6902         unsigned lit = (unsigned) double2ul (operandLitValue(result));
6903         if (lit&0x100)
6904             emitSETIRP;
6905         else
6906             emitCLRIRP;
6907     } else {
6908         if ((AOP_TYPE(result) == AOP_PCODE)
6909             && (AOP(result)->aopu.pcop->type == PO_LITERAL))
6910         {
6911             int addrs = PCOL(AOP(result)->aopu.pcop)->lit;
6912             if (addrs & 0x100)
6913                 emitSETIRP;
6914             else
6915                 emitCLRIRP;
6916         } else {
6917             emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
6918             if(AOP_SIZE(result) > 1) {
6919                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
6920                 emitSETIRP;
6921             }
6922         }
6923     }
6924 }
6925
6926 static void
6927 setup_fsr (operand *ptr)
6928 {
6929   mov2w_op(ptr, 0);
6930   emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
6931
6932   /* also setup-up IRP */
6933   SetIrp (ptr);
6934 }
6935
6936 /*-----------------------------------------------------------------*/
6937 /* emitPtrByteGet - emits code to get a byte into WREG from an     */
6938 /*                  arbitrary pointer (__code, __data, generic)    */
6939 /*-----------------------------------------------------------------*/
6940 static void
6941 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
6942 {
6943     FENTRY;
6944     switch (p_type)
6945     {
6946     case POINTER:
6947     case FPOINTER:
6948       if (!alreadyAddressed) setup_fsr (src);
6949       emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
6950       break;
6951
6952     case CPOINTER:
6953       assert( AOP_SIZE(src) == 2 );
6954       mov2w_op(src, 0);
6955       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
6956       mov2w_op(src, 1);
6957       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
6958       emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE));   /* GPOINTER tag for __code space */
6959       call_libraryfunc ("__gptrget1");
6960       break;
6961
6962     case GPOINTER:
6963       assert( AOP_SIZE(src) == 3 );
6964       mov2w_op(src, 0);
6965       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
6966       mov2w_op(src, 1);
6967       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
6968       mov2w_op(src, 2);
6969       call_libraryfunc ("__gptrget1");
6970       break;
6971
6972     default:
6973       assert( !"unhandled pointer type" );
6974       break;
6975     }
6976 }
6977
6978 /*-----------------------------------------------------------------*/
6979 /* emitPtrByteSet - emits code to set a byte from src through a    */
6980 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR).       */
6981 /*-----------------------------------------------------------------*/
6982 static void
6983 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
6984 {
6985     FENTRY;
6986     switch (p_type)
6987     {
6988     case POINTER:
6989     case FPOINTER:
6990       if (!alreadyAddressed) setup_fsr (dst);
6991       emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
6992       break;
6993
6994     case CPOINTER:
6995       assert( !"trying to assign to __code pointer" );
6996       break;
6997
6998     case GPOINTER:
6999       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
7000       mov2w_op(dst, 0);
7001       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
7002       mov2w_op(dst, 1);
7003       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
7004       mov2w_op(dst, 2);
7005       call_libraryfunc ("__gptrput1");
7006       break;
7007
7008     default:
7009       assert( !"unhandled pointer type" );
7010       break;
7011     }
7012 }
7013
7014 /*-----------------------------------------------------------------*/
7015 /* genUnpackBits - generates code for unpacking bits               */
7016 /*-----------------------------------------------------------------*/
7017 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
7018 {
7019   int rsize;            /* result size */
7020   sym_link *etype;      /* bitfield type information */
7021   int blen;             /* bitfield length */
7022   int bstr;             /* bitfield starting bit within byte */
7023
7024   FENTRY;
7025   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7026   etype = getSpec(operandType(result));
7027   rsize = getSize (operandType (result));
7028   blen = SPEC_BLEN (etype);
7029   bstr = SPEC_BSTR (etype);
7030
7031   /* single bit field case */
7032   if (blen == 1) {
7033     if (ifx) { /* that is for an if statement */
7034       pCodeOp *pcop;
7035       resolvedIfx rIfx;
7036       resolveIfx(&rIfx,ifx);
7037       if (ptype == -1) /* direct */
7038     pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
7039       else
7040     pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
7041       emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
7042       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
7043       ifx->generated=1;
7044     } else {
7045       int i;
7046       assert (!pic14_sameRegs (AOP(result), AOP(left)));
7047       for (i=0; i < AOP_SIZE(result); i++)
7048     emitpcode (POC_CLRF, popGet (AOP(result), i));
7049
7050       switch (ptype)
7051       {
7052       case -1:
7053         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
7054     /* adjust result below */
7055         break;
7056
7057       case POINTER:
7058       case FPOINTER:
7059       case GPOINTER:
7060       case CPOINTER:
7061         emitPtrByteGet (left, ptype, FALSE);
7062     emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
7063     emitSKPZ;
7064     /* adjust result below */
7065         break;
7066
7067       default:
7068         assert( !"unhandled pointer type" );
7069       } // switch
7070
7071       /* move sign-/zero extended bit to result */
7072       if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
7073     emitpcode (POC_INCF, popGet (AOP(result), 0));
7074       } else {
7075     emitpcode (POC_DECF, popGet (AOP(result), 0));
7076       }
7077       addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
7078     }
7079     return;
7080   }
7081   else if (blen <= 8 && ((blen + bstr) <= 8))
7082   {
7083     /* blen > 1 */
7084     int i;
7085
7086     for (i=0; i < AOP_SIZE(result); i++)
7087       emitpcode (POC_CLRF, popGet (AOP(result), i));
7088
7089     switch (ptype)
7090     {
7091     case -1:
7092       mov2w(AOP(left), 0);
7093       break;
7094
7095     case POINTER:
7096     case FPOINTER:
7097     case GPOINTER:
7098     case CPOINTER:
7099       emitPtrByteGet (left, ptype, FALSE);
7100       break;
7101
7102     default:
7103       assert( !"unhandled pointer type" );
7104     } // switch
7105
7106     if (blen < 8)
7107       emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
7108     movwf(AOP(result), 0);
7109     AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
7110
7111     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
7112     {
7113       /* signed bitfield */
7114       assert (bstr + blen > 0);
7115       emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
7116       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
7117       emitpcode(POC_IORWF, popGet(AOP(result),0));
7118     }
7119     addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
7120     return;
7121   }
7122
7123   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
7124 }
7125
7126 #if 1
7127 /*-----------------------------------------------------------------*/
7128 /* genDataPointerGet - generates code when ptr offset is known     */
7129 /*-----------------------------------------------------------------*/
7130 static void genDataPointerGet (operand *left,
7131     operand *result,
7132     iCode *ic)
7133 {
7134     int size , offset = 0;
7135
7136     FENTRY;
7137     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7138
7139
7140     /* optimization - most of the time, left and result are the same
7141     * address, but different types. for the pic code, we could omit
7142     * the following
7143     */
7144     aopOp(result,ic,TRUE);
7145
7146     if (pic14_sameRegs (AOP(left), AOP(result)))
7147         return;
7148
7149     DEBUGpic14_AopType(__LINE__,left,NULL,result);
7150
7151     //emitpcode(POC_MOVFW, popGet(AOP(left),0));
7152
7153     size = AOP_SIZE(result);
7154     if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
7155
7156     offset = 0;
7157     while (size--) {
7158         emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7159         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7160         offset++;
7161     }
7162
7163     freeAsmop(left,NULL,ic,TRUE);
7164     freeAsmop(result,NULL,ic,TRUE);
7165 }
7166 #endif
7167
7168 /*-----------------------------------------------------------------*/
7169 /* genNearPointerGet - pic14_emitcode for near pointer fetch       */
7170 /*-----------------------------------------------------------------*/
7171 static void genNearPointerGet (operand *left,
7172                                operand *result,
7173                                iCode *ic)
7174 {
7175     asmop *aop = NULL;
7176     sym_link *ltype = operandType(left);
7177     sym_link *rtype = operandType(result);
7178     sym_link *retype= getSpec(rtype);      /* bitfield type information */
7179     int direct = 0;
7180
7181     FENTRY;
7182     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7183
7184
7185     aopOp(left,ic,FALSE);
7186
7187     /* if left is rematerialisable and
7188     result is not bit variable type and
7189     the left is pointer to data space i.e
7190     lower 128 bytes of space */
7191     if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
7192         !IS_BITVAR(retype)         &&
7193         PIC_IS_DATA_PTR(ltype)) {
7194         genDataPointerGet (left,result,ic);
7195         return ;
7196     }
7197
7198     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7199     aopOp (result,ic,FALSE);
7200
7201     /* Check if can access directly instead of via a pointer */
7202     if ((AOP_TYPE(left) == AOP_PCODE)
7203         && (AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
7204         && (AOP_SIZE(result) == 1))
7205     {
7206         direct = 1;
7207     }
7208
7209     if (IS_BITFIELD(getSpec(operandType(result))))
7210     {
7211         genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
7212         goto release;
7213     }
7214
7215     /* If the pointer value is not in a the FSR then need to put it in */
7216     /* Must set/reset IRP bit for use with FSR. */
7217     if (!direct)
7218       setup_fsr (left);
7219
7220 //  sym_link *etype;
7221     /* if bitfield then unpack the bits */
7222     {
7223         /* we have can just get the values */
7224         int size = AOP_SIZE(result);
7225         int offset = 0 ;
7226
7227         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7228
7229         while(size--) {
7230             if (direct)
7231                 emitpcode(POC_MOVWF,popGet(AOP(left),0));
7232             else
7233                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
7234             if (AOP_TYPE(result) == AOP_LIT) {
7235                 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
7236             } else {
7237                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
7238             }
7239             if (size && !direct)
7240                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
7241             offset++;
7242         }
7243     }
7244
7245     /* now some housekeeping stuff */
7246     if (aop) {
7247         /* we had to allocate for this iCode */
7248         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7249         freeAsmop(NULL,aop,ic,TRUE);
7250     } else {
7251         /* we did not allocate which means left
7252         already in a pointer register, then
7253         if size > 0 && this could be used again
7254         we have to point it back to where it
7255         belongs */
7256         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7257         if (AOP_SIZE(result) > 1 &&
7258             !OP_SYMBOL(left)->remat &&
7259             ( OP_SYMBOL(left)->liveTo > ic->seq ||
7260             ic->depth )) {
7261             int size = AOP_SIZE(result) - 1;
7262             while (size--)
7263                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
7264         }
7265     }
7266
7267 release:
7268     /* done */
7269     freeAsmop(left,NULL,ic,TRUE);
7270     freeAsmop(result,NULL,ic,TRUE);
7271
7272 }
7273
7274 /*-----------------------------------------------------------------*/
7275 /* genGenPointerGet - gget value from generic pointer space        */
7276 /*-----------------------------------------------------------------*/
7277 static void genGenPointerGet (operand *left,
7278                               operand *result, iCode *ic)
7279 {
7280     FENTRY;
7281     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7282     aopOp(left,ic,FALSE);
7283     aopOp(result,ic,FALSE);
7284
7285
7286     DEBUGpic14_AopType(__LINE__,left,NULL,result);
7287
7288     if (IS_BITFIELD(getSpec(operandType(result))))
7289     {
7290       genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
7291       return;
7292     }
7293
7294     {
7295       /* emit call to __gptrget */
7296       char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
7297       int size = AOP_SIZE(result);
7298       int idx = 0;
7299
7300       assert (size > 0 && size <= 4);
7301
7302       /* pass arguments */
7303       assert (AOP_SIZE(left) == 3);
7304       mov2w(AOP(left), 0);
7305       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
7306       mov2w(AOP(left), 1);
7307       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
7308       mov2w(AOP(left), 2);
7309       call_libraryfunc (func[size]);
7310
7311       /* save result */
7312       movwf (AOP(result), --size);
7313       while (size--) {
7314         emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
7315         movwf (AOP(result), size);
7316       } // while
7317     }
7318
7319     freeAsmop(left,NULL,ic,TRUE);
7320     freeAsmop(result,NULL,ic,TRUE);
7321
7322 }
7323
7324 /*-----------------------------------------------------------------*/
7325 /* genConstPointerGet - get value from const generic pointer space */
7326 /*-----------------------------------------------------------------*/
7327 static void genConstPointerGet (operand *left,
7328                                 operand *result, iCode *ic)
7329 {
7330     //sym_link *retype = getSpec(operandType(result));
7331     #if 0
7332     symbol *albl, *blbl;//, *clbl;
7333     pCodeOp *pcop;
7334     #endif
7335     PIC_OPCODE poc;
7336     int i, size, lit;
7337
7338     FENTRY;
7339     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7340     aopOp(left,ic,FALSE);
7341     aopOp(result,ic,FALSE);
7342
7343     size = AOP_SIZE(result);
7344
7345     DEBUGpic14_AopType(__LINE__,left,NULL,result);
7346
7347     DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
7348
7349     lit = op_isLitLike (left);
7350     poc = lit ? POC_MOVLW : POC_MOVFW;
7351
7352     if (IS_BITFIELD(getSpec(operandType(result))))
7353     {
7354         genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
7355         goto release;
7356     }
7357
7358     {
7359         char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
7360         int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
7361         assert (size > 0 && size <= 4);
7362
7363         mov2w_op(left, 0);
7364         emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
7365         mov2w_op(left, 1);
7366         emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
7367         emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
7368         call_libraryfunc (func[size]);
7369
7370         movwf(AOP(result),size-1);
7371         for (i = 1; i < size; i++)
7372         {
7373             emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
7374             movwf(AOP(result),size - 1 - i);
7375         } // for
7376     }
7377
7378 release:
7379     freeAsmop(left,NULL,ic,TRUE);
7380     freeAsmop(result,NULL,ic,TRUE);
7381
7382 }
7383 /*-----------------------------------------------------------------*/
7384 /* genPointerGet - generate code for pointer get                   */
7385 /*-----------------------------------------------------------------*/
7386 static void genPointerGet (iCode *ic)
7387 {
7388     operand *left, *result ;
7389     sym_link *type, *etype;
7390     int p_type = -1;
7391
7392     FENTRY;
7393     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7394
7395     left = IC_LEFT(ic);
7396     result = IC_RESULT(ic) ;
7397
7398     /* depending on the type of pointer we need to
7399     move it to the correct pointer register */
7400     type = operandType(left);
7401     etype = getSpec(type);
7402
7403     if (IS_PTR_CONST(type))
7404         DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
7405
7406     /* if left is of type of pointer then it is simple */
7407     if (IS_PTR(type) && !IS_FUNC(type->next))
7408         p_type = DCL_TYPE(type);
7409     else {
7410         /* we have to go by the storage class */
7411         p_type = PTR_TYPE(SPEC_OCLS(etype));
7412
7413         DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
7414
7415         if (SPEC_OCLS(etype)->codesp ) {
7416             DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
7417             //p_type = CPOINTER ;
7418         }
7419         else
7420             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
7421                 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
7422             /*p_type = FPOINTER ;*/
7423             else
7424                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
7425                     DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
7426                 /*        p_type = PPOINTER; */
7427                 else
7428                     if (SPEC_OCLS(etype) == idata )
7429                         DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
7430                     /*      p_type = IPOINTER; */
7431                     else
7432                         DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
7433                     /*      p_type = POINTER ; */
7434     }
7435
7436     /* now that we have the pointer type we assign
7437     the pointer values */
7438     switch (p_type) {
7439
7440     case POINTER:
7441     case FPOINTER:
7442     //case IPOINTER:
7443         genNearPointerGet (left,result,ic);
7444         break;
7445 /*
7446     case PPOINTER:
7447         genPagedPointerGet(left,result,ic);
7448         break;
7449
7450     case FPOINTER:
7451         genFarPointerGet (left,result,ic);
7452         break;
7453 */
7454     case CPOINTER:
7455         genConstPointerGet (left,result,ic);
7456         break;
7457
7458     case GPOINTER:
7459         genGenPointerGet (left,result,ic);
7460         break;
7461     default:
7462         assert ( !"unhandled pointer type" );
7463         break;
7464     }
7465
7466 }
7467
7468 /*-----------------------------------------------------------------*/
7469 /* genPackBits - generates code for packed bit storage             */
7470 /*-----------------------------------------------------------------*/
7471 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
7472 {
7473   int blen;             /* bitfield length */
7474   int bstr;             /* bitfield starting bit within byte */
7475   int litval;           /* source literal value (if AOP_LIT) */
7476   unsigned char mask;   /* bitmask within current byte */
7477
7478   FENTRY;
7479   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7480
7481   blen = SPEC_BLEN (etype);
7482   bstr = SPEC_BSTR (etype);
7483
7484   /* If the bitfield length is less than a byte and does not cross byte boundaries */
7485   if ((blen <= 8) && ((bstr + blen) <= 8))
7486   {
7487     mask = ((unsigned char) (0xFF << (blen + bstr)) |
7488         (unsigned char) (0xFF >> (8 - bstr)));
7489
7490     if (AOP_TYPE (right) == AOP_LIT)
7491     {
7492       /* Case with a bitfield length <8 and literal source */
7493       int lit = (int) ulFromVal (AOP (right)->aopu.aop_lit);
7494       if (blen == 1) {
7495         pCodeOp *pcop;
7496
7497     switch (p_type)
7498     {
7499     case -1:
7500       if (AOP(result)->type == AOP_PCODE)
7501         pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
7502       else
7503         pcop = popGet(AOP(result),0);
7504       emitpcode(lit?POC_BSF:POC_BCF,pcop);
7505       break;
7506
7507     case POINTER:
7508     case FPOINTER:
7509       setup_fsr (result);
7510       emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
7511       break;
7512
7513     case CPOINTER:
7514       assert( !"trying to assign to bitfield via pointer to __code space" );
7515       break;
7516
7517     case GPOINTER:
7518       emitPtrByteGet(result, p_type, FALSE);
7519       if (lit) {
7520         emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
7521       } else {
7522         emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
7523       }
7524       emitPtrByteSet(result, p_type, TRUE);
7525       break;
7526
7527     default:
7528       assert( !"unhandled pointer type" );
7529       break;
7530     } // switch (p_type)
7531       } else {
7532         /* blen > 1 */
7533     litval = lit << bstr;
7534     litval &= (~mask) & 0x00ff;
7535
7536     switch (p_type)
7537     {
7538     case -1:
7539       mov2w (AOP(result), 0);
7540       if ((litval|mask) != 0x00ff)
7541         emitpcode(POC_ANDLW, popGetLit (mask));
7542       if (litval != 0x00)
7543         emitpcode(POC_IORLW, popGetLit (litval));
7544       movwf (AOP(result), 0);
7545       break;
7546
7547     case POINTER:
7548     case FPOINTER:
7549     case GPOINTER:
7550       emitPtrByteGet(result, p_type, FALSE);
7551       if ((litval|mask) != 0x00ff)
7552         emitpcode(POC_ANDLW, popGetLit (mask));
7553       if (litval != 0x00)
7554         emitpcode(POC_IORLW, popGetLit (litval));
7555       emitPtrByteSet(result, p_type, TRUE);
7556       break;
7557
7558     case CPOINTER:
7559       assert( !"trying to assign to bitfield via pointer to __code space" );
7560       break;
7561
7562     default:
7563       assert( !"unhandled pointer type" );
7564       break;
7565     } // switch
7566       } // if (blen > 1)
7567     }
7568     else
7569     {
7570       /* right is no literal */
7571       if (blen==1) {
7572         switch (p_type)
7573     {
7574     case -1:
7575       /* Note more efficient code, of pre clearing bit then only setting it if required,
7576        * can only be done if it is known that the result is not a SFR */
7577       emitpcode(POC_RRFW,popGet(AOP(right),0));
7578       emitSKPC;
7579       emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
7580       emitSKPNC;
7581       emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
7582       break;
7583
7584     case POINTER:
7585     case FPOINTER:
7586     case GPOINTER:
7587       emitPtrByteGet (result, p_type, FALSE);
7588       emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
7589       emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
7590       emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
7591       emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
7592       emitPtrByteSet (result, p_type, TRUE);
7593       break;
7594
7595     case CPOINTER:
7596       assert( !"trying to assign to bitfield via pointer to __code space" );
7597       break;
7598
7599     default:
7600       assert( !"unhandled pointer type" );
7601       break;
7602     } // switch
7603     return;
7604       } else {
7605     /* Case with a bitfield 1 < length <= 8 and arbitrary source */
7606     pCodeOp *temp = popGetTempReg ();
7607
7608     mov2w (AOP(right), 0);
7609     if (blen < 8) {
7610       emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
7611     }
7612     emitpcode(POC_MOVWF, temp);
7613     if (bstr) {
7614       AccLsh (temp, bstr);
7615     }
7616
7617     switch (p_type)
7618     {
7619     case -1:
7620       mov2w (AOP(result), 0);
7621       emitpcode(POC_ANDLW, popGetLit (mask));
7622       emitpcode(POC_IORFW, temp);
7623       movwf (AOP(result), 0);
7624       break;
7625
7626     case POINTER:
7627     case FPOINTER:
7628     case GPOINTER:
7629       emitPtrByteGet (result, p_type, FALSE);
7630       emitpcode(POC_ANDLW, popGetLit (mask));
7631       emitpcode(POC_IORFW, temp);
7632       emitPtrByteSet (result, p_type, TRUE);
7633       break;
7634
7635     case CPOINTER:
7636       assert( !"trying to assign to bitfield via pointer to __code space" );
7637       break;
7638
7639     default:
7640       assert( !"unhandled pointer type" );
7641       break;
7642     } // switch
7643
7644     popReleaseTempReg (temp);
7645       } // if (blen > 1)
7646     } // if (AOP(right)->type != AOP_LIT)
7647     return;
7648   } // if (blen <= 8 && ((blen + bstr) <= 8))
7649
7650   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
7651 }
7652
7653 /*-----------------------------------------------------------------*/
7654 /* genDataPointerSet - remat pointer to data space                 */
7655 /*-----------------------------------------------------------------*/
7656 static void genDataPointerSet(operand *right,
7657     operand *result,
7658     iCode *ic)
7659 {
7660     int size, offset = 0 ;
7661     int ressize;
7662
7663     FENTRY;
7664     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7665     aopOp(right,ic,FALSE);
7666     aopOp(result,ic,FALSE);
7667
7668     assert (IS_SYMOP(result));
7669     assert (IS_PTR(OP_SYM_TYPE(result)));
7670
7671     if (AOP_TYPE(right) == AOP_LIT)
7672       size = 4;
7673     else
7674       size = AOP_SIZE(right);
7675     ressize = getSize(OP_SYM_ETYPE(result));
7676     if (size > ressize) size = ressize;
7677     //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
7678
7679     //assert( !"what's going on here?" );
7680
7681     /*
7682     if ( AOP_TYPE(result) == AOP_PCODE) {
7683     fprintf(stderr,"genDataPointerSet   %s, %d\n",
7684     AOP(result)->aopu.pcop->name,
7685     PCOI(AOP(result)->aopu.pcop)->offset);
7686     }
7687     */
7688
7689     // tsd, was l+1 - the underline `_' prefix was being stripped
7690     while (size--) {
7691         emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
7692
7693         if (AOP_TYPE(right) == AOP_LIT) {
7694             unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
7695             //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
7696             if(lit&0xff) {
7697                 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
7698                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
7699             } else {
7700                 emitpcode(POC_CLRF, popGet(AOP(result), offset));
7701             }
7702         } else {
7703             //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
7704             emitpcode(POC_MOVFW, popGet(AOP(right), offset));
7705             emitpcode(POC_MOVWF, popGet(AOP(result), offset));
7706         }
7707
7708         offset++;
7709     }
7710
7711     freeAsmop(right,NULL,ic,TRUE);
7712     freeAsmop(result,NULL,ic,TRUE);
7713 }
7714
7715 /*-----------------------------------------------------------------*/
7716 /* genNearPointerSet - pic14_emitcode for near pointer put         */
7717 /*-----------------------------------------------------------------*/
7718 static void genNearPointerSet (operand *right,
7719                                operand *result,
7720                                iCode *ic)
7721 {
7722     asmop *aop = NULL;
7723     sym_link *ptype = operandType(result);
7724     sym_link *retype = getSpec(operandType(right));
7725     sym_link *letype = getSpec(ptype);
7726     int direct = 0;
7727
7728
7729     FENTRY;
7730     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7731     aopOp(result,ic,FALSE);
7732
7733 #if 1
7734     /* if the result is rematerializable &
7735     in data space & not a bit variable */
7736     //if (AOP_TYPE(result) == AOP_IMMD &&
7737     if (AOP_TYPE(result) == AOP_PCODE &&
7738         PIC_IS_DATA_PTR(ptype) &&
7739         !IS_BITVAR (retype) &&
7740         !IS_BITVAR (letype)) {
7741         genDataPointerSet (right,result,ic);
7742         freeAsmop(result,NULL,ic,TRUE);
7743         return;
7744     }
7745 #endif
7746
7747     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7748     aopOp(right,ic,FALSE);
7749     DEBUGpic14_AopType(__LINE__,NULL,right,result);
7750
7751     /* Check if can access directly instead of via a pointer */
7752     if ((AOP_TYPE(result) == AOP_PCODE)
7753         && (AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
7754         && (AOP_SIZE(right) == 1))
7755     {
7756         direct = 1;
7757     }
7758
7759     if (IS_BITFIELD (letype))
7760     {
7761       genPackBits (letype, result, right, direct?-1:POINTER);
7762       return;
7763     }
7764
7765     /* If the pointer value is not in a the FSR then need to put it in */
7766     /* Must set/reset IRP bit for use with FSR. */
7767     /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
7768     if (!direct)
7769         setup_fsr (result);
7770
7771     {
7772         /* we have can just get the values */
7773         int size = AOP_SIZE(right);
7774         int offset = 0 ;
7775
7776         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7777         while (size--) {
7778             char *l = aopGet(AOP(right),offset,FALSE,TRUE);
7779             if (*l == '@' ) {
7780                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
7781             } else {
7782                 if (AOP_TYPE(right) == AOP_LIT) {
7783                     emitpcode(POC_MOVLW,popGet(AOP(right),offset));
7784                 } else {
7785                     emitpcode(POC_MOVFW,popGet(AOP(right),offset));
7786                 }
7787                 if (direct)
7788                     emitpcode(POC_MOVWF,popGet(AOP(result),0));
7789                 else
7790                     emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
7791             }
7792             if (size && !direct)
7793                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
7794             offset++;
7795         }
7796     }
7797
7798     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7799     /* now some housekeeping stuff */
7800     if (aop) {
7801         /* we had to allocate for this iCode */
7802         freeAsmop(NULL,aop,ic,TRUE);
7803     } else {
7804         /* we did not allocate which means left
7805         already in a pointer register, then
7806         if size > 0 && this could be used again
7807         we have to point it back to where it
7808         belongs */
7809         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7810         if (AOP_SIZE(right) > 1 &&
7811             !OP_SYMBOL(result)->remat &&
7812             ( OP_SYMBOL(result)->liveTo > ic->seq ||
7813             ic->depth )) {
7814             int size = AOP_SIZE(right) - 1;
7815             while (size--)
7816                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
7817         }
7818     }
7819
7820     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7821     /* done */
7822
7823     freeAsmop(right,NULL,ic,TRUE);
7824     freeAsmop(result,NULL,ic,TRUE);
7825 }
7826
7827 /*-----------------------------------------------------------------*/
7828 /* genGenPointerSet - set value from generic pointer space         */
7829 /*-----------------------------------------------------------------*/
7830 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
7831 {
7832     sym_link *retype = getSpec(operandType(result));
7833
7834     FENTRY;
7835     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7836     aopOp(right,ic,FALSE);
7837     aopOp(result,ic,FALSE);
7838
7839
7840     DEBUGpic14_AopType(__LINE__,right,NULL,result);
7841
7842     if (IS_BITFIELD(retype))
7843     {
7844       genPackBits (retype, result, right, GPOINTER);
7845       return;
7846     }
7847
7848     {
7849       /* emit call to __gptrput */
7850       char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
7851       int size = AOP_SIZE(right);
7852       int idx = 0;
7853
7854       /* The following assertion fails for
7855        *   struct foo { char a; char b; } bar;
7856        *   void demo(struct foo *dst, char c) { dst->b = c; }
7857        * as size will be 1 (sizeof(c)), whereas dst->b will be accessed
7858        * using (((char *)dst)+1), whose OP_SYM_ETYPE still is struct foo
7859        * of size 2.
7860        * The frontend seems to guarantee that IC_LEFT has the correct size,
7861        * it works fine both for larger and smaller types of `char c'.
7862        * */
7863       //assert (size == getSize(OP_SYM_ETYPE(result)));
7864       assert (size > 0 && size <= 4);
7865
7866       /* pass arguments */
7867       /* - value (MSB in Gstack_base_addr-2, growing downwards) */
7868       {
7869         int off = size;
7870         idx = 2;
7871         while (off--)
7872         {
7873           mov2w_op (right, off);
7874           emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
7875         }
7876         idx = 0;
7877       }
7878       /* - address */
7879       assert (AOP_SIZE(result) == 3);
7880       mov2w(AOP(result), 0);
7881       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
7882       mov2w(AOP(result), 1);
7883       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
7884       mov2w(AOP(result), 2);
7885       call_libraryfunc (func[size]);
7886     }
7887
7888     freeAsmop(right,NULL,ic,TRUE);
7889     freeAsmop(result,NULL,ic,TRUE);
7890 }
7891
7892 /*-----------------------------------------------------------------*/
7893 /* genPointerSet - stores the value into a pointer location        */
7894 /*-----------------------------------------------------------------*/
7895 static void genPointerSet (iCode *ic)
7896 {
7897     operand *right, *result ;
7898     sym_link *type, *etype;
7899     int p_type;
7900
7901     FENTRY;
7902     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7903
7904     right = IC_RIGHT(ic);
7905     result = IC_RESULT(ic) ;
7906
7907     /* depending on the type of pointer we need to
7908     move it to the correct pointer register */
7909     type = operandType(result);
7910     etype = getSpec(type);
7911     /* if left is of type of pointer then it is simple */
7912     if (IS_PTR(type) && !IS_FUNC(type->next)) {
7913         p_type = DCL_TYPE(type);
7914     }
7915     else {
7916         /* we have to go by the storage class */
7917         p_type = PTR_TYPE(SPEC_OCLS(etype));
7918
7919         /*  if (SPEC_OCLS(etype)->codesp ) { */
7920         /*      p_type = CPOINTER ;  */
7921         /*  } */
7922         /*  else */
7923         /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7924         /*    p_type = FPOINTER ; */
7925         /*      else */
7926         /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7927         /*        p_type = PPOINTER ; */
7928         /*    else */
7929         /*        if (SPEC_OCLS(etype) == idata ) */
7930         /*      p_type = IPOINTER ; */
7931         /*        else */
7932         /*      p_type = POINTER ; */
7933     }
7934
7935     /* now that we have the pointer type we assign
7936     the pointer values */
7937     switch (p_type) {
7938
7939     case POINTER:
7940     case FPOINTER:
7941     //case IPOINTER:
7942         genNearPointerSet (right,result,ic);
7943         break;
7944 /*
7945     case PPOINTER:
7946         genPagedPointerSet (right,result,ic);
7947         break;
7948
7949     case FPOINTER:
7950         genFarPointerSet (right,result,ic);
7951         break;
7952 */
7953     case GPOINTER:
7954         genGenPointerSet (right,result,ic);
7955         break;
7956
7957     default:
7958         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7959             "genPointerSet: illegal pointer type");
7960     }
7961 }
7962
7963 /*-----------------------------------------------------------------*/
7964 /* genIfx - generate code for Ifx statement                        */
7965 /*-----------------------------------------------------------------*/
7966 static void genIfx (iCode *ic, iCode *popIc)
7967 {
7968     operand *cond = IC_COND(ic);
7969     int isbit =0;
7970
7971     FENTRY;
7972     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7973
7974     aopOp(cond,ic,FALSE);
7975
7976     /* get the value into acc */
7977     if (AOP_TYPE(cond) != AOP_CRY)
7978         pic14_toBoolean(cond);
7979     else
7980         isbit = 1;
7981
7982     /* if there was something to be popped then do it */
7983     if (popIc)
7984         genIpop(popIc);
7985
7986     if (isbit)
7987     {
7988         /* This assumes that CARRY is set iff cond is true */
7989         if (IC_TRUE(ic))
7990         {
7991             assert (!IC_FALSE(ic));
7992             emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
7993             //emitSKPNC;
7994             emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
7995         } else {
7996             assert (IC_FALSE(ic));
7997             emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
7998             //emitSKPC;
7999             emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
8000         }
8001         if (0)
8002         {
8003             static int hasWarned = 0;
8004             if (!hasWarned)
8005             {
8006                 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
8007                 hasWarned = 1;
8008             }
8009         }
8010     }
8011     else
8012     {
8013         /* now Z is set iff !cond */
8014         if (IC_TRUE(ic))
8015         {
8016             assert (!IC_FALSE(ic));
8017             emitSKPZ;
8018             emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
8019         } else {
8020             emitSKPNZ;
8021             emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
8022         }
8023     }
8024
8025     ic->generated = 1;
8026
8027     /* the result is now in the accumulator */
8028     freeAsmop(cond,NULL,ic,TRUE);
8029 }
8030
8031 /*-----------------------------------------------------------------*/
8032 /* genAddrOf - generates code for address of                       */
8033 /*-----------------------------------------------------------------*/
8034 static void genAddrOf (iCode *ic)
8035 {
8036     operand *right, *result, *left;
8037     int size, offset ;
8038
8039     FENTRY;
8040     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8041
8042
8043     //aopOp(IC_RESULT(ic),ic,FALSE);
8044
8045     aopOp((left=IC_LEFT(ic)),ic,FALSE);
8046     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
8047     aopOp((result=IC_RESULT(ic)),ic,TRUE);
8048
8049     DEBUGpic14_AopType(__LINE__,left,right,result);
8050     assert (IS_SYMOP (left));
8051
8052     /* sanity check: generic pointers to code space are not yet supported,
8053      * pionters to codespace must not be assigned addresses of __data values. */
8054  #if 0
8055     fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
8056     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)));
8057     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)));
8058     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)));
8059     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)));
8060 #endif
8061
8062     if (IS_SYMOP(result) && IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
8063       fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
8064         IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
8065         OP_SYMBOL(left)->name);
8066     } else if (IS_SYMOP(result) && !IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
8067       fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
8068         IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
8069         OP_SYMBOL(left)->name);
8070     }
8071
8072     size = AOP_SIZE(IC_RESULT(ic));
8073     if (IS_SYMOP(result) && IS_GENPTR(OP_SYM_TYPE(result))) {
8074         /* strip tag */
8075         if (size > GPTRSIZE-1) size = GPTRSIZE-1;
8076     }
8077     offset = 0;
8078
8079     while (size--) {
8080         /* fixing bug #863624, reported from (errolv) */
8081         emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
8082         emitpcode(POC_MOVWF, popGet(AOP(result), offset));
8083
8084 #if 0
8085         emitpcode(POC_MOVLW, popGet(AOP(left),offset));
8086         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8087 #endif
8088         offset++;
8089     }
8090
8091     if (IS_SYMOP(result) && IS_GENPTR(OP_SYM_TYPE(result)))
8092     {
8093         /* provide correct tag */
8094         int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
8095         emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
8096         movwf (AOP(result), 2);
8097     }
8098
8099     freeAsmop(left,NULL,ic,FALSE);
8100     freeAsmop(result,NULL,ic,TRUE);
8101
8102 }
8103
8104 #if 0
8105 /*-----------------------------------------------------------------*/
8106 /* genFarFarAssign - assignment when both are in far space         */
8107 /*-----------------------------------------------------------------*/
8108 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
8109 {
8110     int size = AOP_SIZE(right);
8111     int offset = 0;
8112     char *l ;
8113     /* first push the right side on to the stack */
8114     while (size--) {
8115         l = aopGet(AOP(right),offset++,FALSE,FALSE);
8116         MOVA(l);
8117         pic14_emitcode ("push","acc");
8118     }
8119
8120     freeAsmop(right,NULL,ic,FALSE);
8121     /* now assign DPTR to result */
8122     aopOp(result,ic,FALSE);
8123     size = AOP_SIZE(result);
8124     while (size--) {
8125         pic14_emitcode ("pop","acc");
8126         aopPut(AOP(result),"a",--offset);
8127     }
8128     freeAsmop(result,NULL,ic,FALSE);
8129
8130 }
8131 #endif
8132
8133 /*-----------------------------------------------------------------*/
8134 /* genAssign - generate code for assignment                        */
8135 /*-----------------------------------------------------------------*/
8136 static void genAssign (iCode *ic)
8137 {
8138     operand *result, *right;
8139     int size, offset,know_W;
8140     unsigned long lit = 0L;
8141
8142     result = IC_RESULT(ic);
8143     right  = IC_RIGHT(ic) ;
8144
8145     FENTRY;
8146     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8147
8148     /* if they are the same */
8149     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
8150         return ;
8151
8152     aopOp(right,ic,FALSE);
8153     aopOp(result,ic,TRUE);
8154
8155     DEBUGpic14_AopType(__LINE__,NULL,right,result);
8156
8157     /* if they are the same registers */
8158     if (pic14_sameRegs(AOP(right),AOP(result)))
8159         goto release;
8160
8161     /* special case: assign from __code */
8162     if (!IS_ITEMP(right)                /* --> iTemps never reside in __code */
8163         && IS_SYMOP (right)         /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
8164         && !IS_FUNC(OP_SYM_TYPE(right))     /* --> we would want its address instead of the first instruction */
8165         && !IS_CODEPTR(OP_SYM_TYPE(right))  /* --> get symbols address instread */
8166         && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
8167     {
8168       emitpComment ("genAssign from CODESPACE");
8169       genConstPointerGet (right, result, ic);
8170       goto release;
8171     }
8172
8173     /* just for symmetry reasons... */
8174     if (!IS_ITEMP(result)
8175         && IS_SYMOP (result)
8176         && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
8177     {
8178       assert ( !"cannot write to CODESPACE" );
8179     }
8180
8181     /* if the result is a bit */
8182     if (AOP_TYPE(result) == AOP_CRY) {
8183
8184     /* if the right size is a literal then
8185         we know what the value is */
8186         if (AOP_TYPE(right) == AOP_LIT) {
8187
8188             emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8189                 popGet(AOP(result),0));
8190
8191             if (((int) operandLitValue(right)))
8192                 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
8193                 AOP(result)->aopu.aop_dir,
8194                 AOP(result)->aopu.aop_dir);
8195             else
8196                 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
8197                 AOP(result)->aopu.aop_dir,
8198                 AOP(result)->aopu.aop_dir);
8199             goto release;
8200         }
8201
8202         /* the right is also a bit variable */
8203         if (AOP_TYPE(right) == AOP_CRY) {
8204             emitpcode(POC_BCF,    popGet(AOP(result),0));
8205             emitpcode(POC_BTFSC,  popGet(AOP(right),0));
8206             emitpcode(POC_BSF,    popGet(AOP(result),0));
8207
8208             pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
8209                 AOP(result)->aopu.aop_dir,
8210                 AOP(result)->aopu.aop_dir);
8211             pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
8212                 AOP(right)->aopu.aop_dir,
8213                 AOP(right)->aopu.aop_dir);
8214             pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
8215                 AOP(result)->aopu.aop_dir,
8216                 AOP(result)->aopu.aop_dir);
8217             goto release ;
8218         }
8219
8220         /* we need to or */
8221         emitpcode(POC_BCF,    popGet(AOP(result),0));
8222         pic14_toBoolean(right);
8223         emitSKPZ;
8224         emitpcode(POC_BSF,    popGet(AOP(result),0));
8225         //aopPut(AOP(result),"a",0);
8226         goto release ;
8227     }
8228
8229     /* bit variables done */
8230     /* general case */
8231     size = AOP_SIZE(result);
8232     offset = 0 ;
8233     if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
8234         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8235         if(aopIdx(AOP(result),0) == 4) {
8236             DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8237             emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8238             emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8239             goto release;
8240         } else
8241             DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
8242     }
8243
8244     know_W=-1;
8245     while (size--) {
8246
8247         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8248         if(AOP_TYPE(right) == AOP_LIT) {
8249             lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
8250             if(lit&0xff) {
8251                 if(know_W != (int)(lit&0xff))
8252                     emitpcode(POC_MOVLW,popGetLit(lit&0xff));
8253                 know_W = lit&0xff;
8254                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8255             } else
8256                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
8257
8258         } else if (AOP_TYPE(right) == AOP_CRY) {
8259             emitpcode(POC_CLRF, popGet(AOP(result),offset));
8260             if(offset == 0) {
8261                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
8262                 emitpcode(POC_INCF, popGet(AOP(result),0));
8263             }
8264         } else {
8265             mov2w_op (right, offset);
8266             emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8267         }
8268
8269         offset++;
8270     }
8271
8272
8273 release:
8274     freeAsmop (right,NULL,ic,FALSE);
8275     freeAsmop (result,NULL,ic,TRUE);
8276 }
8277
8278 /*-----------------------------------------------------------------*/
8279 /* genJumpTab - genrates code for jump table                       */
8280 /*-----------------------------------------------------------------*/
8281 static void genJumpTab (iCode *ic)
8282 {
8283     symbol *jtab;
8284     char *l;
8285
8286     FENTRY;
8287     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8288
8289     aopOp(IC_JTCOND(ic),ic,FALSE);
8290     /* get the condition into accumulator */
8291     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
8292     MOVA(l);
8293     /* multiply by three */
8294     pic14_emitcode("add","a,acc");
8295     pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
8296
8297     jtab = newiTempLabel(NULL);
8298     pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
8299     pic14_emitcode("jmp","@a+dptr");
8300     pic14_emitcode("","%05d_DS_:",jtab->key+100);
8301
8302     emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
8303     emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
8304     emitpcode(POC_MOVLW, popGetLabel(jtab->key));
8305     emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
8306     emitSKPNC;
8307     emitpcode(POC_INCF, popCopyReg(&pc_pclath));
8308     emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
8309     emitpLabel(jtab->key);
8310
8311     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8312
8313     /* now generate the jump labels */
8314     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8315     jtab = setNextItem(IC_JTLABELS(ic))) {
8316         pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
8317         emitpcode(POC_GOTO,popGetLabel(jtab->key));
8318
8319     }
8320
8321 }
8322
8323 /*-----------------------------------------------------------------*/
8324 /* genMixedOperation - gen code for operators between mixed types  */
8325 /*-----------------------------------------------------------------*/
8326 /*
8327 TSD - Written for the PIC port - but this unfortunately is buggy.
8328 This routine is good in that it is able to efficiently promote
8329 types to different (larger) sizes. Unfortunately, the temporary
8330 variables that are optimized out by this routine are sometimes
8331 used in other places. So until I know how to really parse the
8332 iCode tree, I'm going to not be using this routine :(.
8333 */
8334 static int genMixedOperation (iCode *ic)
8335 {
8336     FENTRY;
8337 #if 0
8338     operand *result = IC_RESULT(ic);
8339     sym_link *ctype = operandType(IC_LEFT(ic));
8340     operand *right = IC_RIGHT(ic);
8341     int ret = 0;
8342     int big,small;
8343     int offset;
8344
8345     iCode *nextic;
8346     operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
8347
8348     pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
8349
8350     nextic = ic->next;
8351     if(!nextic)
8352         return 0;
8353
8354     nextright = IC_RIGHT(nextic);
8355     nextleft  = IC_LEFT(nextic);
8356     nextresult = IC_RESULT(nextic);
8357
8358     aopOp(right,ic,FALSE);
8359     aopOp(result,ic,FALSE);
8360     aopOp(nextright,  nextic, FALSE);
8361     aopOp(nextleft,   nextic, FALSE);
8362     aopOp(nextresult, nextic, FALSE);
8363
8364     if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
8365
8366         operand *t = right;
8367         right = nextright;
8368         nextright = t;
8369
8370         pic14_emitcode(";remove right +","");
8371
8372     } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
8373     /*
8374     operand *t = right;
8375     right = nextleft;
8376     nextleft = t;
8377         */
8378         pic14_emitcode(";remove left +","");
8379     } else
8380         return 0;
8381
8382     big = AOP_SIZE(nextleft);
8383     small = AOP_SIZE(nextright);
8384
8385     switch(nextic->op) {
8386
8387     case '+':
8388         pic14_emitcode(";optimize a +","");
8389         /* if unsigned or not an integral type */
8390         if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
8391             pic14_emitcode(";add a bit to something","");
8392         } else {
8393
8394             pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
8395
8396             if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
8397                 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
8398                 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
8399             } else
8400                 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
8401
8402             offset = 0;
8403             while(--big) {
8404
8405                 offset++;
8406
8407                 if(--small) {
8408                     if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8409                         pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8410                         pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8411                     }
8412
8413                     pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8414                     emitSKPNC;
8415                     pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
8416                         AOP(IC_RIGHT(nextic))->aopu.aop_dir,
8417                         AOP(IC_RIGHT(nextic))->aopu.aop_dir);
8418                     pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8419                     pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
8420
8421                 } else {
8422                     pic14_emitcode("rlf","known_zero,w");
8423
8424                     /*
8425                     if right is signed
8426                     btfsc  right,7
8427                     addlw ff
8428                     */
8429                     if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8430                         pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8431                         pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8432                     } else {
8433                         pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8434                     }
8435                 }
8436             }
8437             ret = 1;
8438         }
8439     }
8440     ret = 1;
8441
8442 release:
8443     freeAsmop(right,NULL,ic,TRUE);
8444     freeAsmop(result,NULL,ic,TRUE);
8445     freeAsmop(nextright,NULL,ic,TRUE);
8446     freeAsmop(nextleft,NULL,ic,TRUE);
8447     if(ret)
8448         nextic->generated = 1;
8449
8450     return ret;
8451 #else
8452     return 0;
8453 #endif
8454 }
8455 /*-----------------------------------------------------------------*/
8456 /* genCast - gen code for casting                                  */
8457 /*-----------------------------------------------------------------*/
8458 static void genCast (iCode *ic)
8459 {
8460     operand *result = IC_RESULT(ic);
8461     sym_link *restype = operandType(result);
8462     sym_link *rtype = operandType(IC_RIGHT(ic));
8463     operand *right = IC_RIGHT(ic);
8464     int size, offset ;
8465
8466     FENTRY;
8467     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
8468     /* if they are equivalent then do nothing */
8469     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8470         return ;
8471
8472     aopOp(right,ic,FALSE) ;
8473     aopOp(result,ic,FALSE);
8474
8475     DEBUGpic14_AopType(__LINE__,NULL,right,result);
8476
8477     /* if the result is a bit */
8478     if (AOP_TYPE(result) == AOP_CRY) {
8479         assert(!"assigning to bit variables is not supported");
8480     }
8481
8482     if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
8483         int offset = 1;
8484         size = AOP_SIZE(result);
8485
8486         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
8487
8488         emitpcode(POC_CLRF,   popGet(AOP(result),0));
8489         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
8490         emitpcode(POC_INCF,   popGet(AOP(result),0));
8491
8492         while (size--)
8493             emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
8494
8495         goto release;
8496     }
8497
8498     if (IS_PTR(restype))
8499     {
8500       operand *result = IC_RESULT(ic);
8501       //operand *left = IC_LEFT(ic);
8502       operand *right = IC_RIGHT(ic);
8503       int tag = 0xff;
8504
8505       /* copy common part */
8506       int max, size = AOP_SIZE(result);
8507       if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
8508       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
8509
8510       /* warn if we discard generic opinter tag */
8511       if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
8512       {
8513         //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
8514       } // if
8515
8516       max = size;
8517       while (size--)
8518       {
8519         mov2w_op (right, size);
8520         movwf (AOP(result), size);
8521       } // while
8522
8523       /* upcast into generic pointer type? */
8524       if (IS_GENPTR(restype)
8525         && (size < AOP_SIZE(result))
8526         && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
8527       {
8528         //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
8529         if (IS_PTR(rtype))
8530         {
8531           switch (DCL_TYPE(rtype))
8532           {
8533           case POINTER: /* __data */
8534           case FPOINTER:    /* __data */
8535         assert (AOP_SIZE(right) == 2);
8536         tag = GPTRTAG_DATA;
8537         break;
8538
8539           case CPOINTER:    /* __code */
8540         assert (AOP_SIZE(right) == 2);
8541         tag = GPTRTAG_CODE;
8542         break;
8543
8544           case GPOINTER:    /* unknown destination, __data or __code */
8545         /* assume __data space (address of immediate) */
8546         assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
8547         if (AOP(right)->code)
8548           tag = GPTRTAG_CODE;
8549         else
8550           tag = GPTRTAG_DATA;
8551         break;
8552
8553           default:
8554         assert (!"unhandled pointer type");
8555           } // switch
8556         } else {
8557           /* convert other values into pointers to __data space */
8558           tag = GPTRTAG_DATA;
8559         }
8560
8561         assert (AOP_SIZE(result) == 3);
8562         if (tag == 0) {
8563           emitpcode(POC_CLRF, popGet(AOP(result), 2));
8564         } else {
8565           emitpcode(POC_MOVLW, popGetLit(tag));
8566           movwf(AOP(result), 2);
8567         }
8568       } else {
8569         addSign(result, max, 0);
8570       } // if
8571       goto release;
8572     }
8573
8574     /* if they are the same size : or less */
8575     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8576
8577         /* if they are in the same place */
8578         if (pic14_sameRegs(AOP(right),AOP(result)))
8579             goto release;
8580
8581         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
8582         if (IS_PTR_CONST(rtype))
8583             DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
8584         if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
8585             DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
8586
8587         if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
8588             emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
8589             emitpcode(POC_MOVWF, popGet(AOP(result),0));
8590             emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
8591             emitpcode(POC_MOVWF, popGet(AOP(result),1));
8592             if(AOP_SIZE(result) <2)
8593                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
8594
8595         } else {
8596
8597             /* if they in different places then copy */
8598             size = AOP_SIZE(result);
8599             offset = 0 ;
8600             while (size--) {
8601                 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8602                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8603
8604                 //aopPut(AOP(result),
8605                 // aopGet(AOP(right),offset,FALSE,FALSE),
8606                 // offset);
8607
8608                 offset++;
8609             }
8610         }
8611         goto release;
8612     }
8613
8614     /* so we now know that the size of destination is greater
8615     than the size of the source.
8616     Now, if the next iCode is an operator then we might be
8617     able to optimize the operation without performing a cast.
8618     */
8619     if(0 && genMixedOperation(ic)) {
8620         /* XXX: cannot optimize: must copy regs! */
8621         goto release;
8622     }
8623
8624     /* we move to result for the size of source */
8625     size = AOP_SIZE(right);
8626     offset = 0 ;
8627     while (size--) {
8628         emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
8629         emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
8630         offset++;
8631     }
8632
8633     addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
8634
8635 release:
8636     freeAsmop(right,NULL,ic,TRUE);
8637     freeAsmop(result,NULL,ic,TRUE);
8638
8639 }
8640
8641 /*-----------------------------------------------------------------*/
8642 /* genDjnz - generate decrement & jump if not zero instrucion      */
8643 /*-----------------------------------------------------------------*/
8644 static int genDjnz (iCode *ic, iCode *ifx)
8645 {
8646     symbol *lbl, *lbl1;
8647     FENTRY;
8648     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8649
8650     if (!ifx)
8651         return 0;
8652
8653         /* if the if condition has a false label
8654     then we cannot save */
8655     if (IC_FALSE(ifx))
8656         return 0;
8657
8658         /* if the minus is not of the form
8659     a = a - 1 */
8660     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8661         !IS_OP_LITERAL(IC_RIGHT(ic)))
8662         return 0;
8663
8664     if (operandLitValue(IC_RIGHT(ic)) != 1)
8665         return 0;
8666
8667         /* if the size of this greater than one then no
8668     saving */
8669     if (getSize(operandType(IC_RESULT(ic))) > 1)
8670         return 0;
8671
8672     /* otherwise we can save BIG */
8673     lbl = newiTempLabel(NULL);
8674     lbl1= newiTempLabel(NULL);
8675
8676     aopOp(IC_RESULT(ic),ic,FALSE);
8677
8678     emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
8679     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
8680
8681     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8682     ifx->generated = 1;
8683     return 1;
8684 }
8685
8686 /*-----------------------------------------------------------------*/
8687 /* genReceive - generate code for a receive iCode                  */
8688 /*-----------------------------------------------------------------*/
8689 static void genReceive (iCode *ic)
8690 {
8691     FENTRY;
8692     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8693
8694     if (isOperandInFarSpace(IC_RESULT(ic)) &&
8695         ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8696         IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8697
8698         int size = getSize(operandType(IC_RESULT(ic)));
8699         int offset =  fReturnSizePic - size;
8700         while (size--) {
8701             pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
8702                 fReturn[fReturnSizePic - offset - 1] : "acc"));
8703             offset++;
8704         }
8705         aopOp(IC_RESULT(ic),ic,FALSE);
8706         size = AOP_SIZE(IC_RESULT(ic));
8707         offset = 0;
8708         while (size--) {
8709             pic14_emitcode ("pop","acc");
8710             aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8711         }
8712
8713     } else {
8714         _G.accInUse++;
8715         aopOp(IC_RESULT(ic),ic,FALSE);
8716         _G.accInUse--;
8717         GpsuedoStkPtr = ic->parmBytes; // address used arg on stack
8718         assignResultValue(IC_RESULT(ic));
8719     }
8720
8721     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8722 }
8723
8724 /*-----------------------------------------------------------------*/
8725 /* genDummyRead - generate code for dummy read of volatiles        */
8726 /*-----------------------------------------------------------------*/
8727 static void
8728 genDummyRead (iCode * ic)
8729 {
8730     FENTRY;
8731     pic14_emitcode ("; genDummyRead","");
8732     pic14_emitcode ("; not implemented","");
8733
8734     ic = ic;
8735 }
8736
8737 /*-----------------------------------------------------------------*/
8738 /* genpic14Code - generate code for pic14 based controllers        */
8739 /*-----------------------------------------------------------------*/
8740 /*
8741 * At this point, ralloc.c has gone through the iCode and attempted
8742 * to optimize in a way suitable for a PIC. Now we've got to generate
8743 * PIC instructions that correspond to the iCode.
8744 *
8745 * Once the instructions are generated, we'll pass through both the
8746 * peep hole optimizer and the pCode optimizer.
8747 *-----------------------------------------------------------------*/
8748
8749 void genpic14Code (iCode *lic)
8750 {
8751     iCode *ic;
8752     int cln = 0;
8753     const char *cline;
8754
8755     FENTRY;
8756     lineHead = lineCurr = NULL;
8757
8758     pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
8759     addpBlock(pb);
8760
8761     /* if debug information required */
8762     if (options.debug && debugFile && currFunc) {
8763         debugFile->writeFunction (currFunc, lic);
8764     }
8765
8766
8767     for (ic = lic ; ic ; ic = ic->next ) {
8768
8769         //DEBUGpic14_emitcode(";ic","");
8770         //fprintf (stderr, "in ic loop\n");
8771         //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
8772         //ic->lineno, printCLine(ic->filename, ic->lineno));
8773
8774         if (!options.noCcodeInAsm && (cln != ic->lineno)) {
8775           cln = ic->lineno;
8776           //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
8777           cline = printCLine (ic->filename, ic->lineno);
8778           if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
8779           addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
8780           //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
8781         }
8782
8783         if (options.iCodeInAsm) {
8784           const char *iLine = printILine(ic);
8785           emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
8786                   dbuf_free(iLine);
8787         }
8788         /* if the result is marked as
8789         spilt and rematerializable or code for
8790         this has already been generated then
8791         do nothing */
8792         if (resultRemat(ic) || ic->generated )
8793             continue ;
8794
8795         /* depending on the operation */
8796         switch (ic->op) {
8797         case '!' :
8798             genNot(ic);
8799             break;
8800
8801         case '~' :
8802             genCpl(ic);
8803             break;
8804
8805         case UNARYMINUS:
8806             genUminus (ic);
8807             break;
8808
8809         case IPUSH:
8810             genIpush (ic);
8811             break;
8812
8813         case IPOP:
8814             /* IPOP happens only when trying to restore a
8815             spilt live range, if there is an ifx statement
8816             following this pop then the if statement might
8817             be using some of the registers being popped which
8818             would destory the contents of the register so
8819             we need to check for this condition and handle it */
8820             if (ic->next            &&
8821                 ic->next->op == IFX &&
8822                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
8823                 genIfx (ic->next,ic);
8824             else
8825                 genIpop (ic);
8826             break;
8827
8828         case CALL:
8829             genCall (ic);
8830             break;
8831
8832         case PCALL:
8833             genPcall (ic);
8834             break;
8835
8836         case FUNCTION:
8837             genFunction (ic);
8838             break;
8839
8840         case ENDFUNCTION:
8841             genEndFunction (ic);
8842             break;
8843
8844         case RETURN:
8845             genRet (ic);
8846             break;
8847
8848         case LABEL:
8849             genLabel (ic);
8850             break;
8851
8852         case GOTO:
8853             genGoto (ic);
8854             break;
8855
8856         case '+' :
8857             genPlus (ic) ;
8858             break;
8859
8860         case '-' :
8861             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8862                 genMinus (ic);
8863             break;
8864
8865         case '*' :
8866             genMult (ic);
8867             break;
8868
8869         case '/' :
8870             genDiv (ic) ;
8871             break;
8872
8873         case '%' :
8874             genMod (ic);
8875             break;
8876
8877         case '>' :
8878             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8879             break;
8880
8881         case '<' :
8882             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8883             break;
8884
8885         case LE_OP:
8886         case GE_OP:
8887         case NE_OP:
8888
8889             /* note these two are xlated by algebraic equivalence
8890             during parsing SDCC.y */
8891             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8892                 "got '>=' or '<=' shouldn't have come here");
8893             break;
8894
8895         case EQ_OP:
8896             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8897             break;
8898
8899         case AND_OP:
8900             genAndOp (ic);
8901             break;
8902
8903         case OR_OP:
8904             genOrOp (ic);
8905             break;
8906
8907         case '^' :
8908             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8909             break;
8910
8911         case '|' :
8912             genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8913             break;
8914
8915         case BITWISEAND:
8916             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8917             break;
8918
8919         case INLINEASM:
8920             genInline (ic);
8921             break;
8922
8923         case RRC:
8924             genRRC (ic);
8925             break;
8926
8927         case RLC:
8928             genRLC (ic);
8929             break;
8930
8931         case GETHBIT:
8932             genGetHbit (ic);
8933             break;
8934
8935         case LEFT_OP:
8936             genLeftShift (ic);
8937             break;
8938
8939         case RIGHT_OP:
8940             genRightShift (ic);
8941             break;
8942
8943         case GET_VALUE_AT_ADDRESS:
8944             genPointerGet(ic);
8945             break;
8946
8947         case '=' :
8948             if (POINTER_SET(ic))
8949                 genPointerSet(ic);
8950             else
8951                 genAssign(ic);
8952             break;
8953
8954         case IFX:
8955             genIfx (ic,NULL);
8956             break;
8957
8958         case ADDRESS_OF:
8959             genAddrOf (ic);
8960             break;
8961
8962         case JUMPTABLE:
8963             genJumpTab (ic);
8964             break;
8965
8966         case CAST:
8967             genCast (ic);
8968             break;
8969
8970         case RECEIVE:
8971             genReceive(ic);
8972             break;
8973
8974         case SEND:
8975             addSet(&_G.sendSet,ic);
8976             break;
8977
8978         case DUMMY_READ_VOLATILE:
8979             genDummyRead (ic);
8980             break;
8981
8982         default :
8983             fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
8984             ic = ic;
8985             break;
8986         }
8987     }
8988
8989
8990     /* now we are ready to call the
8991     peep hole optimizer */
8992     if (!options.nopeep) {
8993         peepHole (&lineHead);
8994     }
8995     /* now do the actual printing */
8996     printLine (lineHead,codeOutBuf);
8997
8998 #ifdef PCODE_DEBUG
8999     DFPRINTF((stderr,"printing pBlock\n\n"));
9000     printpBlock(stdout,pb);
9001 #endif
9002
9003     return;
9004 }
9005
9006 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
9007  * (meaning: representing its own address) or not (referencing its contents).
9008  * This can only be decided based on the operand's type. */
9009 static int
9010 aop_isLitLike (asmop *aop)
9011 {
9012   assert (aop);
9013   if (aop->type == AOP_LIT) return 1;
9014   if (aop->type == AOP_IMMD) return 1;
9015   if ((aop->type == AOP_PCODE) &&
9016         ((aop->aopu.pcop->type == PO_LITERAL)))
9017   {
9018     /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
9019      * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
9020     return 1;
9021   }
9022   return 0;
9023 }
9024
9025 int
9026 op_isLitLike (operand *op)
9027 {
9028   assert (op);
9029   if (aop_isLitLike (AOP(op))) return 1;
9030   if (IS_SYMOP(op) && IS_FUNC(OP_SYM_TYPE(op))) return 1;
9031   if (IS_SYMOP(op) && IS_PTR(OP_SYM_TYPE(op))
9032         && (AOP_TYPE(op) == AOP_PCODE)
9033         && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
9034     return 1;
9035   }
9036
9037   return 0;
9038 }
9039