04b5cf9acef4fbb4123d86d2f45c6f1706a07b73
[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   }
222   va_end (va);
223 }
224
225 void emitpLabel(int key)
226 {
227     addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
228 }
229
230 /* gen.h defines a macro emitpcode that should be used to call emitpcode
231  * as this allows for easy debugging (ever asked the question: where was
232  * this instruction geenrated? Here is the answer... */
233 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
234 {
235     if(pcop)
236         addpCode2pBlock(pb,newpCode(poc,pcop));
237     else {
238         static int has_warned = 0;
239
240         DEBUGpic14_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
241         if (!has_warned) {
242             has_warned = 1;
243             fprintf( stderr, "WARNING: encountered NULL pcop--this is probably a compiler bug...\n" );
244         }
245     }
246 }
247
248 static void emitpcodeNULLop(PIC_OPCODE poc)
249 {
250     addpCode2pBlock(pb,newpCode(poc,NULL));
251 }
252
253 /*-----------------------------------------------------------------*/
254 /* pic14_emitcode - writes the code into a file : for now it is simple    */
255 /*-----------------------------------------------------------------*/
256 void pic14_emitcode (char *inst,char *fmt, ...)
257 {
258     va_list ap;
259     char lb[INITIAL_INLINEASM];
260     char *lbp = lb;
261
262     va_start(ap,fmt);
263
264     if (inst && *inst) {
265         if (fmt && *fmt)
266             sprintf(lb,"%s\t",inst);
267         else
268             sprintf(lb,"%s",inst);
269         vsprintf(lb+(strlen(lb)),fmt,ap);
270     }  else
271         vsprintf(lb,fmt,ap);
272
273     while (isspace(*lbp)) lbp++;
274
275     if (lbp && *lbp)
276         lineCurr = (lineCurr ?
277         connectLine(lineCurr,newLineNode(lb)) :
278     (lineHead = newLineNode(lb)));
279     lineCurr->isInline = _G.inLine;
280     lineCurr->isDebug  = _G.debugLine;
281     lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
282
283     if(debug_verbose)
284         addpCode2pBlock(pb,newpCodeCharP(lb));
285
286     va_end(ap);
287 }
288
289 /*-----------------------------------------------------------------*/
290 /* pic14_emitDebuggerSymbol - associate the current code location  */
291 /*   with a debugger symbol                                        */
292 /*-----------------------------------------------------------------*/
293 void
294 pic14_emitDebuggerSymbol (char * debugSym)
295 {
296     _G.debugLine = 1;
297     pic14_emitcode ("", ";%s ==.", debugSym);
298     _G.debugLine = 0;
299 }
300
301 /*-----------------------------------------------------------------*/
302 /* newAsmop - creates a new asmOp                                  */
303 /*-----------------------------------------------------------------*/
304 static asmop *newAsmop (short type)
305 {
306     asmop *aop;
307
308     aop = Safe_calloc(1,sizeof(asmop));
309     aop->type = type;
310     return aop;
311 }
312
313 /*-----------------------------------------------------------------*/
314 /* resolveIfx - converts an iCode ifx into a form more useful for  */
315 /*              generating code                                    */
316 /*-----------------------------------------------------------------*/
317 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
318 {
319     if(!resIfx)
320         return;
321
322     //  DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
323
324     resIfx->condition = 1;  /* assume that the ifx is true */
325     resIfx->generated = 0;  /* indicate that the ifx has not been used */
326
327     if(!ifx) {
328         resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL);  / * oops, there is no ifx. so create a label */
329     } else {
330         if(IC_TRUE(ifx)) {
331             resIfx->lbl = IC_TRUE(ifx);
332         } else {
333             resIfx->lbl = IC_FALSE(ifx);
334             resIfx->condition = 0;
335         }
336     }
337
338     //  DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
339
340 }
341
342 /*-----------------------------------------------------------------*/
343 /* aopForSym - for a true symbol                                   */
344 /*-----------------------------------------------------------------*/
345 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
346 {
347     asmop *aop;
348     memmap *space= SPEC_OCLS(sym->etype);
349
350     DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
351     /* if already has one */
352     if (sym->aop)
353         return sym->aop;
354
355     //DEBUGpic14_emitcode(";","%d",__LINE__);
356     /* if it is in direct space */
357     if (IN_DIRSPACE(space)) {
358         sym->aop = aop = newAsmop (AOP_DIR);
359         aop->aopu.aop_dir = sym->rname ;
360         aop->size = getSize(sym->type);
361         DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
362         return aop;
363     }
364
365     /* special case for a function */
366     if (IS_FUNC(sym->type)) {
367
368         sym->aop = aop = newAsmop(AOP_PCODE);
369         aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
370         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
371         PCOI(aop->aopu.pcop)->_function = 1;
372         PCOI(aop->aopu.pcop)->index = 0;
373         aop->size = FPTRSIZE;
374         DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
375         return aop;
376     }
377
378     if (IS_ARRAY(sym->type)) {
379         sym->aop = aop = newAsmop(AOP_PCODE);
380         aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
381         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
382         PCOI(aop->aopu.pcop)->_function = 0;
383         PCOI(aop->aopu.pcop)->index = 0;
384         aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
385
386         DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
387         return aop;
388     }
389
390     /* only remaining is far space */
391     /* in which case DPTR gets the address */
392     sym->aop = aop = newAsmop(AOP_PCODE);
393
394     aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
395     PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
396     PCOI(aop->aopu.pcop)->index = 0;
397
398     DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
399         __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
400
401     allocDirReg (IC_LEFT(ic));
402
403     aop->size = FPTRSIZE;
404
405     /* if it is in code space */
406     if (IN_CODESPACE(space))
407         aop->code = 1;
408
409     return aop;
410 }
411
412 /*-----------------------------------------------------------------*/
413 /* aopForRemat - rematerialzes an object                           */
414 /*-----------------------------------------------------------------*/
415 static asmop *aopForRemat (operand *op) // x symbol *sym)
416 {
417     symbol *sym = OP_SYMBOL(op);
418     iCode *ic = NULL;
419     asmop *aop = newAsmop(AOP_PCODE);
420     int val = 0;
421     int offset = 0;
422
423     ic = sym->rematiCode;
424
425     DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
426     if(IS_OP_POINTER(op)) {
427         DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
428     }
429     for (;;) {
430         if (ic->op == '+') {
431             val += (int) operandLitValue(IC_RIGHT(ic));
432         } else if (ic->op == '-') {
433             val -= (int) operandLitValue(IC_RIGHT(ic));
434         } else
435             break;
436
437         ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
438     }
439
440     offset = OP_SYMBOL(IC_LEFT(ic))->offset;
441     aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
442     PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
443     PCOI(aop->aopu.pcop)->index = val;
444
445     DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
446         __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
447         val, IS_PTR_CONST(operandType(op)));
448
449     //  DEBUGpic14_emitcode(";","aop type  %s",AopType(AOP_TYPE(IC_LEFT(ic))));
450
451     allocDirReg (IC_LEFT(ic));
452
453     return aop;
454 }
455
456 static int aopIdx (asmop *aop, int offset)
457 {
458     if(!aop)
459         return -1;
460
461     if(aop->type !=  AOP_REG)
462         return -2;
463
464     return aop->aopu.aop_reg[offset]->rIdx;
465
466 }
467
468 /*-----------------------------------------------------------------*/
469 /* regsInCommon - two operands have some registers in common       */
470 /*-----------------------------------------------------------------*/
471 static bool regsInCommon (operand *op1, operand *op2)
472 {
473     symbol *sym1, *sym2;
474     int i;
475
476     /* if they have registers in common */
477     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
478         return FALSE ;
479
480     sym1 = OP_SYMBOL(op1);
481     sym2 = OP_SYMBOL(op2);
482
483     if (sym1->nRegs == 0 || sym2->nRegs == 0)
484         return FALSE ;
485
486     for (i = 0 ; i < sym1->nRegs ; i++) {
487         int j;
488         if (!sym1->regs[i])
489             continue ;
490
491         for (j = 0 ; j < sym2->nRegs ;j++ ) {
492             if (!sym2->regs[j])
493                 continue ;
494
495             if (sym2->regs[j] == sym1->regs[i])
496                 return TRUE ;
497         }
498     }
499
500     return FALSE ;
501 }
502
503 /*-----------------------------------------------------------------*/
504 /* operandsEqu - equivalent                                        */
505 /*-----------------------------------------------------------------*/
506 static bool operandsEqu ( operand *op1, operand *op2)
507 {
508     symbol *sym1, *sym2;
509
510     /* if they not symbols */
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 both are itemps & one is spilt
518     and the other is not then false */
519     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
520         sym1->isspilt != sym2->isspilt )
521         return FALSE ;
522
523     /* if they are the same */
524     if (sym1 == sym2)
525         return TRUE ;
526
527     if (sym1->rname[0] && sym2->rname[0]
528         && strcmp (sym1->rname, sym2->rname) == 0)
529         return TRUE;
530
531
532     /* if left is a tmp & right is not */
533     if (IS_ITEMP(op1)  &&
534         !IS_ITEMP(op2) &&
535         sym1->isspilt  &&
536         (sym1->usl.spillLoc == sym2))
537         return TRUE;
538
539     if (IS_ITEMP(op2)  &&
540         !IS_ITEMP(op1) &&
541         sym2->isspilt  &&
542         sym1->level > 0 &&
543         (sym2->usl.spillLoc == sym1))
544         return TRUE ;
545
546     return FALSE ;
547 }
548
549 /*-----------------------------------------------------------------*/
550 /* pic14_sameRegs - two asmops have the same registers             */
551 /*-----------------------------------------------------------------*/
552 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
553 {
554     int i;
555
556     if (aop1 == aop2)
557         return TRUE ;
558
559     if (aop1->type != AOP_REG ||
560         aop2->type != AOP_REG )
561         return FALSE ;
562
563     if (aop1->size != aop2->size )
564         return FALSE ;
565
566     for (i = 0 ; i < aop1->size ; i++ )
567         if (aop1->aopu.aop_reg[i] !=
568             aop2->aopu.aop_reg[i] )
569             return FALSE ;
570
571         return TRUE ;
572 }
573
574 /*-----------------------------------------------------------------*/
575 /* aopOp - allocates an asmop for an operand  :                    */
576 /*-----------------------------------------------------------------*/
577 void aopOp (operand *op, iCode *ic, bool result)
578 {
579     asmop *aop;
580     symbol *sym;
581     int i;
582
583     if (!op)
584         return ;
585
586     /* if this a literal */
587     if (IS_OP_LITERAL(op)) {
588         op->aop = aop = newAsmop(AOP_LIT);
589         aop->aopu.aop_lit = op->operand.valOperand;
590         aop->size = getSize(operandType(op));
591         return;
592     }
593
594     {
595         sym_link *type = operandType(op);
596         if(IS_PTR_CONST(type))
597             DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
598     }
599
600     /* if already has a asmop then continue */
601     if (op->aop)
602         return ;
603
604     /* if the underlying symbol has a aop */
605     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
606         DEBUGpic14_emitcode(";","%d",__LINE__);
607         op->aop = OP_SYMBOL(op)->aop;
608         return;
609     }
610
611     /* if this is a true symbol */
612     if (IS_TRUE_SYMOP(op)) {
613         //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
614         op->aop = aopForSym(ic,OP_SYMBOL(op),result);
615         return ;
616     }
617
618     /* this is a temporary : this has
619     only four choices :
620     a) register
621     b) spillocation
622     c) rematerialize
623     d) conditional
624     e) can be a return use only */
625
626     sym = OP_SYMBOL(op);
627
628
629     /* if the type is a conditional */
630     if (sym->regType == REG_CND) {
631         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
632         aop->size = 0;
633         return;
634     }
635
636     /* if it is spilt then two situations
637     a) is rematerialize
638     b) has a spill location */
639     if (sym->isspilt || sym->nRegs == 0) {
640
641         DEBUGpic14_emitcode(";","%d",__LINE__);
642         /* rematerialize it NOW */
643         if (sym->remat) {
644
645             sym->aop = op->aop = aop = aopForRemat (op);
646             aop->size = getSize(sym->type);
647             //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
648             return;
649         }
650
651         if (sym->ruonly ) {
652             if(sym->isptr) {    // && sym->uptr
653                 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
654                 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
655
656                 //PCOI(aop->aopu.pcop)->_const = 0;
657                 //PCOI(aop->aopu.pcop)->index = 0;
658                 /*
659                 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
660                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
661                 */
662                 //allocDirReg (IC_LEFT(ic));
663
664                 aop->size = getSize(sym->type);
665                 DEBUGpic14_emitcode(";","%d",__LINE__);
666                 return;
667
668             } else {
669
670                 unsigned i;
671
672                 aop = op->aop = sym->aop = newAsmop(AOP_STR);
673                 aop->size = getSize(sym->type);
674                 for ( i = 0 ; i < fReturnSizePic ; i++ )
675                     aop->aopu.aop_str[i] = fReturn[i];
676
677                 DEBUGpic14_emitcode(";","%d",__LINE__);
678                 return;
679             }
680         }
681
682         /* else spill location  */
683         if (sym->usl.spillLoc)
684         {
685             asmop *oldAsmOp = NULL;
686
687             if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
688             {
689                 /* force a new aop if sizes differ */
690                 oldAsmOp = sym->usl.spillLoc->aop;
691                 sym->usl.spillLoc->aop = NULL;
692             }
693             DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
694                 __FUNCTION__,__LINE__,
695                 sym->usl.spillLoc->rname,
696                 sym->rname, sym->usl.spillLoc->offset);
697
698             sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
699             if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
700             {
701                 /* Don't reuse the new aop, go with the last one */
702                 sym->usl.spillLoc->aop = oldAsmOp;
703             }
704             //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
705             aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname,
706                 getSize(sym->type),
707                 sym->usl.spillLoc->offset);
708             aop->size = getSize(sym->type);
709
710             return;
711         }
712     }
713
714     {
715         sym_link *type = operandType(op);
716         if(IS_PTR_CONST(type))
717             DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
718     }
719
720     /* must be in a register */
721     DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
722     sym->aop = op->aop = aop = newAsmop(AOP_REG);
723     aop->size = sym->nRegs;
724     for ( i = 0 ; i < sym->nRegs ;i++)
725         aop->aopu.aop_reg[i] = sym->regs[i];
726 }
727
728 /*-----------------------------------------------------------------*/
729 /* freeAsmop - free up the asmop given to an operand               */
730 /*----------------------------------------------------------------*/
731 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
732 {
733     asmop *aop ;
734
735     if (!op)
736         aop = aaop;
737     else
738         aop = op->aop;
739
740     if (!aop)
741         return ;
742
743     aop->freed = 1;
744
745     /* all other cases just dealloc */
746     if (op) {
747         op->aop = NULL;
748         if (IS_SYMOP(op)) {
749             OP_SYMBOL(op)->aop = NULL;
750             /* if the symbol has a spill */
751             if (SPIL_LOC(op))
752                 SPIL_LOC(op)->aop = NULL;
753         }
754     }
755 }
756
757 /*-----------------------------------------------------------------*/
758 /* pic14aopLiteral - string from a literal value                   */
759 /*-----------------------------------------------------------------*/
760 static unsigned int pic14aopLiteral (value *val, int offset)
761 {
762         union {
763                 float f;
764                 unsigned char c[4];
765         } fl;
766
767         /* if it is a float then it gets tricky */
768         /* otherwise it is fairly simple */
769         if (!IS_FLOAT(val->type)) {
770                 unsigned long v = ulFromVal (val);
771
772                 return ( (v >> (offset * 8)) & 0xff);
773         }
774
775         /* it is type float */
776         fl.f = (float) floatFromVal(val);
777 #ifdef WORDS_BIGENDIAN
778         return fl.c[3-offset];
779 #else
780         return fl.c[offset];
781 #endif
782 }
783
784 /*-----------------------------------------------------------------*/
785 /* aopGet - for fetching value of the aop                          */
786 /*-----------------------------------------------------------------*/
787 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
788 {
789     char *s = buffer ;
790     char *rs;
791
792     //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
793     /* offset is greater than
794     size then zero */
795     assert(aop);
796     if (offset > (aop->size - 1) &&
797         aop->type != AOP_LIT)
798         return zero;
799
800     /* depending on type */
801     switch (aop->type) {
802
803     case AOP_IMMD:
804         if (bit16)
805             sprintf (s,"%s",aop->aopu.aop_immd);
806         else
807             if (offset)
808                 sprintf(s,"(%s >> %d)",
809                 aop->aopu.aop_immd,
810                 offset*8);
811             else
812                 sprintf(s,"%s",
813                 aop->aopu.aop_immd);
814             DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
815             rs = Safe_calloc(1,strlen(s)+1);
816             strcpy(rs,s);
817             return rs;
818
819     case AOP_DIR:
820         if (offset) {
821             sprintf(s,"(%s + %d)",
822                 aop->aopu.aop_dir,
823                 offset);
824             DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
825         } else
826             sprintf(s,"%s",aop->aopu.aop_dir);
827         rs = Safe_calloc(1,strlen(s)+1);
828         strcpy(rs,s);
829         return rs;
830
831     case AOP_REG:
832         //if (dname)
833         //    return aop->aopu.aop_reg[offset]->dname;
834         //else
835         return aop->aopu.aop_reg[offset]->name;
836
837     case AOP_CRY:
838         //pic14_emitcode(";","%d",__LINE__);
839         return aop->aopu.aop_dir;
840
841     case AOP_LIT:
842         sprintf(s, "0x%02x", pic14aopLiteral (aop->aopu.aop_lit, offset));
843         rs = Safe_strdup(s);
844         return rs;
845
846     case AOP_STR:
847         aop->coff = offset ;
848         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
849             dname)
850             return "acc";
851         DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
852
853         return aop->aopu.aop_str[offset];
854
855     case AOP_PCODE:
856         {
857             pCodeOp *pcop = aop->aopu.pcop;
858             DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
859             if(pcop->name) {
860                 if (pcop->type == PO_IMMEDIATE) {
861                     offset += PCOI(pcop)->index;
862                 }
863                 if (offset) {
864                     DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
865                     sprintf(s,"(%s+%d)", pcop->name,offset);
866                 } else {
867                     DEBUGpic14_emitcode(";","%s",pcop->name);
868                     sprintf(s,"%s", pcop->name);
869                 }
870             } else
871                 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
872
873         }
874         rs = Safe_calloc(1,strlen(s)+1);
875         strcpy(rs,s);
876         return rs;
877
878   }
879
880   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
881       "aopget got unsupported aop->type");
882   exit(0);
883 }
884
885 /*-----------------------------------------------------------------*/
886 /* popGetTempReg - create a new temporary pCodeOp                  */
887 /*-----------------------------------------------------------------*/
888 static pCodeOp *popGetTempReg(void)
889 {
890
891     pCodeOp *pcop;
892
893     pcop = newpCodeOp(NULL, PO_GPR_TEMP);
894     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
895         PCOR(pcop)->r->wasUsed=1;
896         PCOR(pcop)->r->isFree=0;
897     }
898
899     return pcop;
900 }
901
902 /*-----------------------------------------------------------------*/
903 /* popReleaseTempReg - create a new temporary pCodeOp                  */
904 /*-----------------------------------------------------------------*/
905 static void popReleaseTempReg(pCodeOp *pcop)
906 {
907
908     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
909         PCOR(pcop)->r->isFree = 1;
910
911 }
912
913 /*-----------------------------------------------------------------*/
914 /* popGetLabel - create a new pCodeOp of type PO_LABEL             */
915 /*-----------------------------------------------------------------*/
916 pCodeOp *popGetLabel(unsigned int key)
917 {
918
919     DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
920
921     if(key>(unsigned int)max_key)
922         max_key = key;
923
924     return newpCodeOpLabel(NULL,key+100+labelOffset);
925 }
926
927 /*-------------------------------------------------------------------*/
928 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
929 /*-------------------------------------------------------------------*/
930 static pCodeOp *popGetHighLabel(unsigned int key)
931 {
932     pCodeOp *pcop;
933     pcop = popGetLabel(key);
934     PCOLAB(pcop)->offset = 1;
935     return pcop;
936 }
937
938 /*-----------------------------------------------------------------*/
939 /* popGetLit - asm operator to pcode operator conversion               */
940 /*-----------------------------------------------------------------*/
941 pCodeOp *popGetLit(unsigned int lit)
942 {
943
944     return newpCodeOpLit((unsigned char)lit);
945 }
946
947 /*-----------------------------------------------------------------*/
948 /* popGetImmd - asm operator to pcode immediate conversion         */
949 /*-----------------------------------------------------------------*/
950 static pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
951 {
952
953     return newpCodeOpImmd(name, offset,index, 0, is_func);
954 }
955
956 /*-----------------------------------------------------------------*/
957 /* popGetWithString - asm operator to pcode operator conversion            */
958 /*-----------------------------------------------------------------*/
959 static pCodeOp *popGetWithString(char *str, int isExtern)
960 {
961     pCodeOp *pcop;
962
963
964     if(!str) {
965         fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
966         exit (1);
967     }
968
969     pcop = newpCodeOp(str,PO_STR);
970     PCOS(pcop)->isPublic = isExtern ? 1 : 0;
971
972     return pcop;
973 }
974
975 pCodeOp *popGetExternal (char *str, int isReg)
976 {
977     pCodeOp *pcop;
978
979     if (isReg) {
980         pcop = newpCodeOpRegFromStr(str);
981     } else {
982         pcop = popGetWithString (str, 1);
983     }
984
985     if (str) {
986       symbol *sym;
987
988       for (sym = setFirstItem (externs); sym; sym = setNextItem (externs))
989       {
990         if (!strcmp (str, sym->rname)) break;
991       }
992
993       if (!sym)
994       {
995         sym = newSymbol(str, 0);
996         strncpy(sym->rname, str, SDCC_NAME_MAX);
997         addSet (&externs, sym);
998       } // if
999       sym->used++;
1000     }
1001     return pcop;
1002 }
1003
1004 /*-----------------------------------------------------------------*/
1005 /* popRegFromString -                                              */
1006 /*-----------------------------------------------------------------*/
1007 static pCodeOp *popRegFromString(char *str, int size, int offset)
1008 {
1009
1010     pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1011     pcop->type = PO_DIR;
1012
1013     DEBUGpic14_emitcode(";","%d",__LINE__);
1014
1015     if(!str)
1016         str = "BAD_STRING";
1017
1018     pcop->name = Safe_calloc(1,strlen(str)+1);
1019     strcpy(pcop->name,str);
1020
1021     //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1022
1023     PCOR(pcop)->r = dirregWithName(pcop->name);
1024     if(PCOR(pcop)->r == NULL) {
1025         //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1026         PCOR(pcop)->r = allocRegByName (pcop->name,size);
1027         DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1028     } else {
1029         DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1030     }
1031     PCOR(pcop)->instance = offset;
1032
1033     return pcop;
1034 }
1035
1036 /*-----------------------------------------------------------------*/
1037 /*-----------------------------------------------------------------*/
1038 static pCodeOp *popRegFromIdx(int rIdx)
1039 {
1040     pCodeOp *pcop;
1041
1042     DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1043         __FUNCTION__,__LINE__,rIdx);
1044
1045     pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1046
1047     PCOR(pcop)->rIdx = rIdx;
1048     PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1049     PCOR(pcop)->r->isFree = 0;
1050     PCOR(pcop)->r->wasUsed = 1;
1051
1052     pcop->type = PCOR(pcop)->r->pc_type;
1053
1054
1055     return pcop;
1056 }
1057
1058 /*-----------------------------------------------------------------*/
1059 /* popGet - asm operator to pcode operator conversion              */
1060 /*-----------------------------------------------------------------*/
1061 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1062 {
1063     //char *s = buffer ;
1064     //char *rs;
1065
1066     pCodeOp *pcop;
1067
1068     //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1069     /* offset is greater than
1070     size then zero */
1071
1072     assert (aop);
1073
1074
1075     /* XXX: still needed for BIT operands (AOP_CRY) */
1076     if (offset > (aop->size - 1) &&
1077         aop->type != AOP_LIT &&
1078         aop->type != AOP_PCODE)
1079     {
1080         printf( "%s: (offset[%d] > AOP_SIZE(op)[%d]-1) && AOP_TYPE(op) != AOP_LIT)\n", __FUNCTION__, offset, aop->size);
1081         return NULL;  //zero;
1082     }
1083
1084     /* depending on type */
1085     switch (aop->type) {
1086
1087     case AOP_IMMD:
1088         DEBUGpic14_emitcode(";","%d",__LINE__);
1089         return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1090
1091     case AOP_DIR:
1092         return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1093
1094     case AOP_REG:
1095         {
1096             int rIdx;
1097             assert (offset < aop->size);
1098             rIdx = aop->aopu.aop_reg[offset]->rIdx;
1099
1100             pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1101             PCOR(pcop)->rIdx = rIdx;
1102             PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1103             PCOR(pcop)->r->wasUsed=1;
1104             PCOR(pcop)->r->isFree=0;
1105
1106             PCOR(pcop)->instance = offset;
1107             pcop->type = PCOR(pcop)->r->pc_type;
1108             //rs = aop->aopu.aop_reg[offset]->name;
1109             DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1110             return pcop;
1111         }
1112
1113     case AOP_CRY:
1114         pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1115         PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1116         //if(PCOR(pcop)->r == NULL)
1117         //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1118         return pcop;
1119
1120     case AOP_LIT:
1121         return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1122
1123     case AOP_STR:
1124         DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1125         return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1126
1127     case AOP_PCODE:
1128         pcop = NULL;
1129         DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1130             __LINE__,
1131             ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1132         //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1133         switch (aop->aopu.pcop->type)
1134         {
1135         case PO_IMMEDIATE:
1136           pcop = pCodeOpCopy (aop->aopu.pcop);
1137           /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1138            * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1139           PCOI(pcop)->index += offset;
1140           //PCOI(pcop)->offset = 0;
1141           break;
1142         case PO_DIR:
1143           pcop = pCodeOpCopy (aop->aopu.pcop);
1144           PCOR(pcop)->instance = offset;
1145           break;
1146         default:
1147           assert ( !"unhandled pCode type" );
1148           break;
1149         } // switch
1150         return pcop;
1151     }
1152
1153     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1154         "popGet got unsupported aop->type");
1155     exit(0);
1156 }
1157
1158 /*-----------------------------------------------------------------*/
1159 /* popGetAddr - access the low/high word of a symbol (immediate)   */
1160 /*              (for non-PO_IMMEDIATEs this is the same as popGet) */
1161 /*-----------------------------------------------------------------*/
1162 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1163 {
1164   if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1165   {
1166     pCodeOp *pcop = aop->aopu.pcop;
1167     assert (offset <= GPTRSIZE);
1168
1169     /* special case: index >= 2 should return GPOINTER-style values */
1170     if (offset == 2)
1171     {
1172       pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1173       return pcop;
1174     }
1175
1176     pcop = pCodeOpCopy (pcop);
1177     /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1178      * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1179     PCOI(pcop)->offset += offset;
1180     PCOI(pcop)->index += index;
1181     //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);
1182     return pcop;
1183   } else {
1184     return popGet (aop, offset + index);
1185   }
1186 }
1187
1188 /*-----------------------------------------------------------------*/
1189 /* aopPut - puts a string for a aop                                */
1190 /*-----------------------------------------------------------------*/
1191 void aopPut (asmop *aop, char *s, int offset)
1192 {
1193     char *d = buffer ;
1194     symbol *lbl ;
1195
1196     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1197
1198     if (aop->size && offset > ( aop->size - 1)) {
1199         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1200             "aopPut got offset > aop->size");
1201         exit(0);
1202     }
1203
1204     /* will assign value to value */
1205     /* depending on where it is ofcourse */
1206     switch (aop->type) {
1207     case AOP_DIR:
1208         if (offset) {
1209             sprintf(d,"(%s + %d)",
1210                 aop->aopu.aop_dir,offset);
1211             fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1212
1213         } else
1214             sprintf(d,"%s",aop->aopu.aop_dir);
1215
1216         if (strcmp(d,s)) {
1217             DEBUGpic14_emitcode(";","%d",__LINE__);
1218             if(strcmp(s,"W"))
1219                 pic14_emitcode("movf","%s,w",s);
1220             pic14_emitcode("movwf","%s",d);
1221
1222             if(strcmp(s,"W")) {
1223                 pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1224                 if(offset >= aop->size) {
1225                     emitpcode(POC_CLRF,popGet(aop,offset));
1226                     break;
1227                 } else {
1228                     emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1229                 }
1230             }
1231             emitpcode(POC_MOVWF,popGet(aop,offset));
1232
1233         }
1234         break;
1235
1236     case AOP_REG:
1237         if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1238             if(strcmp(s,"W")==0 )
1239                 pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1240
1241             pic14_emitcode("movwf","%s",
1242                 aop->aopu.aop_reg[offset]->name);
1243
1244             if(strcmp(s,zero)==0) {
1245                 emitpcode(POC_CLRF,popGet(aop,offset));
1246
1247             } else if(strcmp(s,"W")==0) {
1248                 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1249                 pcop->type = PO_GPR_REGISTER;
1250
1251                 PCOR(pcop)->rIdx = -1;
1252                 PCOR(pcop)->r = NULL;
1253
1254                 DEBUGpic14_emitcode(";","%d",__LINE__);
1255                 pcop->name = Safe_strdup(s);
1256                 emitpcode(POC_MOVFW,pcop);
1257                 emitpcode(POC_MOVWF,popGet(aop,offset));
1258             } else if(strcmp(s,one)==0) {
1259                 emitpcode(POC_CLRF,popGet(aop,offset));
1260                 emitpcode(POC_INCF,popGet(aop,offset));
1261             } else {
1262                 emitpcode(POC_MOVWF,popGet(aop,offset));
1263             }
1264         }
1265         break;
1266
1267     case AOP_STK:
1268         if (strcmp(s,"a") == 0)
1269             pic14_emitcode("push","acc");
1270         else
1271             pic14_emitcode("push","%s",s);
1272
1273         break;
1274
1275     case AOP_CRY:
1276         /* if bit variable */
1277         if (!aop->aopu.aop_dir) {
1278             pic14_emitcode("clr","a");
1279             pic14_emitcode("rlc","a");
1280         } else {
1281             if (s == zero)
1282                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1283             else
1284                 if (s == one)
1285                     pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1286                 else
1287                     if (!strcmp(s,"c"))
1288                         pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1289                     else {
1290                         lbl = newiTempLabel(NULL);
1291
1292                         if (strcmp(s,"a")) {
1293                             MOVA(s);
1294                         }
1295                         pic14_emitcode("clr","c");
1296                         pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1297                         pic14_emitcode("cpl","c");
1298                         pic14_emitcode("","%05d_DS_:",lbl->key+100);
1299                         pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1300                     }
1301         }
1302         break;
1303
1304     case AOP_STR:
1305         aop->coff = offset;
1306         if (strcmp(aop->aopu.aop_str[offset],s))
1307             pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1308         break;
1309
1310     default :
1311         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1312             "aopPut got unsupported aop->type");
1313         exit(0);
1314     }
1315
1316 }
1317
1318 /*-----------------------------------------------------------------*/
1319 /* mov2w_op - generate either a MOVLW or MOVFW based operand type  */
1320 /*-----------------------------------------------------------------*/
1321 static void mov2w_op (operand *op, int offset)
1322 {
1323     assert (op);
1324     FENTRY;
1325
1326     /* for PO_IMMEDIATEs: use address or value? */
1327     if (op_isLitLike (op))
1328     {
1329         /* access address of op */
1330         if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1331         if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1332         {
1333             if (offset == GPTRSIZE-1)
1334                 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1335             else
1336                 emitpcode (POC_MOVLW, popGetLit (0));
1337         }
1338         else
1339             emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1340     } else {
1341         /* access value stored in op */
1342         mov2w (AOP(op), offset);
1343     }
1344 }
1345
1346
1347 /*-----------------------------------------------------------------*/
1348 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1349 /*-----------------------------------------------------------------*/
1350 void mov2w (asmop *aop, int offset)
1351 {
1352
1353     if(!aop)
1354         return;
1355
1356     DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1357
1358     if ( aop_isLitLike (aop) )
1359         emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1360     else
1361         emitpcode(POC_MOVFW,popGet(aop,offset));
1362
1363 }
1364
1365 static void movwf (asmop *op, int offset)
1366 {
1367     emitpcode (POC_MOVWF, popGet(op, offset));
1368 }
1369
1370 static pCodeOp *get_argument_pcop (int idx)
1371 {
1372     assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1373     return popRegFromIdx (Gstack_base_addr - (idx - 1));
1374 }
1375
1376 static pCodeOp *get_return_val_pcop (int offset)
1377 {
1378     assert (offset > 0 && "the most significant byte is returned via WREG");
1379     return popRegFromIdx (Gstack_base_addr - (offset - 1));
1380 }
1381
1382 static void pass_argument (operand *op, int offset, int idx)
1383 {
1384     if (op)
1385         mov2w_op (op, offset);
1386     if (idx != 0)
1387         emitpcode(POC_MOVWF, get_argument_pcop (idx));
1388 }
1389
1390 static void get_returnvalue (operand *op, int offset, int idx)
1391 {
1392     if (idx != 0)
1393         emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1394     movwf(AOP(op), offset);
1395 }
1396
1397 static void call_libraryfunc (char *name)
1398 {
1399     symbol *sym;
1400
1401     /* library code might reside in different page... */
1402     emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1403     /* call the library function */
1404     emitpcode (POC_CALL, popGetExternal (name, 0));
1405     /* might return from different page... */
1406     emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1407
1408     /* create symbol, mark it as `extern' */
1409     sym = findSym(SymbolTab, NULL, name);
1410     if (!sym) {
1411     sym = newSymbol(name, 0);
1412     strncpy(sym->rname, name, SDCC_NAME_MAX);
1413     addSym(SymbolTab, sym, sym->rname, 0, 0, 0);
1414     addSet(&externs, sym);
1415     } // if
1416     sym->used++;
1417 }
1418
1419 /*-----------------------------------------------------------------*/
1420 /* pic14_getDataSize - get the operand data size                   */
1421 /*-----------------------------------------------------------------*/
1422 int pic14_getDataSize(operand *op)
1423 {
1424     int size;
1425
1426     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1427
1428 #if 0
1429     size = getSize(OP_SYM_ETYPE(op));
1430     return size;
1431     //return AOP_SIZE(op);
1432
1433     // tsd- in the pic port, the genptr size is 1, so this code here
1434     // fails. ( in the 8051 port, the size was 4).
1435 #else
1436     size = AOP_SIZE(op);
1437     if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)))
1438     {
1439         sym_link *type = operandType(op);
1440         if (IS_GENPTR(type))
1441         {
1442             /* generic pointer; arithmetic operations
1443             * should ignore the high byte (pointer type).
1444             */
1445             size--;
1446             DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1447         }
1448     }
1449     return size;
1450 #endif
1451 }
1452
1453 /*-----------------------------------------------------------------*/
1454 /* pic14_outAcc - output Acc                                       */
1455 /*-----------------------------------------------------------------*/
1456 void pic14_outAcc(operand *result)
1457 {
1458     int size,offset;
1459     DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1460     DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1461
1462
1463     size = pic14_getDataSize(result);
1464     if(size){
1465         emitpcode(POC_MOVWF,popGet(AOP(result),0));
1466         size--;
1467         offset = 1;
1468         /* unsigned or positive */
1469         while(size--)
1470             emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1471     }
1472
1473 }
1474
1475 /*-----------------------------------------------------------------*/
1476 /* pic14_outBitC - output a bit C                                  */
1477 /*-----------------------------------------------------------------*/
1478 static void pic14_outBitC(operand *result)
1479 {
1480
1481     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1482     /* if the result is bit */
1483     if (AOP_TYPE(result) == AOP_CRY)
1484         aopPut(AOP(result),"c",0);
1485     else {
1486         pic14_emitcode("clr","a  ; %d", __LINE__);
1487         pic14_emitcode("rlc","a");
1488         pic14_outAcc(result);
1489     }
1490 }
1491
1492 /*-----------------------------------------------------------------*/
1493 /* pic14_toBoolean - emit code for orl a,operator(sizeop)          */
1494 /*-----------------------------------------------------------------*/
1495 static void pic14_toBoolean(operand *oper)
1496 {
1497     int size = AOP_SIZE(oper);
1498     int offset = 0;
1499
1500     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1501
1502     assert (size > 0);
1503
1504     if (size == 1) {
1505         /* MOVFW does not load the flags... */
1506         emitpcode(POC_MOVLW, popGetLit(0));
1507         offset = 0;
1508     } else {
1509         emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1510         offset = 1;
1511     }
1512
1513     while (offset < size) {
1514         emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1515     }
1516     /* Z is set iff (oper == 0) */
1517 }
1518
1519
1520 /*-----------------------------------------------------------------*/
1521 /* genNot - generate code for ! operation                          */
1522 /*-----------------------------------------------------------------*/
1523 static void genNot (iCode *ic)
1524 {
1525     //symbol *tlbl;
1526     int size;
1527
1528     FENTRY;
1529
1530     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1531     /* assign asmOps to operand & result */
1532     aopOp (IC_LEFT(ic),ic,FALSE);
1533     aopOp (IC_RESULT(ic),ic,TRUE);
1534
1535     DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1536     /* if in bit space then a special case */
1537     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1538         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1539             emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
1540             emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
1541         } else {
1542             emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
1543             emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
1544             emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
1545         }
1546         goto release;
1547     }
1548
1549     size = AOP_SIZE(IC_LEFT(ic));
1550     mov2w (AOP(IC_LEFT(ic)),0);
1551     while (--size > 0)
1552     {
1553       if (op_isLitLike (IC_LEFT(ic)))
1554         emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
1555       else
1556         emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
1557     }
1558     emitpcode(POC_MOVLW, popGetLit (0));
1559     emitSKPNZ;
1560     emitpcode(POC_MOVLW, popGetLit (1));
1561     movwf(AOP(IC_RESULT(ic)), 0);
1562
1563     for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
1564     {
1565       emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
1566     }
1567     goto release;
1568
1569 release:
1570     /* release the aops */
1571     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1572     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1573 }
1574
1575
1576 /*-----------------------------------------------------------------*/
1577 /* genCpl - generate code for complement                           */
1578 /*-----------------------------------------------------------------*/
1579 static void genCpl (iCode *ic)
1580 {
1581     operand *left, *result;
1582     int size, offset=0;
1583
1584     FENTRY;
1585
1586     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1587     aopOp((left = IC_LEFT(ic)),ic,FALSE);
1588     aopOp((result=IC_RESULT(ic)),ic,TRUE);
1589
1590     /* if both are in bit space then
1591     a special case */
1592     if (AOP_TYPE(result) == AOP_CRY &&
1593         AOP_TYPE(left) == AOP_CRY ) {
1594
1595         pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir);
1596         pic14_emitcode("cpl","c");
1597         pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir);
1598         goto release;
1599     }
1600
1601     size = AOP_SIZE(result);
1602     if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
1603     while (size--) {
1604         emitpcode(POC_COMFW,popGet(AOP(left),offset));
1605         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
1606         offset++;
1607     }
1608     addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
1609
1610
1611 release:
1612     /* release the aops */
1613     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1614     freeAsmop(result,NULL,ic,TRUE);
1615 }
1616
1617 /*-----------------------------------------------------------------*/
1618 /* genUminusFloat - unary minus for floating points                */
1619 /*-----------------------------------------------------------------*/
1620 static void genUminusFloat(operand *op,operand *result)
1621 {
1622     int size ,offset =0 ;
1623     char *l;
1624
1625     FENTRY;
1626
1627     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1628     /* for this we just need to flip the
1629     first it then copy the rest in place */
1630     size = AOP_SIZE(op) - 1;
1631     l = aopGet(AOP(op),3,FALSE,FALSE);
1632
1633     MOVA(l);
1634
1635     pic14_emitcode("cpl","acc.7");
1636     aopPut(AOP(result),"a",3);
1637
1638     while(size--) {
1639         aopPut(AOP(result),
1640             aopGet(AOP(op),offset,FALSE,FALSE),
1641             offset);
1642         offset++;
1643     }
1644 }
1645
1646 /*-----------------------------------------------------------------*/
1647 /* genUminus - unary minus code generation                         */
1648 /*-----------------------------------------------------------------*/
1649 static void genUminus (iCode *ic)
1650 {
1651     int size, i;
1652     sym_link *optype, *rtype;
1653
1654     FENTRY;
1655
1656     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1657     /* assign asmops */
1658     aopOp(IC_LEFT(ic),ic,FALSE);
1659     aopOp(IC_RESULT(ic),ic,TRUE);
1660
1661     /* if both in bit space then special
1662     case */
1663     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1664         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1665
1666         emitpcode(POC_BCF,   popGet(AOP(IC_RESULT(ic)),0));
1667         emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
1668         emitpcode(POC_BSF,   popGet(AOP(IC_RESULT(ic)),0));
1669
1670         goto release;
1671     }
1672
1673     optype = operandType(IC_LEFT(ic));
1674     rtype = operandType(IC_RESULT(ic));
1675
1676     /* if float then do float stuff */
1677     if (IS_FLOAT(optype)) {
1678         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1679         goto release;
1680     }
1681
1682     /* otherwise subtract from zero by taking the 2's complement */
1683     size = AOP_SIZE(IC_LEFT(ic));
1684
1685     for(i=0; i<size; i++) {
1686         if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
1687             emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
1688         else {
1689             emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
1690             emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
1691         }
1692     }
1693
1694     emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
1695     for(i=1; i<size; i++) {
1696         emitSKPNZ;
1697         emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
1698     }
1699
1700 release:
1701     /* release the aops */
1702     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1703     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1704 }
1705
1706 /*-----------------------------------------------------------------*/
1707 /* saverbank - saves an entire register bank on the stack          */
1708 /*-----------------------------------------------------------------*/
1709 static void saverbank (int bank, iCode *ic, bool pushPsw)
1710 {
1711     FENTRY;
1712
1713     DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
1714 #if 0
1715     int i;
1716     asmop *aop ;
1717     regs *r = NULL;
1718
1719     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1720     if (options.useXstack) {
1721
1722         aop = newAsmop(0);
1723         r = getFreePtr(ic,&aop,FALSE);
1724         pic14_emitcode("mov","%s,_spx",r->name);
1725
1726     }
1727
1728     for (i = 0 ; i < pic14_nRegs ;i++) {
1729         if (options.useXstack) {
1730             pic14_emitcode("inc","%s",r->name);
1731             //pic14_emitcode("mov","a,(%s+%d)",
1732             //       regspic14[i].base,8*bank+regspic14[i].offset);
1733             pic14_emitcode("movx","@%s,a",r->name);
1734         } else
1735             pic14_emitcode("push","");// "(%s+%d)",
1736         //regspic14[i].base,8*bank+regspic14[i].offset);
1737     }
1738
1739     if (pushPsw) {
1740         if (options.useXstack) {
1741             pic14_emitcode("mov","a,psw");
1742             pic14_emitcode("movx","@%s,a",r->name);
1743             pic14_emitcode("inc","%s",r->name);
1744             pic14_emitcode("mov","_spx,%s",r->name);
1745             freeAsmop (NULL,aop,ic,TRUE);
1746
1747         } else
1748             pic14_emitcode("push","psw");
1749
1750         pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1751     }
1752     ic->bankSaved = 1;
1753 #endif
1754 }
1755
1756 /*-----------------------------------------------------------------*/
1757 /* saveRegisters - will look for a call and save the registers     */
1758 /*-----------------------------------------------------------------*/
1759 static void saveRegisters(iCode *lic)
1760 {
1761     iCode *ic;
1762     bitVect *rsave;
1763     sym_link *dtype;
1764
1765     FENTRY;
1766
1767     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1768     /* look for call */
1769     for (ic = lic ; ic ; ic = ic->next)
1770         if (ic->op == CALL || ic->op == PCALL)
1771             break;
1772
1773         if (!ic) {
1774             fprintf(stderr,"found parameter push with no function call\n");
1775             return ;
1776         }
1777
1778         /* if the registers have been saved already then
1779         do nothing */
1780         if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
1781             return ;
1782
1783             /* find the registers in use at this time
1784         and push them away to safety */
1785         rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1786             ic->rUsed);
1787
1788         ic->regsSaved = 1;
1789
1790         //fprintf(stderr, "ERROR: saveRegisters did not do anything to save registers, please report this as a bug.\n");
1791
1792         dtype = operandType(IC_LEFT(ic));
1793         if (currFunc && dtype &&
1794             (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
1795             IFFUNC_ISISR(currFunc->type) &&
1796             !ic->bankSaved)
1797
1798             saverbank(FUNC_REGBANK(dtype),ic,TRUE);
1799
1800 }
1801 /*-----------------------------------------------------------------*/
1802 /* unsaveRegisters - pop the pushed registers                      */
1803 /*-----------------------------------------------------------------*/
1804 static void unsaveRegisters (iCode *ic)
1805 {
1806     int i;
1807     bitVect *rsave;
1808
1809     FENTRY;
1810
1811     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1812     /* find the registers in use at this time
1813     and push them away to safety */
1814     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1815         ic->rUsed);
1816
1817     if (options.useXstack) {
1818         pic14_emitcode("mov","r0,%s",spname);
1819         for (i =  pic14_nRegs ; i >= 0 ; i--) {
1820             if (bitVectBitValue(rsave,i)) {
1821                 pic14_emitcode("dec","r0");
1822                 pic14_emitcode("movx","a,@r0");
1823                 pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
1824             }
1825
1826         }
1827         pic14_emitcode("mov","%s,r0",spname);
1828     } //else
1829     //for (i =  pic14_nRegs ; i >= 0 ; i--) {
1830     //  if (bitVectBitValue(rsave,i))
1831     //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
1832     //}
1833
1834 }
1835
1836
1837 /*-----------------------------------------------------------------*/
1838 /* pushSide -                */
1839 /*-----------------------------------------------------------------*/
1840 static void pushSide(operand * oper, int size)
1841 {
1842 #if 0
1843     int offset = 0;
1844     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1845     while (size--) {
1846         char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1847         if (AOP_TYPE(oper) != AOP_REG &&
1848             AOP_TYPE(oper) != AOP_DIR &&
1849             strcmp(l,"a") ) {
1850             pic14_emitcode("mov","a,%s",l);
1851             pic14_emitcode("push","acc");
1852         } else
1853             pic14_emitcode("push","%s",l);
1854     }
1855 #endif
1856 }
1857
1858 /*-----------------------------------------------------------------*/
1859 /* assignResultValue -               */
1860 /*-----------------------------------------------------------------*/
1861 static void assignResultValue(operand * oper)
1862 {
1863     int size = AOP_SIZE(oper);
1864     int offset = 0;
1865
1866     FENTRY;
1867
1868     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1869
1870     DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
1871
1872     /* assign MSB first (passed via WREG) */
1873     while (size--) {
1874         get_returnvalue (oper, size, offset + GpsuedoStkPtr);
1875         GpsuedoStkPtr++;
1876     }
1877 }
1878
1879
1880 /*-----------------------------------------------------------------*/
1881 /* genIpush - genrate code for pushing this gets a little complex  */
1882 /*-----------------------------------------------------------------*/
1883 static void genIpush (iCode *ic)
1884 {
1885     FENTRY;
1886
1887     DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
1888 #if 0
1889     int size, offset = 0 ;
1890     char *l;
1891
1892
1893     /* if this is not a parm push : ie. it is spill push
1894     and spill push is always done on the local stack */
1895     if (!ic->parmPush) {
1896
1897         /* and the item is spilt then do nothing */
1898         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1899             return ;
1900
1901         aopOp(IC_LEFT(ic),ic,FALSE);
1902         size = AOP_SIZE(IC_LEFT(ic));
1903         /* push it on the stack */
1904         while(size--) {
1905             l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1906             if (*l == '#') {
1907                 MOVA(l);
1908                 l = "acc";
1909             }
1910             pic14_emitcode("push","%s",l);
1911         }
1912         return ;
1913     }
1914
1915     /* this is a paramter push: in this case we call
1916     the routine to find the call and save those
1917     registers that need to be saved */
1918     saveRegisters(ic);
1919
1920     /* then do the push */
1921     aopOp(IC_LEFT(ic),ic,FALSE);
1922
1923
1924     // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1925     size = AOP_SIZE(IC_LEFT(ic));
1926
1927     while (size--) {
1928         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1929         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1930             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1931             strcmp(l,"a") ) {
1932             pic14_emitcode("mov","a,%s",l);
1933             pic14_emitcode("push","acc");
1934         } else
1935             pic14_emitcode("push","%s",l);
1936     }
1937
1938     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1939 #endif
1940 }
1941
1942 /*-----------------------------------------------------------------*/
1943 /* genIpop - recover the registers: can happen only for spilling   */
1944 /*-----------------------------------------------------------------*/
1945 static void genIpop (iCode *ic)
1946 {
1947     FENTRY;
1948
1949     DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
1950     assert (!"genIpop -- unimplemented");
1951 #if 0
1952     int size,offset ;
1953
1954
1955     /* if the temp was not pushed then */
1956     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1957         return ;
1958
1959     aopOp(IC_LEFT(ic),ic,FALSE);
1960     size = AOP_SIZE(IC_LEFT(ic));
1961     offset = (size-1);
1962     while (size--)
1963         pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1964         FALSE,TRUE));
1965
1966     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1967 #endif
1968 }
1969
1970 /*-----------------------------------------------------------------*/
1971 /* unsaverbank - restores the resgister bank from stack            */
1972 /*-----------------------------------------------------------------*/
1973 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1974 {
1975     FENTRY;
1976
1977     DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
1978 #if 0
1979     int i;
1980     asmop *aop ;
1981     regs *r = NULL;
1982
1983     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1984     if (popPsw) {
1985         if (options.useXstack) {
1986             aop = newAsmop(0);
1987             r = getFreePtr(ic,&aop,FALSE);
1988
1989
1990             pic14_emitcode("mov","%s,_spx",r->name);
1991             pic14_emitcode("movx","a,@%s",r->name);
1992             pic14_emitcode("mov","psw,a");
1993             pic14_emitcode("dec","%s",r->name);
1994
1995         }else
1996             pic14_emitcode ("pop","psw");
1997     }
1998
1999     for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2000         if (options.useXstack) {
2001             pic14_emitcode("movx","a,@%s",r->name);
2002             //pic14_emitcode("mov","(%s+%d),a",
2003             //     regspic14[i].base,8*bank+regspic14[i].offset);
2004             pic14_emitcode("dec","%s",r->name);
2005
2006         } else
2007             pic14_emitcode("pop",""); //"(%s+%d)",
2008         //regspic14[i].base,8*bank); //+regspic14[i].offset);
2009     }
2010
2011     if (options.useXstack) {
2012
2013         pic14_emitcode("mov","_spx,%s",r->name);
2014         freeAsmop(NULL,aop,ic,TRUE);
2015
2016     }
2017 #endif
2018 }
2019
2020 /*-----------------------------------------------------------------*/
2021 /* genCall - generates a call statement                            */
2022 /*-----------------------------------------------------------------*/
2023 static void genCall (iCode *ic)
2024 {
2025     sym_link *dtype;
2026     symbol *sym;
2027     char *name;
2028     int isExtern;
2029
2030     FENTRY;
2031
2032     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2033
2034     /* if caller saves & we have not saved then */
2035     if (!ic->regsSaved)
2036         saveRegisters(ic);
2037
2038         /* if we are calling a function that is not using
2039         the same register bank then we need to save the
2040     destination registers on the stack */
2041     dtype = operandType(IC_LEFT(ic));
2042     if (currFunc && dtype &&
2043         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2044         IFFUNC_ISISR(currFunc->type) &&
2045         !ic->bankSaved)
2046
2047         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2048
2049     /* if send set is not empty the assign */
2050     if (_G.sendSet) {
2051         iCode *sic;
2052         /* For the Pic port, there is no data stack.
2053         * So parameters passed to functions are stored
2054         * in registers. (The pCode optimizer will get
2055         * rid of most of these :).
2056         */
2057         int psuedoStkPtr=-1;
2058         int firstTimeThruLoop = 1;
2059
2060         _G.sendSet = reverseSet(_G.sendSet);
2061
2062         /* First figure how many parameters are getting passed */
2063         for (sic = setFirstItem(_G.sendSet) ; sic ;
2064         sic = setNextItem(_G.sendSet)) {
2065
2066             aopOp(IC_LEFT(sic),sic,FALSE);
2067             psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2068             freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2069         }
2070
2071         for (sic = setFirstItem(_G.sendSet) ; sic ;
2072         sic = setNextItem(_G.sendSet)) {
2073             int size, offset = 0;
2074
2075             aopOp(IC_LEFT(sic),sic,FALSE);
2076             size = AOP_SIZE(IC_LEFT(sic));
2077
2078             while (size--) {
2079                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2080                     AopType(AOP_TYPE(IC_LEFT(sic))));
2081
2082                 if(!firstTimeThruLoop) {
2083                     /* If this is not the first time we've been through the loop
2084                     * then we need to save the parameter in a temporary
2085                     * register. The last byte of the last parameter is
2086                     * passed in W. */
2087                     emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2088
2089                 }
2090                 firstTimeThruLoop=0;
2091
2092                 mov2w_op (IC_LEFT(sic),  offset);
2093                 offset++;
2094             }
2095             freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2096         }
2097         _G.sendSet = NULL;
2098     }
2099     /* make the call */
2100     sym = OP_SYMBOL(IC_LEFT(ic));
2101     name = sym->rname[0] ? sym->rname : sym->name;
2102     /*
2103      * As SDCC emits code as soon as it reaches the end of each
2104      * function's definition, prototyped functions that are implemented
2105      * after the current one are always considered EXTERN, which
2106      * introduces many unneccessary PAGESEL instructions.
2107      * XXX: Use a post pass to iterate over all `CALL _name' statements
2108      * and insert `PAGESEL _name' and `PAGESEL $' around the CALL
2109      * only iff there is no definition of the function in the whole
2110      * file (might include this in the PAGESEL pass).
2111      */
2112     isExtern = IS_EXTERN(sym->etype) || pic14_inISR;
2113     if (isExtern) {
2114         /* Extern functions and ISRs maybe on a different page;
2115          * must call pagesel */
2116         emitpcode(POC_PAGESEL,popGetWithString(name,1));
2117     }
2118     emitpcode(POC_CALL,popGetWithString(name,isExtern));
2119     if (isExtern) {
2120         /* May have returned from a different page;
2121          * must use pagesel to restore PCLATH before next
2122          * goto or call instruction */
2123         emitpcode(POC_PAGESEL,popGetWithString("$",0));
2124     }
2125     GpsuedoStkPtr=0;
2126     /* if we need assign a result value */
2127     if ((IS_ITEMP(IC_RESULT(ic)) &&
2128         (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2129         OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2130         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2131
2132         _G.accInUse++;
2133         aopOp(IC_RESULT(ic),ic,FALSE);
2134         _G.accInUse--;
2135
2136         assignResultValue(IC_RESULT(ic));
2137
2138         DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2139             AopType(AOP_TYPE(IC_RESULT(ic))));
2140
2141         freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2142     }
2143
2144     /* if register bank was saved then pop them */
2145     if (ic->bankSaved)
2146         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2147
2148     /* if we hade saved some registers then unsave them */
2149     if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2150         unsaveRegisters (ic);
2151
2152
2153 }
2154
2155 /*-----------------------------------------------------------------*/
2156 /* genPcall - generates a call by pointer statement                */
2157 /*-----------------------------------------------------------------*/
2158 static void genPcall (iCode *ic)
2159 {
2160     sym_link *dtype;
2161     symbol *albl = newiTempLabel(NULL);
2162     symbol *blbl = newiTempLabel(NULL);
2163     PIC_OPCODE poc;
2164     pCodeOp *pcop;
2165     operand *left;
2166
2167     FENTRY;
2168
2169     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2170     /* if caller saves & we have not saved then */
2171     if (!ic->regsSaved)
2172         saveRegisters(ic);
2173
2174         /* if we are calling a function that is not using
2175         the same register bank then we need to save the
2176     destination registers on the stack */
2177     dtype = operandType(IC_LEFT(ic));
2178     if (currFunc && dtype &&
2179         IFFUNC_ISISR(currFunc->type) &&
2180         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2181         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2182
2183     left = IC_LEFT(ic);
2184     aopOp(left,ic,FALSE);
2185     DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2186
2187     poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2188
2189     pushSide(IC_LEFT(ic), FPTRSIZE);
2190
2191     /* if send set is not empty, assign parameters */
2192     if (_G.sendSet) {
2193
2194         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2195         /* no way to pass args - W always gets used to make the call */
2196     }
2197     /* first idea - factor out a common helper function and call it.
2198     But don't know how to get it generated only once in its own block
2199
2200     if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2201         char *rname;
2202         char *buffer;
2203         rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2204         DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2205         buffer = Safe_calloc(1,strlen(rname)+16);
2206         sprintf(buffer, "%s_goto_helper", rname);
2207         addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2208         free(buffer);
2209     }
2210     */
2211     emitpcode(POC_CALL,popGetLabel(albl->key));
2212     pcop = popGetLabel(blbl->key);
2213     emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2214     emitpcode(POC_GOTO,pcop);
2215     emitpLabel(albl->key);
2216
2217     emitpcode(poc,popGetAddr(AOP(left),1,0));
2218     emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2219     emitpcode(poc,popGetAddr(AOP(left),0,0));
2220     emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2221
2222     emitpLabel(blbl->key);
2223
2224     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2225
2226     /* if we need to assign a result value */
2227     if ((IS_ITEMP(IC_RESULT(ic)) &&
2228         (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2229         OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2230         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2231
2232         _G.accInUse++;
2233         aopOp(IC_RESULT(ic),ic,FALSE);
2234         _G.accInUse--;
2235
2236         GpsuedoStkPtr = 0;
2237
2238         assignResultValue(IC_RESULT(ic));
2239
2240         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2241     }
2242
2243     /* if register bank was saved then unsave them */
2244     if (currFunc && dtype &&
2245         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2246         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2247
2248         /* if we hade saved some registers then
2249     unsave them */
2250     if (ic->regsSaved)
2251         unsaveRegisters (ic);
2252
2253 }
2254
2255 /*-----------------------------------------------------------------*/
2256 /* resultRemat - result  is rematerializable                       */
2257 /*-----------------------------------------------------------------*/
2258 static int resultRemat (iCode *ic)
2259 {
2260     //  DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2261     FENTRY;
2262
2263     if (SKIP_IC(ic) || ic->op == IFX)
2264         return 0;
2265
2266     if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2267         symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2268         if (sym->remat && !POINTER_SET(ic))
2269             return 1;
2270     }
2271
2272     return 0;
2273 }
2274
2275 /*-----------------------------------------------------------------*/
2276 /* genFunction - generated code for function entry                 */
2277 /*-----------------------------------------------------------------*/
2278 static void genFunction (iCode *ic)
2279 {
2280     symbol *sym;
2281     sym_link *ftype;
2282
2283     FENTRY;
2284
2285     DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2286
2287     labelOffset += (max_key+4);
2288     max_key=0;
2289     GpsuedoStkPtr=0;
2290     _G.nRegsSaved = 0;
2291     /* create the function header */
2292     pic14_emitcode(";","-----------------------------------------");
2293     pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2294     pic14_emitcode(";","-----------------------------------------");
2295
2296     /* prevent this symbol from being emitted as 'extern' */
2297     pic14_stringInSet(sym->rname, &pic14_localFunctions, 1);
2298
2299     pic14_emitcode("","%s:",sym->rname);
2300     addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2301
2302     /* mark symbol as NOT extern (even if it was declared so previously) */
2303     assert(IS_SPEC(sym->etype));
2304     SPEC_EXTR(sym->etype) = 0;
2305     sym->cdef = 0;
2306     if (!SPEC_OCLS(sym->etype)) SPEC_OCLS(sym->etype) = code;
2307     addSetIfnotP(&SPEC_OCLS(sym->etype)->syms, sym);
2308
2309     ftype = operandType(IC_LEFT(ic));
2310
2311     /* if critical function then turn interrupts off */
2312     if (IFFUNC_ISCRITICAL(ftype))
2313         pic14_emitcode("clr","ea");
2314
2315         /* here we need to generate the equates for the
2316     register bank if required */
2317 #if 0
2318     if (FUNC_REGBANK(ftype) != rbank) {
2319         int i ;
2320
2321         rbank = FUNC_REGBANK(ftype);
2322         for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2323             if (strcmp(regspic14[i].base,"0") == 0)
2324                 pic14_emitcode("","%s = 0x%02x",
2325                 regspic14[i].dname,
2326                 8*rbank+regspic14[i].offset);
2327             else
2328                 pic14_emitcode ("","%s = %s + 0x%02x",
2329                 regspic14[i].dname,
2330                 regspic14[i].base,
2331                 8*rbank+regspic14[i].offset);
2332         }
2333     }
2334 #endif
2335
2336     /* if this is an interrupt service routine */
2337     pic14_inISR = 0;
2338     if (IFFUNC_ISISR(sym->type)) {
2339         pic14_inISR = 1;
2340         emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2341         emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2342         /* XXX: Why? Does this assume that ssave and psave reside
2343          * in a shared bank or bank0? We cannot guarantee the
2344          * latter...
2345          */
2346         emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2347         emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2348         //emitpcode(POC_MOVWF,  popGetExternal("___sdcc_saved_status",1 ));
2349         emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2350         /* during an interrupt PCLATH must be cleared before a goto or call statement */
2351         emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));
2352         emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2353         //emitpcode(POC_MOVWF,  popGetExternal("___sdcc_saved_pclath", 1));
2354         emitpcode(POC_MOVFW,  popCopyReg(&pc_fsr));
2355         emitpcode(POC_MOVWF,  popGetExternal("___sdcc_saved_fsr", 1));
2356
2357         pBlockConvert2ISR(pb);
2358         pic14_hasInterrupt = 1;
2359     } else {
2360     /* if callee-save to be used for this function
2361         then save the registers being used in this function */
2362         if (IFFUNC_CALLEESAVES(sym->type)) {
2363             int i;
2364
2365             /* if any registers used */
2366             if (sym->regsUsed) {
2367                 /* save the registers used */
2368                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2369                     if (bitVectBitValue(sym->regsUsed,i)) {
2370                         //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2371                         _G.nRegsSaved++;
2372                     }
2373                 }
2374             }
2375         }
2376     }
2377
2378     /* set the register bank to the desired value */
2379     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2380         pic14_emitcode("push","psw");
2381         pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);
2382     }
2383
2384     if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2385
2386         if (options.useXstack) {
2387             pic14_emitcode("mov","r0,%s",spname);
2388             pic14_emitcode("mov","a,_bp");
2389             pic14_emitcode("movx","@r0,a");
2390             pic14_emitcode("inc","%s",spname);
2391         }
2392         else
2393         {
2394             /* set up the stack */
2395             pic14_emitcode ("push","_bp");   /* save the callers stack  */
2396         }
2397         pic14_emitcode ("mov","_bp,%s",spname);
2398     }
2399
2400     /* adjust the stack for the function */
2401     if (sym->stack) {
2402
2403         int i = sym->stack;
2404         if (i > 256 )
2405             werror(W_STACK_OVERFLOW,sym->name);
2406
2407         if (i > 3 && sym->recvSize < 4) {
2408
2409             pic14_emitcode ("mov","a,sp");
2410             pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2411             pic14_emitcode ("mov","sp,a");
2412
2413         }
2414         else
2415             while(i--)
2416                 pic14_emitcode("inc","sp");
2417     }
2418
2419     if (sym->xstack) {
2420
2421         pic14_emitcode ("mov","a,_spx");
2422         pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2423         pic14_emitcode ("mov","_spx,a");
2424     }
2425
2426 }
2427
2428 /*-----------------------------------------------------------------*/
2429 /* genEndFunction - generates epilogue for functions               */
2430 /*-----------------------------------------------------------------*/
2431 static void genEndFunction (iCode *ic)
2432 {
2433     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2434
2435     FENTRY;
2436
2437     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2438
2439     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2440     {
2441         pic14_emitcode ("mov","%s,_bp",spname);
2442     }
2443
2444     /* if use external stack but some variables were
2445     added to the local stack then decrement the
2446     local stack */
2447     if (options.useXstack && sym->stack) {
2448         pic14_emitcode("mov","a,sp");
2449         pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2450         pic14_emitcode("mov","sp,a");
2451     }
2452
2453
2454     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2455         if (options.useXstack) {
2456             pic14_emitcode("mov","r0,%s",spname);
2457             pic14_emitcode("movx","a,@r0");
2458             pic14_emitcode("mov","_bp,a");
2459             pic14_emitcode("dec","%s",spname);
2460         }
2461         else
2462         {
2463             pic14_emitcode ("pop","_bp");
2464         }
2465     }
2466
2467     /* restore the register bank    */
2468     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2469         pic14_emitcode ("pop","psw");
2470
2471     if (IFFUNC_ISISR(sym->type)) {
2472
2473         /* now we need to restore the registers */
2474         /* if this isr has no bank i.e. is going to
2475         run with bank 0 , then we need to save more
2476 registers :-) */
2477         if (!FUNC_REGBANK(sym->type)) {
2478
2479         /* if this function does not call any other
2480         function then we can be economical and
2481             save only those registers that are used */
2482             if (! IFFUNC_HASFCALL(sym->type)) {
2483                 int i;
2484
2485                 /* if any registers used */
2486                 if (sym->regsUsed) {
2487                     /* save the registers used */
2488                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2489                         if (bitVectBitValue(sym->regsUsed,i)) {
2490                             pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2491                         }
2492                     }
2493                 }
2494
2495             } else {
2496                 /* this function has a function call; cannot
2497                    determines register usage so we will have the
2498                    entire bank */
2499                 unsaverbank(0,ic,FALSE);
2500             }
2501         }
2502
2503         /* if debug then send end of function */
2504         if (options.debug && debugFile && currFunc) {
2505             debugFile->writeEndFunction (currFunc, ic, 1);
2506         }
2507
2508         emitpcode(POC_MOVFW,  popGetExternal("___sdcc_saved_fsr", 1));
2509         emitpcode(POC_MOVWF,  popCopyReg(&pc_fsr));
2510         //emitpcode(POC_MOVFW,  popGetExternal("___sdcc_saved_pclath", 1));
2511         emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
2512         emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
2513         emitpcode(POC_CLRF,   popCopyReg(&pc_status)); // see genFunction
2514         //emitpcode(POC_SWAPFW, popGetExternal("___sdcc_saved_status", 1));
2515         emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
2516         emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
2517         emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
2518         emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
2519         addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
2520         emitpcodeNULLop(POC_RETFIE);
2521     }
2522     else {
2523         if (IFFUNC_ISCRITICAL(sym->type))
2524             pic14_emitcode("setb","ea");
2525
2526         if (IFFUNC_CALLEESAVES(sym->type)) {
2527             int i;
2528
2529             /* if any registers used */
2530             if (sym->regsUsed) {
2531                 /* save the registers used */
2532                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2533                     if (bitVectBitValue(sym->regsUsed,i)) {
2534                         pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2535                     }
2536                 }
2537             }
2538         }
2539
2540         /* if debug then send end of function */
2541         if (options.debug && debugFile && currFunc) {
2542             debugFile->writeEndFunction (currFunc, ic, 1);
2543         }
2544
2545         pic14_emitcode ("return","");
2546         emitpcodeNULLop(POC_RETURN);
2547
2548         /* Mark the end of a function */
2549         addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
2550     }
2551
2552 }
2553
2554 /*-----------------------------------------------------------------*/
2555 /* genRet - generate code for return statement                     */
2556 /*-----------------------------------------------------------------*/
2557 static void genRet (iCode *ic)
2558 {
2559     int size,offset = 0;
2560
2561     FENTRY;
2562
2563     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2564     /* if we have no return value then
2565     just generate the "ret" */
2566     if (!IC_LEFT(ic))
2567         goto jumpret;
2568
2569         /* we have something to return then
2570     move the return value into place */
2571     aopOp(IC_LEFT(ic),ic,FALSE);
2572     size = AOP_SIZE(IC_LEFT(ic));
2573
2574     for (offset = 0; offset < size; offset++)
2575     {
2576         pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
2577     }
2578
2579     freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2580
2581 jumpret:
2582     /* generate a jump to the return label
2583     if the next is not the return statement */
2584     if (!(ic->next && ic->next->op == LABEL &&
2585         IC_LABEL(ic->next) == returnLabel)) {
2586
2587         emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
2588     }
2589
2590 }
2591
2592 /*-----------------------------------------------------------------*/
2593 /* genLabel - generates a label                                    */
2594 /*-----------------------------------------------------------------*/
2595 static void genLabel (iCode *ic)
2596 {
2597     FENTRY;
2598
2599     /* special case never generate */
2600     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2601     if (IC_LABEL(ic) == entryLabel)
2602         return ;
2603
2604     emitpLabel(IC_LABEL(ic)->key);
2605     pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
2606 }
2607
2608 /*-----------------------------------------------------------------*/
2609 /* genGoto - generates a goto                                      */
2610 /*-----------------------------------------------------------------*/
2611 //tsd
2612 static void genGoto (iCode *ic)
2613 {
2614     FENTRY;
2615
2616     emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
2617     pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
2618 }
2619
2620
2621 /*-----------------------------------------------------------------*/
2622 /* genMultbits :- multiplication of bits                           */
2623 /*-----------------------------------------------------------------*/
2624 static void genMultbits (operand *left,
2625                          operand *right,
2626                          operand *result)
2627 {
2628     FENTRY;
2629     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2630
2631     if(!pic14_sameRegs(AOP(result),AOP(right)))
2632         emitpcode(POC_BSF,  popGet(AOP(result),0));
2633
2634     emitpcode(POC_BTFSC,popGet(AOP(right),0));
2635     emitpcode(POC_BTFSS,popGet(AOP(left),0));
2636     emitpcode(POC_BCF,  popGet(AOP(result),0));
2637
2638 }
2639
2640
2641 /*-----------------------------------------------------------------*/
2642 /* genMultOneByte : 8 bit multiplication & division                */
2643 /*-----------------------------------------------------------------*/
2644 static void genMultOneByte (operand *left,
2645                             operand *right,
2646                             operand *result)
2647 {
2648     char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
2649
2650     // symbol *lbl ;
2651     int size,offset,i;
2652
2653
2654     FENTRY;
2655
2656     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2657     DEBUGpic14_AopType(__LINE__,left,right,result);
2658     DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
2659
2660     /* (if two literals, the value is computed before) */
2661     /* if one literal, literal on the right */
2662     if (AOP_TYPE(left) == AOP_LIT){
2663         operand *t = right;
2664         right = left;
2665         left = t;
2666     }
2667
2668     assert (AOP_SIZE(left) == AOP_SIZE(right));
2669
2670     size = min(AOP_SIZE(result),AOP_SIZE(left));
2671     offset = Gstack_base_addr - (2*size - 1);
2672
2673     /* pass right operand as argument */
2674     for (i=0; i < size; i++)
2675     {
2676         mov2w (AOP(right), i);
2677         emitpcode(POC_MOVWF, popRegFromIdx (++offset));
2678     } // for
2679
2680     /* pass left operand as argument */
2681     for (i=0; i < size; i++)
2682     {
2683         mov2w (AOP(left), i);
2684         if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
2685     } // for
2686     assert (offset == Gstack_base_addr);
2687
2688     /* call library routine */
2689     assert (size > 0 && size <= 4);
2690     call_libraryfunc (func[size]);
2691
2692     /* assign result */
2693     movwf (AOP(result), size-1);
2694     for (i=0; i < size - 1; i++)
2695     {
2696         emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
2697         movwf (AOP(result), size - 2 - i);
2698     } // for
2699
2700     /* now (zero-/sign) extend the result to its size */
2701     addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2702 }
2703
2704 /*-----------------------------------------------------------------*/
2705 /* genMult - generates code for multiplication                     */
2706 /*-----------------------------------------------------------------*/
2707 static void genMult (iCode *ic)
2708 {
2709     operand *left = IC_LEFT(ic);
2710     operand *right = IC_RIGHT(ic);
2711     operand *result= IC_RESULT(ic);
2712
2713     FENTRY;
2714
2715     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2716     /* assign the amsops */
2717     aopOp (left,ic,FALSE);
2718     aopOp (right,ic,FALSE);
2719     aopOp (result,ic,TRUE);
2720
2721     DEBUGpic14_AopType(__LINE__,left,right,result);
2722
2723     /* special cases first */
2724     /* both are bits */
2725     if (AOP_TYPE(left) == AOP_CRY &&
2726         AOP_TYPE(right)== AOP_CRY) {
2727         genMultbits(left,right,result);
2728         goto release ;
2729     }
2730
2731     /* if both are of size == 1 */
2732     if (AOP_SIZE(left) == 1 &&
2733         AOP_SIZE(right) == 1 ) {
2734         genMultOneByte(left,right,result);
2735         goto release ;
2736     }
2737
2738     /* should have been converted to function call */
2739     assert(0) ;
2740
2741 release :
2742     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2743     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2744     freeAsmop(result,NULL,ic,TRUE);
2745 }
2746
2747 /*-----------------------------------------------------------------*/
2748 /* genDivbits :- division of bits                                  */
2749 /*-----------------------------------------------------------------*/
2750 static void genDivbits (operand *left,
2751                         operand *right,
2752                         operand *result)
2753 {
2754
2755     char *l;
2756
2757     FENTRY;
2758
2759     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2760     /* the result must be bit */
2761     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
2762     l = aopGet(AOP(left),0,FALSE,FALSE);
2763
2764     MOVA(l);
2765
2766     pic14_emitcode("div","ab");
2767     pic14_emitcode("rrc","a");
2768     aopPut(AOP(result),"c",0);
2769 }
2770
2771 /*-----------------------------------------------------------------*/
2772 /* genDivOneByte : 8 bit division                                  */
2773 /*-----------------------------------------------------------------*/
2774 static void genDivOneByte (operand *left,
2775                            operand *right,
2776                            operand *result)
2777 {
2778     int size;
2779     int sign;
2780
2781     FENTRY;
2782     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2783
2784     assert (AOP_SIZE(right) == 1);
2785     assert (AOP_SIZE(left) == 1);
2786
2787     size = min(AOP_SIZE(result),AOP_SIZE(left));
2788     sign = !(SPEC_USIGN(operandType(left))
2789         && SPEC_USIGN(operandType(right)));
2790
2791     if (AOP_TYPE(right) == AOP_LIT)
2792     {
2793         /* XXX: might add specialized code */
2794     }
2795
2796     if (!sign)
2797     {
2798         /* unsigned division */
2799     #if 1
2800         mov2w(AOP(right),0);
2801         emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
2802         mov2w(AOP(left),0);
2803         call_libraryfunc("__divuchar");
2804         movwf(AOP(result),0);
2805     #else
2806         pCodeOp *temp;
2807         symbol *lbl;
2808
2809         temp = popGetTempReg();
2810         lbl = newiTempLabel(NULL);
2811
2812         /* XXX: improve this naive approach:
2813            [result] = [a] / [b]
2814             ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
2815
2816            In PIC assembler:
2817            movf  left,W
2818            movwf temp       // temp <-- left
2819            movf  right,W    // W <-- right
2820            clrf  result
2821            label1:
2822            incf  result
2823            subwf temp,F     // temp <-- temp - W
2824            skipNC       // subwf clears CARRY (i.e. sets BORROW) if temp < W
2825            goto  label1
2826            decf result      // we just subtract once too often
2827          */
2828
2829         /* XXX: This loops endlessly on DIVIDE BY ZERO */
2830         /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
2831
2832         mov2w(AOP(left),0);
2833         emitpcode(POC_MOVWF, temp);
2834         mov2w(AOP(right),0);
2835         emitpcode(POC_CLRF, popGet(AOP(result),0));
2836
2837         emitpLabel(lbl->key);
2838         emitpcode(POC_INCF, popGet(AOP(result),0));
2839         emitpcode(POC_SUBWF, temp);
2840         emitSKPNC;
2841         emitpcode(POC_GOTO, popGetLabel(lbl->key));
2842         emitpcode(POC_DECF, popGet(AOP(result),0));
2843         popReleaseTempReg(temp);
2844     #endif
2845     }
2846     else
2847     {
2848         /* signed division */
2849         mov2w(AOP(right),0);
2850         emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
2851         mov2w(AOP(left),0);
2852         call_libraryfunc("__divschar");
2853         movwf(AOP(result),0);
2854     }
2855
2856     /* now performed the signed/unsigned division -- extend result */
2857     addSign(result, 1, sign);
2858 }
2859
2860 /*-----------------------------------------------------------------*/
2861 /* genDiv - generates code for division                */
2862 /*-----------------------------------------------------------------*/
2863 static void genDiv (iCode *ic)
2864 {
2865     operand *left = IC_LEFT(ic);
2866     operand *right = IC_RIGHT(ic);
2867     operand *result= IC_RESULT(ic);
2868
2869     FENTRY;
2870     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2871     /* assign the amsops */
2872     aopOp (left,ic,FALSE);
2873     aopOp (right,ic,FALSE);
2874     aopOp (result,ic,TRUE);
2875
2876     /* special cases first */
2877     /* both are bits */
2878     if (AOP_TYPE(left) == AOP_CRY &&
2879         AOP_TYPE(right)== AOP_CRY) {
2880         genDivbits(left,right,result);
2881         goto release ;
2882     }
2883
2884     /* if both are of size == 1 */
2885     if (AOP_SIZE(left) == 1 &&
2886         AOP_SIZE(right) == 1 ) {
2887         genDivOneByte(left,right,result);
2888         goto release ;
2889     }
2890
2891     /* should have been converted to function call */
2892     assert(0);
2893 release :
2894     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2895     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2896     freeAsmop(result,NULL,ic,TRUE);
2897 }
2898
2899 /*-----------------------------------------------------------------*/
2900 /* genModOneByte : 8 bit modulus                                   */
2901 /*-----------------------------------------------------------------*/
2902 static void genModOneByte (operand *left,
2903                            operand *right,
2904                            operand *result)
2905 {
2906     int size;
2907     int sign;
2908
2909     FENTRY;
2910     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2911
2912     assert (AOP_SIZE(right) == 1);
2913     assert (AOP_SIZE(left) == 1);
2914
2915     size = min(AOP_SIZE(result),AOP_SIZE(left));
2916     sign = !(SPEC_USIGN(operandType(left))
2917         && SPEC_USIGN(operandType(right)));
2918
2919     if (AOP_TYPE(right) == AOP_LIT)
2920     {
2921         /* XXX: might add specialized code */
2922     }
2923
2924     if (!sign)
2925     {
2926         /* unsigned division */
2927     #if 1
2928         mov2w(AOP(right),0);
2929         emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
2930         mov2w(AOP(left),0);
2931         call_libraryfunc("__moduchar");
2932         movwf(AOP(result),0);
2933     #else
2934         pCodeOp *temp;
2935         symbol *lbl;
2936
2937         lbl = newiTempLabel(NULL);
2938
2939         assert(!pic14_sameRegs(AOP(right),AOP(result)));
2940
2941         /* XXX: improve this naive approach:
2942            [result] = [a] % [b]
2943             ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
2944
2945            In PIC assembler:
2946            movf  left,W
2947            movwf result     // result <-- left
2948            movf  right,W    // W <-- right
2949            label1:
2950            subwf result,F   // result <-- result - W
2951            skipNC       // subwf clears CARRY (i.e. sets BORROW) if result < W
2952            goto  label1
2953            addwf result, F  // we just subtract once too often
2954          */
2955
2956         /* XXX: This loops endlessly on DIVIDE BY ZERO */
2957         /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
2958
2959         if (!pic14_sameRegs(AOP(left), AOP(result)))
2960         {
2961             mov2w(AOP(left),0);
2962             emitpcode(POC_MOVWF, popGet(AOP(result),0));
2963         }
2964         mov2w(AOP(right),0);
2965
2966         emitpLabel(lbl->key);
2967         emitpcode(POC_SUBWF, popGet(AOP(result),0));
2968         emitSKPNC;
2969         emitpcode(POC_GOTO, popGetLabel(lbl->key));
2970         emitpcode(POC_ADDWF, popGet(AOP(result),0));
2971     #endif
2972     }
2973     else
2974     {
2975         /* signed division */
2976         mov2w(AOP(right),0);
2977         emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
2978         mov2w(AOP(left),0);
2979         call_libraryfunc("__modschar");
2980         movwf(AOP(result),0);
2981     }
2982
2983     /* now we performed the signed/unsigned modulus -- extend result */
2984     addSign(result, 1, sign);
2985 }
2986
2987 /*-----------------------------------------------------------------*/
2988 /* genMod - generates code for division                            */
2989 /*-----------------------------------------------------------------*/
2990 static void genMod (iCode *ic)
2991 {
2992     operand *left = IC_LEFT(ic);
2993     operand *right = IC_RIGHT(ic);
2994     operand *result= IC_RESULT(ic);
2995
2996     FENTRY;
2997     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2998     /* assign the amsops */
2999     aopOp (left,ic,FALSE);
3000     aopOp (right,ic,FALSE);
3001     aopOp (result,ic,TRUE);
3002
3003     /* if both are of size == 1 */
3004     if (AOP_SIZE(left) == 1 &&
3005         AOP_SIZE(right) == 1 ) {
3006         genModOneByte(left,right,result);
3007         goto release ;
3008     }
3009
3010     /* should have been converted to function call */
3011     assert(0);
3012
3013 release :
3014     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3015     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3016     freeAsmop(result,NULL,ic,TRUE);
3017 }
3018
3019 /*-----------------------------------------------------------------*/
3020 /* genIfxJump :- will create a jump depending on the ifx           */
3021 /*-----------------------------------------------------------------*/
3022 /*
3023 note: May need to add parameter to indicate when a variable is in bit space.
3024 */
3025 static void genIfxJump (iCode *ic, char *jval)
3026 {
3027
3028     FENTRY;
3029     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3030     /* if true label then we jump if condition
3031     supplied is true */
3032     if ( IC_TRUE(ic) ) {
3033
3034         if(strcmp(jval,"a") == 0)
3035             emitSKPZ;
3036         else if (strcmp(jval,"c") == 0)
3037             emitSKPC;
3038         else {
3039             DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3040             emitpcode(POC_BTFSC,    newpCodeOpBit(jval,-1,1));
3041         }
3042
3043         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3044         pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3045
3046     }
3047     else {
3048         /* false label is present */
3049         if(strcmp(jval,"a") == 0)
3050             emitSKPNZ;
3051         else if (strcmp(jval,"c") == 0)
3052             emitSKPNC;
3053         else {
3054             DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3055             emitpcode(POC_BTFSS,    newpCodeOpBit(jval,-1,1));
3056         }
3057
3058         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3059         pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3060
3061     }
3062
3063
3064     /* mark the icode as generated */
3065     ic->generated = 1;
3066 }
3067
3068 /*-----------------------------------------------------------------*/
3069 /* genSkipc                                                        */
3070 /*-----------------------------------------------------------------*/
3071 static void genSkipc(resolvedIfx *rifx)
3072 {
3073     FENTRY;
3074     if(!rifx)
3075         return;
3076
3077     if(rifx->condition)
3078         emitSKPNC;
3079     else
3080         emitSKPC;
3081
3082     emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3083     emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3084     rifx->generated = 1;
3085 }
3086
3087 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3088 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
3089 #define DEBUGpc           emitpComment
3090
3091 /*-----------------------------------------------------------------*/
3092 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
3093 /*                  aop (if it's NOT a literal) or from lit (if    */
3094 /*                  aop is a literal)                              */
3095 /*-----------------------------------------------------------------*/
3096 static void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset)
3097 {
3098   if (aop->type == AOP_LIT) {
3099     emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3100   } else {
3101     emitpcode (POC_MOVFW, popGet (aop, offset));
3102   }
3103 }
3104
3105 /* genCmp performs a left < right comparison, stores
3106  * the outcome in result (if != NULL) and generates
3107  * control flow code for the ifx (if != NULL).
3108  *
3109  * This version leaves in sequences like
3110  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3111  * which should be optmized by the peephole
3112  * optimizer - RN 2005-01-01 */
3113 static void genCmp (operand *left,operand *right,
3114                     operand *result, iCode *ifx, int sign)
3115 {
3116   resolvedIfx rIfx;
3117   int size;
3118   int offs;
3119   symbol *templbl;
3120   operand *dummy;
3121   unsigned long lit;
3122   unsigned long mask;
3123   int performedLt;
3124   int invert_result = 0;
3125
3126   FENTRY;
3127
3128   assert (AOP_SIZE(left) == AOP_SIZE(right));
3129   assert (left && right);
3130
3131   size = AOP_SIZE(right) - 1;
3132   mask = (0x100UL << (size*8)) - 1;
3133   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3134   performedLt = 1;
3135   templbl = NULL;
3136   lit = 0;
3137
3138   resolveIfx (&rIfx, ifx);
3139
3140   /**********************************************************************
3141    * handle bits - bit compares are promoted to int compares seemingly! *
3142    **********************************************************************/
3143 #if 0
3144   // THIS IS COMPLETELY UNTESTED!
3145   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3146     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3147     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3148     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3149
3150     emitSETC;
3151     // 1 < {0,1} is false --> clear C by skipping the next instruction
3152     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3153     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3154     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3155     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3156     emitCLRC; // only skipped for left=0 && right=1
3157
3158     goto correct_result_in_carry;
3159   } // if
3160 #endif
3161
3162   /*************************************************
3163    * make sure that left is register (or the like) *
3164    *************************************************/
3165   if (!isAOP_REGlike(left)) {
3166     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3167     assert (isAOP_LIT(left));
3168     assert (isAOP_REGlike(right));
3169     // swap left and right
3170     // left < right <==> right > left <==> (right >= left + 1)
3171     lit = ulFromVal(AOP(left)->aopu.aop_lit);
3172
3173     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
3174       // MAXVALUE < right? always false
3175       if (performedLt) emitCLRC; else emitSETC;
3176       goto correct_result_in_carry;
3177     } // if
3178
3179     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
3180     // that's why we handled it above.
3181     lit++;
3182
3183     dummy = left;
3184     left = right;
3185     right = dummy;
3186
3187     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
3188   } else if (isAOP_LIT(right)) {
3189     lit = ulFromVal(AOP(right)->aopu.aop_lit);
3190   } // if
3191
3192   assert (isAOP_REGlike(left)); // left must be register or the like
3193   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
3194
3195   /*************************************************
3196    * special cases go here                         *
3197    *************************************************/
3198
3199   if (isAOP_LIT(right)) {
3200     if (!sign) {
3201       // unsigned comparison to a literal
3202       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
3203       if (lit == 0) {
3204     // unsigned left < 0? always false
3205     if (performedLt) emitCLRC; else emitSETC;
3206     goto correct_result_in_carry;
3207       }
3208     } else {
3209       // signed comparison to a literal
3210       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
3211       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
3212     // signed left < 0x80000000? always false
3213     if (performedLt) emitCLRC; else emitSETC;
3214     goto correct_result_in_carry;
3215       } else if (lit == 0) {
3216     // compare left < 0; set CARRY if SIGNBIT(left) is set
3217     if (performedLt) emitSETC; else emitCLRC;
3218     emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
3219     if (performedLt) emitCLRC; else emitSETC;
3220     goto correct_result_in_carry;
3221       }
3222     } // if (!sign)
3223   } // right is literal
3224
3225   /*************************************************
3226    * perform a general case comparison             *
3227    * make sure we get CARRY==1 <==> left >= right  *
3228    *************************************************/
3229   // compare most significant bytes
3230   //DEBUGpc ("comparing bytes at offset %d", size);
3231   if (!sign) {
3232     // unsigned comparison
3233     pic14_mov2w_regOrLit (AOP(right), lit, size);
3234     emitpcode (POC_SUBFW, popGet (AOP(left), size));
3235   } else {
3236     // signed comparison
3237     // (add 2^n to both operands then perform an unsigned comparison)
3238     if (isAOP_LIT(right)) {
3239       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
3240       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
3241
3242       if (litbyte == 0x80) {
3243     // left >= 0x80 -- always true, but more bytes to come
3244     mov2w (AOP(left), size);
3245     emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
3246     emitSETC;
3247       } else {
3248     // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
3249     mov2w (AOP(left), size);
3250     emitpcode (POC_ADDLW, popGetLit (0x80));
3251     emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
3252       } // if
3253     } else {
3254       pCodeOp *pctemp = popGetTempReg();
3255       mov2w (AOP(left), size);
3256       emitpcode (POC_ADDLW, popGetLit (0x80));
3257       emitpcode (POC_MOVWF, pctemp);
3258       mov2w (AOP(right), size);
3259       emitpcode (POC_ADDLW, popGetLit (0x80));
3260       emitpcode (POC_SUBFW, pctemp);
3261       popReleaseTempReg(pctemp);
3262     }
3263   } // if (!sign)
3264
3265   // compare remaining bytes (treat as unsigned case from above)
3266   templbl = newiTempLabel ( NULL );
3267   offs = size;
3268   while (offs--) {
3269     //DEBUGpc ("comparing bytes at offset %d", offs);
3270     emitSKPZ;
3271     emitpcode (POC_GOTO, popGetLabel (templbl->key));
3272     pic14_mov2w_regOrLit (AOP(right), lit, offs);
3273     emitpcode (POC_SUBFW, popGet (AOP(left), offs));
3274   } // while (offs)
3275   emitpLabel (templbl->key);
3276   goto result_in_carry;
3277
3278 result_in_carry:
3279
3280   /****************************************************
3281    * now CARRY contains the result of the comparison: *
3282    * SUBWF sets CARRY iff                             *
3283    * F-W >= 0 <==> F >= W <==> !(F < W)               *
3284    * (F=left, W=right)                                *
3285    ****************************************************/
3286
3287   if (performedLt) {
3288     invert_result = 1;
3289     // value will be used in the following genSkipc()
3290     rIfx.condition ^= 1;
3291   } // if
3292
3293 correct_result_in_carry:
3294
3295   // assign result to variable (if neccessary)
3296   if (result && AOP_TYPE(result) != AOP_CRY) {
3297     //DEBUGpc ("assign result");
3298     size = AOP_SIZE(result);
3299     while (size--) {
3300       emitpcode (POC_CLRF, popGet (AOP(result), size));
3301     } // while
3302     if (invert_result) {
3303       emitSKPC;
3304       emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
3305     } else {
3306       emitpcode (POC_RLF, popGet (AOP(result), 0));
3307     }
3308   } // if (result)
3309
3310   // perform conditional jump
3311   if (ifx) {
3312     //DEBUGpc ("generate control flow");
3313     genSkipc (&rIfx);
3314     ifx->generated = 1;
3315   } // if
3316 }
3317
3318 /*-----------------------------------------------------------------*/
3319 /* genCmpGt :- greater than comparison                             */
3320 /*-----------------------------------------------------------------*/
3321 static void genCmpGt (iCode *ic, iCode *ifx)
3322 {
3323     operand *left, *right, *result;
3324     sym_link *letype , *retype;
3325     int sign ;
3326
3327     FENTRY;
3328     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3329     left = IC_LEFT(ic);
3330     right= IC_RIGHT(ic);
3331     result = IC_RESULT(ic);
3332
3333     letype = getSpec(operandType(left));
3334     retype =getSpec(operandType(right));
3335     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3336     /* assign the amsops */
3337     aopOp (left,ic,FALSE);
3338     aopOp (right,ic,FALSE);
3339     aopOp (result,ic,TRUE);
3340
3341     genCmp(right, left, result, ifx, sign);
3342
3343     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3344     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3345     freeAsmop(result,NULL,ic,TRUE);
3346 }
3347
3348 /*-----------------------------------------------------------------*/
3349 /* genCmpLt - less than comparisons                                */
3350 /*-----------------------------------------------------------------*/
3351 static void genCmpLt (iCode *ic, iCode *ifx)
3352 {
3353     operand *left, *right, *result;
3354     sym_link *letype , *retype;
3355     int sign ;
3356
3357     FENTRY;
3358     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3359     left = IC_LEFT(ic);
3360     right= IC_RIGHT(ic);
3361     result = IC_RESULT(ic);
3362
3363     letype = getSpec(operandType(left));
3364     retype =getSpec(operandType(right));
3365     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3366
3367     /* assign the amsops */
3368     aopOp (left,ic,FALSE);
3369     aopOp (right,ic,FALSE);
3370     aopOp (result,ic,TRUE);
3371
3372     genCmp(left, right, result, ifx, sign);
3373
3374     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3375     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3376     freeAsmop(result,NULL,ic,TRUE);
3377 }
3378
3379 /*-----------------------------------------------------------------*/
3380 /* genCmpEq - generates code for equal to                          */
3381 /*-----------------------------------------------------------------*/
3382 static void genCmpEq (iCode *ic, iCode *ifx)
3383 {
3384   operand *left, *right, *result;
3385   int size;
3386   symbol *false_label;
3387
3388   FENTRY;
3389   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3390
3391   if(ifx)
3392     DEBUGpic14_emitcode ("; ifx is non-null","");
3393   else
3394     DEBUGpic14_emitcode ("; ifx is null","");
3395
3396   aopOp((left=IC_LEFT(ic)),ic,FALSE);
3397   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3398   aopOp((result=IC_RESULT(ic)),ic,TRUE);
3399
3400   DEBUGpic14_AopType(__LINE__,left,right,result);
3401
3402   /* if literal, move literal to right */
3403   if (op_isLitLike (IC_LEFT(ic))) {
3404     operand *tmp = right ;
3405     right = left;
3406     left = tmp;
3407   }
3408
3409   false_label = NULL;
3410   if (ifx && !IC_TRUE(ifx))
3411   {
3412     assert (IC_FALSE(ifx));
3413     false_label = IC_FALSE(ifx);
3414   }
3415
3416   size = min(AOP_SIZE(left),AOP_SIZE(right));
3417   assert(!pic14_sameRegs(AOP(result),AOP(left)));
3418   assert(!pic14_sameRegs(AOP(result),AOP(right)));
3419
3420   /* assume left != right */
3421   {
3422     int i;
3423     for (i=0; i < AOP_SIZE(result); i++)
3424     {
3425       emitpcode(POC_CLRF, popGet(AOP(result),i));
3426     }
3427   }
3428
3429   if (AOP_TYPE(right) == AOP_LIT)
3430   {
3431     unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
3432     int i;
3433     size = AOP_SIZE(left);
3434     assert(!op_isLitLike(left));
3435
3436     switch (lit)
3437     {
3438       case 0:
3439         mov2w(AOP(left), 0);
3440     for (i=1; i < size; i++)
3441       emitpcode(POC_IORFW,popGet(AOP(left),i));
3442     /* now Z is set iff `left == right' */
3443     emitSKPZ;
3444     if (!false_label) false_label = newiTempLabel(NULL);
3445     emitpcode(POC_GOTO, popGetLabel(false_label->key));
3446     break;
3447
3448       default:
3449     for (i=0; i < size; i++)
3450     {
3451       mov2w(AOP(left),i);
3452       emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
3453       /* now Z is cleared if `left != right' */
3454       emitSKPZ;
3455       if (!false_label) false_label = newiTempLabel(NULL);
3456       emitpcode(POC_GOTO, popGetLabel(false_label->key));
3457     } // for i
3458     break;
3459     } // switch (lit)
3460   }
3461   else
3462   {
3463     /* right is no literal */
3464     int i;
3465
3466     for (i=0; i < size; i++)
3467     {
3468       mov2w(AOP(right),i);
3469       emitpcode(POC_XORFW,popGet(AOP(left),i));
3470       /* now Z is cleared if `left != right' */
3471       emitSKPZ;
3472       if (!false_label) false_label = newiTempLabel(NULL);
3473       emitpcode(POC_GOTO, popGetLabel(false_label->key));
3474     } // for i
3475   }
3476
3477   /* if we reach here, left == right */
3478
3479   if (AOP_SIZE(result) > 0)
3480   {
3481     emitpcode(POC_INCF, popGet(AOP(result),0));
3482   }
3483
3484   if (ifx && IC_TRUE(ifx))
3485   {
3486     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3487   }
3488
3489   if (false_label && (!ifx || IC_TRUE(ifx)))
3490     emitpLabel(false_label->key);
3491
3492   if (ifx) ifx->generated = 1;
3493
3494   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3495   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3496   freeAsmop(result,NULL,ic,TRUE);
3497 }
3498
3499 /*-----------------------------------------------------------------*/
3500 /* ifxForOp - returns the icode containing the ifx for operand     */
3501 /*-----------------------------------------------------------------*/
3502 static iCode *ifxForOp ( operand *op, iCode *ic )
3503 {
3504     FENTRY;
3505     /* if true symbol then needs to be assigned */
3506     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3507     if (IS_TRUE_SYMOP(op))
3508         return NULL ;
3509
3510     /* if this has register type condition and
3511     the next instruction is ifx with the same operand
3512     and live to of the operand is upto the ifx only then */
3513     if (ic->next &&
3514         ic->next->op == IFX &&
3515         IC_COND(ic->next)->key == op->key &&
3516         OP_SYMBOL(op)->liveTo <= ic->next->seq )
3517         return ic->next;
3518
3519     if (ic->next &&
3520         ic->next->op == IFX &&
3521         IC_COND(ic->next)->key == op->key) {
3522         DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
3523         return ic->next;
3524     }
3525
3526     DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
3527     if (ic->next &&
3528         ic->next->op == IFX)
3529         DEBUGpic14_emitcode ("; ic-next"," is an IFX");
3530
3531     if (ic->next &&
3532         ic->next->op == IFX &&
3533         IC_COND(ic->next)->key == op->key) {
3534         DEBUGpic14_emitcode ("; "," key is okay");
3535         DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
3536             OP_SYMBOL(op)->liveTo,
3537             ic->next->seq);
3538     }
3539
3540
3541     return NULL;
3542 }
3543 /*-----------------------------------------------------------------*/
3544 /* genAndOp - for && operation                                     */
3545 /*-----------------------------------------------------------------*/
3546 static void genAndOp (iCode *ic)
3547 {
3548     operand *left,*right, *result;
3549     /*     symbol *tlbl; */
3550
3551     FENTRY;
3552     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3553     /* note here that && operations that are in an
3554     if statement are taken away by backPatchLabels
3555     only those used in arthmetic operations remain */
3556     aopOp((left=IC_LEFT(ic)),ic,FALSE);
3557     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3558     aopOp((result=IC_RESULT(ic)),ic,FALSE);
3559
3560     DEBUGpic14_AopType(__LINE__,left,right,result);
3561
3562     emitpcode(POC_MOVFW,popGet(AOP(left),0));
3563     emitpcode(POC_ANDFW,popGet(AOP(right),0));
3564     emitpcode(POC_MOVWF,popGet(AOP(result),0));
3565
3566     /* if both are bit variables */
3567     /*     if (AOP_TYPE(left) == AOP_CRY && */
3568     /*         AOP_TYPE(right) == AOP_CRY ) { */
3569     /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
3570     /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
3571     /*         pic14_outBitC(result); */
3572     /*     } else { */
3573     /*         tlbl = newiTempLabel(NULL); */
3574     /*         pic14_toBoolean(left);     */
3575     /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
3576     /*         pic14_toBoolean(right); */
3577     /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
3578     /*         pic14_outBitAcc(result); */
3579     /*     } */
3580
3581     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3582     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3583     freeAsmop(result,NULL,ic,TRUE);
3584 }
3585
3586
3587 /*-----------------------------------------------------------------*/
3588 /* genOrOp - for || operation                                      */
3589 /*-----------------------------------------------------------------*/
3590 /*
3591 tsd pic port -
3592 modified this code, but it doesn't appear to ever get called
3593 */
3594
3595 static void genOrOp (iCode *ic)
3596 {
3597     operand *left,*right, *result;
3598     symbol *tlbl;
3599     int i;
3600
3601     /* note here that || operations that are in an
3602     if statement are taken away by backPatchLabels
3603     only those used in arthmetic operations remain */
3604     FENTRY;
3605     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3606     aopOp((left=IC_LEFT(ic)),ic,FALSE);
3607     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3608     aopOp((result=IC_RESULT(ic)),ic,FALSE);
3609
3610     DEBUGpic14_AopType(__LINE__,left,right,result);
3611
3612     for (i=0; i < AOP_SIZE(result); i++)
3613     {
3614         emitpcode(POC_CLRF, popGet(AOP(result), i));
3615     } // for i
3616
3617     tlbl = newiTempLabel(NULL);
3618     pic14_toBoolean(left);
3619     emitSKPZ;
3620     emitpcode(POC_GOTO, popGetLabel(tlbl->key));
3621     pic14_toBoolean(right);
3622     emitpLabel(tlbl->key);
3623     /* here Z is clear IFF `left || right' */
3624     emitSKPZ;
3625     emitpcode(POC_INCF, popGet(AOP(result), 0));
3626
3627     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3628     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3629     freeAsmop(result,NULL,ic,TRUE);
3630 }
3631
3632 /*-----------------------------------------------------------------*/
3633 /* isLiteralBit - test if lit == 2^n                               */
3634 /*-----------------------------------------------------------------*/
3635 static int isLiteralBit(unsigned long lit)
3636 {
3637     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3638         0x100L,0x200L,0x400L,0x800L,
3639         0x1000L,0x2000L,0x4000L,0x8000L,
3640         0x10000L,0x20000L,0x40000L,0x80000L,
3641         0x100000L,0x200000L,0x400000L,0x800000L,
3642         0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3643         0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3644     int idx;
3645
3646     FENTRY;
3647     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3648     for(idx = 0; idx < 32; idx++)
3649         if(lit == pw[idx])
3650             return idx+1;
3651         return 0;
3652 }
3653
3654 /*-----------------------------------------------------------------*/
3655 /* continueIfTrue -                                                */
3656 /*-----------------------------------------------------------------*/
3657 static void continueIfTrue (iCode *ic)
3658 {
3659     FENTRY;
3660     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3661     if(IC_TRUE(ic))
3662     {
3663         // Why +100?!?
3664         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
3665         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
3666     }
3667     ic->generated = 1;
3668 }
3669
3670 /*-----------------------------------------------------------------*/
3671 /* jmpIfTrue -                                                     */
3672 /*-----------------------------------------------------------------*/
3673 static void jumpIfTrue (iCode *ic)
3674 {
3675     FENTRY;
3676     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3677     if(!IC_TRUE(ic))
3678     {
3679         // Why +100?!?
3680         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
3681         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
3682     }
3683     ic->generated = 1;
3684 }
3685
3686 /*-----------------------------------------------------------------*/
3687 /* jmpTrueOrFalse -                                                */
3688 /*-----------------------------------------------------------------*/
3689 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3690 {
3691     FENTRY;
3692     // ugly but optimized by peephole
3693     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3694     if(IC_TRUE(ic)){
3695         symbol *nlbl = newiTempLabel(NULL);
3696         pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
3697         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
3698         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
3699         pic14_emitcode("","%05d_DS_:",nlbl->key+100);
3700     }
3701     else{
3702         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
3703         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
3704     }
3705     ic->generated = 1;
3706 }
3707
3708 /*-----------------------------------------------------------------*/
3709 /* genAnd  - code for and                                          */
3710 /*-----------------------------------------------------------------*/
3711 static void genAnd (iCode *ic, iCode *ifx)
3712 {
3713     operand *left, *right, *result;
3714     int size, offset=0;
3715     unsigned long lit = 0L;
3716     int bytelit = 0;
3717     resolvedIfx rIfx;
3718
3719     FENTRY;
3720     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3721     aopOp((left = IC_LEFT(ic)),ic,FALSE);
3722     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3723     aopOp((result=IC_RESULT(ic)),ic,TRUE);
3724
3725     resolveIfx(&rIfx,ifx);
3726
3727     /* if left is a literal & right is not then exchange them */
3728     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3729         AOP_NEEDSACC(left)) {
3730         operand *tmp = right ;
3731         right = left;
3732         left = tmp;
3733     }
3734
3735     /* if result = right then exchange them */
3736     if(pic14_sameRegs(AOP(result),AOP(right))){
3737         operand *tmp = right ;
3738         right = left;
3739         left = tmp;
3740     }
3741
3742     /* if right is bit then exchange them */
3743     if (AOP_TYPE(right) == AOP_CRY &&
3744         AOP_TYPE(left) != AOP_CRY){
3745         operand *tmp = right ;
3746         right = left;
3747         left = tmp;
3748     }
3749     if(AOP_TYPE(right) == AOP_LIT)
3750         lit = ulFromVal (AOP(right)->aopu.aop_lit);
3751
3752     size = AOP_SIZE(result);
3753
3754     DEBUGpic14_AopType(__LINE__,left,right,result);
3755
3756     // if(bit & yy)
3757     // result = bit & yy;
3758     if (AOP_TYPE(left) == AOP_CRY){
3759         // c = bit & literal;
3760         if(AOP_TYPE(right) == AOP_LIT){
3761             if(lit & 1) {
3762                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
3763                     // no change
3764                     goto release;
3765                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3766             } else {
3767                 // bit(result) = 0;
3768                 if(size && (AOP_TYPE(result) == AOP_CRY)){
3769                     pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
3770                     goto release;
3771                 }
3772                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
3773                     jumpIfTrue(ifx);
3774                     goto release;
3775                 }
3776                 pic14_emitcode("clr","c");
3777             }
3778         } else {
3779             if (AOP_TYPE(right) == AOP_CRY){
3780                 // c = bit & bit;
3781                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3782                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3783             } else {
3784                 // c = bit & val;
3785                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
3786                 // c = lsb
3787                 pic14_emitcode("rrc","a");
3788                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3789             }
3790         }
3791         // bit = c
3792         // val = c
3793         if(size)
3794             pic14_outBitC(result);
3795         // if(bit & ...)
3796         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
3797             genIfxJump(ifx, "c");
3798         goto release ;
3799     }
3800
3801     // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
3802     // bit = val & 0xZZ     - size = 1, ifx = FALSE -
3803     if((AOP_TYPE(right) == AOP_LIT) &&
3804         (AOP_TYPE(result) == AOP_CRY) &&
3805         (AOP_TYPE(left) != AOP_CRY)){
3806         int posbit = isLiteralBit(lit);
3807         /* left &  2^n */
3808         if(posbit){
3809             posbit--;
3810             //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
3811             // bit = left & 2^n
3812             if(size)
3813                 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
3814             // if(left &  2^n)
3815             else{
3816                 if(ifx){
3817                     int offset = 0;
3818                     while (posbit > 7) {
3819                         posbit -= 8;
3820                         offset++;
3821                     }
3822                     emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
3823                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
3824                     emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
3825
3826                     ifx->generated = 1;
3827                 }
3828                 goto release;
3829             }
3830         } else {
3831             symbol *tlbl = newiTempLabel(NULL);
3832             int sizel = AOP_SIZE(left);
3833             if(size)
3834                 pic14_emitcode("setb","c");
3835             while(sizel--){
3836                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
3837                     mov2w( AOP(left), offset);
3838                     // byte ==  2^n ?
3839                     if((posbit = isLiteralBit(bytelit)) != 0) {
3840                         emitpcode(rIfx.condition ? POC_BTFSC : POC_BTFSS, // XXX: or the other way round?
3841                             newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit - 1, 0));
3842                         pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
3843                     }
3844                     else{
3845                         emitpcode(POC_ANDLW, newpCodeOpLit(bytelit & 0x0ff));
3846                         if (rIfx.condition) emitSKPZ;
3847                         else emitSKPNZ;
3848
3849                         if(bytelit != 0x0FFL)
3850                         {
3851                             pic14_emitcode("anl","a,%s",
3852                             aopGet(AOP(right),offset,FALSE,TRUE));
3853                         }
3854                         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
3855                     }
3856
3857                     emitpcode(POC_GOTO, popGetLabel(rIfx.lbl->key));
3858                     ifx->generated = 1;
3859
3860                 }
3861                 offset++;
3862             }
3863             // bit = left & literal
3864             if(size){
3865                 pic14_emitcode("clr","c");
3866                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
3867             }
3868             // if(left & literal)
3869             else{
3870                 if(ifx)
3871                     jmpTrueOrFalse(ifx, tlbl);
3872                 goto release ;
3873             }
3874         }
3875         pic14_outBitC(result);
3876         goto release ;
3877     }
3878
3879     /* if left is same as result */
3880     if(pic14_sameRegs(AOP(result),AOP(left))){
3881         int know_W = -1;
3882         for(;size--; offset++,lit>>=8) {
3883             if(AOP_TYPE(right) == AOP_LIT){
3884                 switch(lit & 0xff) {
3885                 case 0x00:
3886                     /*  and'ing with 0 has clears the result */
3887                     emitpcode(POC_CLRF,popGet(AOP(result),offset));
3888                     break;
3889                 case 0xff:
3890                     /* and'ing with 0xff is a nop when the result and left are the same */
3891                     break;
3892
3893                 default:
3894                     {
3895                         int p = my_powof2( (~lit) & 0xff );
3896                         if(p>=0) {
3897                             /* only one bit is set in the literal, so use a bcf instruction */
3898                             emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
3899
3900                         } else {
3901                             if(know_W != (int)(lit&0xff))
3902                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
3903                             know_W = lit &0xff;
3904                             emitpcode(POC_ANDWF,popGet(AOP(left),offset));
3905                         }
3906                     }
3907                 }
3908             } else {
3909                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
3910                 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
3911             }
3912         }
3913
3914     } else {
3915         // left & result in different registers
3916         if(AOP_TYPE(result) == AOP_CRY){
3917             // result = bit
3918             // if(size), result in bit
3919             // if(!size && ifx), conditional oper: if(left & right)
3920             symbol *tlbl = newiTempLabel(NULL);
3921             int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
3922             if(size)
3923                 pic14_emitcode("setb","c");
3924             while(sizer--){
3925                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3926                 pic14_emitcode("anl","a,%s",
3927                     aopGet(AOP(left),offset,FALSE,FALSE));
3928                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
3929                 offset++;
3930             }
3931             if(size){
3932                 CLRC;
3933                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
3934                 pic14_outBitC(result);
3935             } else if(ifx)
3936                 jmpTrueOrFalse(ifx, tlbl);
3937         } else {
3938             for(;(size--);offset++) {
3939                 // normal case
3940                 // result = left & right
3941                 if(AOP_TYPE(right) == AOP_LIT){
3942                     int t = (lit >> (offset*8)) & 0x0FFL;
3943                     switch(t) {
3944                     case 0x00:
3945                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
3946                         break;
3947                     case 0xff:
3948                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
3949                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
3950                         break;
3951                     default:
3952                         emitpcode(POC_MOVLW, popGetLit(t));
3953                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
3954                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
3955                     }
3956                     continue;
3957                 }
3958
3959                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
3960                 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
3961                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
3962             }
3963         }
3964     }
3965
3966 release :
3967     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3968     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3969     freeAsmop(result,NULL,ic,TRUE);
3970 }
3971
3972 /*-----------------------------------------------------------------*/
3973 /* genOr  - code for or                                            */
3974 /*-----------------------------------------------------------------*/
3975 static void genOr (iCode *ic, iCode *ifx)
3976 {
3977     operand *left, *right, *result;
3978     int size, offset=0;
3979     unsigned long lit = 0L;
3980
3981     FENTRY;
3982     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3983
3984     aopOp((left = IC_LEFT(ic)),ic,FALSE);
3985     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3986     aopOp((result=IC_RESULT(ic)),ic,TRUE);
3987
3988     DEBUGpic14_AopType(__LINE__,left,right,result);
3989
3990     /* if left is a literal & right is not then exchange them */
3991     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3992         AOP_NEEDSACC(left)) {
3993         operand *tmp = right ;
3994         right = left;
3995         left = tmp;
3996     }
3997
3998     /* if result = right then exchange them */
3999     if(pic14_sameRegs(AOP(result),AOP(right))){
4000         operand *tmp = right ;
4001         right = left;
4002         left = tmp;
4003     }
4004
4005     /* if right is bit then exchange them */
4006     if (AOP_TYPE(right) == AOP_CRY &&
4007         AOP_TYPE(left) != AOP_CRY){
4008         operand *tmp = right ;
4009         right = left;
4010         left = tmp;
4011     }
4012
4013     DEBUGpic14_AopType(__LINE__,left,right,result);
4014
4015     if(AOP_TYPE(right) == AOP_LIT)
4016         lit = ulFromVal (AOP(right)->aopu.aop_lit);
4017
4018     size = AOP_SIZE(result);
4019
4020     // if(bit | yy)
4021     // xx = bit | yy;
4022     if (AOP_TYPE(left) == AOP_CRY){
4023         if(AOP_TYPE(right) == AOP_LIT){
4024             // c = bit & literal;
4025             if(lit){
4026                 // lit != 0 => result = 1
4027                 if(AOP_TYPE(result) == AOP_CRY){
4028                     if(size)
4029                         emitpcode(POC_BSF, popGet(AOP(result),0));
4030                     //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
4031                     //   AOP(result)->aopu.aop_dir,
4032                     //   AOP(result)->aopu.aop_dir);
4033                     else if(ifx)
4034                         continueIfTrue(ifx);
4035                     goto release;
4036                 }
4037             } else {
4038                 // lit == 0 => result = left
4039                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
4040                     goto release;
4041                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
4042             }
4043         } else {
4044             if (AOP_TYPE(right) == AOP_CRY){
4045                 if(pic14_sameRegs(AOP(result),AOP(left))){
4046                     // c = bit | bit;
4047                     emitpcode(POC_BCF,   popGet(AOP(result),0));
4048                     emitpcode(POC_BTFSC, popGet(AOP(right),0));
4049                     emitpcode(POC_BSF,   popGet(AOP(result),0));
4050
4051                     pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
4052                         AOP(result)->aopu.aop_dir,
4053                         AOP(result)->aopu.aop_dir);
4054                     pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
4055                         AOP(right)->aopu.aop_dir,
4056                         AOP(right)->aopu.aop_dir);
4057                     pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
4058                         AOP(result)->aopu.aop_dir,
4059                         AOP(result)->aopu.aop_dir);
4060                 } else {
4061                         emitpcode(POC_BCF,   popGet(AOP(result),0));
4062                         emitpcode(POC_BTFSS, popGet(AOP(right),0));
4063                         emitpcode(POC_BTFSC, popGet(AOP(left),0));
4064                         emitpcode(POC_BSF,   popGet(AOP(result),0));
4065                 }
4066             } else {
4067                 // c = bit | val;
4068                 symbol *tlbl = newiTempLabel(NULL);
4069                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4070
4071
4072                 emitpcode(POC_BCF,   popGet(AOP(result),0));
4073
4074                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4075                     pic14_emitcode(";XXX setb","c");
4076                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
4077                     AOP(left)->aopu.aop_dir,tlbl->key+100);
4078                 pic14_toBoolean(right);
4079                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4080                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4081                     jmpTrueOrFalse(ifx, tlbl);
4082                     goto release;
4083                 } else {
4084                     CLRC;
4085                     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4086                 }
4087             }
4088         }
4089         // bit = c
4090         // val = c
4091         if(size)
4092             pic14_outBitC(result);
4093         // if(bit | ...)
4094         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4095             genIfxJump(ifx, "c");
4096         goto release ;
4097     }
4098
4099     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
4100     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
4101     if((AOP_TYPE(right) == AOP_LIT) &&
4102       (AOP_TYPE(result) == AOP_CRY) &&
4103       (AOP_TYPE(left) != AOP_CRY)){
4104         if(lit){
4105             pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4106             // result = 1
4107             if(size)
4108                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
4109             else
4110                 continueIfTrue(ifx);
4111             goto release;
4112         } else {
4113             pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4114             // lit = 0, result = boolean(left)
4115             if(size)
4116                 pic14_emitcode(";XXX setb","c");
4117             pic14_toBoolean(right);
4118             if(size){
4119                 symbol *tlbl = newiTempLabel(NULL);
4120                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4121                 CLRC;
4122                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4123             } else {
4124                 genIfxJump (ifx,"a");
4125                 goto release;
4126             }
4127         }
4128         pic14_outBitC(result);
4129         goto release ;
4130     }
4131
4132     /* if left is same as result */
4133     if(pic14_sameRegs(AOP(result),AOP(left))){
4134         int know_W = -1;
4135         for(;size--; offset++,lit>>=8) {
4136             if(AOP_TYPE(right) == AOP_LIT){
4137                 if((lit & 0xff) == 0)
4138                     /*  or'ing with 0 has no effect */
4139                     continue;
4140                 else {
4141                     int p = my_powof2(lit & 0xff);
4142                     if(p>=0) {
4143                         /* only one bit is set in the literal, so use a bsf instruction */
4144                         emitpcode(POC_BSF,
4145                             newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
4146                     } else {
4147                         if(know_W != (int)(lit & 0xff))
4148                             emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
4149                         know_W = lit & 0xff;
4150                         emitpcode(POC_IORWF, popGet(AOP(left),offset));
4151                     }
4152
4153                 }
4154             } else {
4155                 emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
4156                 emitpcode(POC_IORWF,  popGet(AOP(left),offset));
4157             }
4158         }
4159     } else {
4160         // left & result in different registers
4161         if(AOP_TYPE(result) == AOP_CRY){
4162             // result = bit
4163             // if(size), result in bit
4164             // if(!size && ifx), conditional oper: if(left | right)
4165             symbol *tlbl = newiTempLabel(NULL);
4166             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4167             pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4168
4169
4170             if(size)
4171                 pic14_emitcode(";XXX setb","c");
4172             while(sizer--){
4173                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4174                 pic14_emitcode(";XXX orl","a,%s",
4175                     aopGet(AOP(left),offset,FALSE,FALSE));
4176                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4177                 offset++;
4178             }
4179             if(size){
4180                 CLRC;
4181                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4182                 pic14_outBitC(result);
4183             } else if(ifx)
4184                 jmpTrueOrFalse(ifx, tlbl);
4185         } else for(;(size--);offset++){
4186             // normal case
4187             // result = left | right
4188             if(AOP_TYPE(right) == AOP_LIT){
4189                 int t = (lit >> (offset*8)) & 0x0FFL;
4190                 switch(t) {
4191                 case 0x00:
4192                     emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
4193                     emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
4194
4195                     break;
4196                 default:
4197                     emitpcode(POC_MOVLW,  popGetLit(t));
4198                     emitpcode(POC_IORFW,  popGet(AOP(left),offset));
4199                     emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
4200                 }
4201                 continue;
4202             }
4203
4204             // faster than result <- left, anl result,right
4205             // and better if result is SFR
4206             emitpcode(POC_MOVFW,popGet(AOP(right),offset));
4207             emitpcode(POC_IORFW,popGet(AOP(left),offset));
4208             emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
4209         }
4210     }
4211
4212 release :
4213     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4214     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4215     freeAsmop(result,NULL,ic,TRUE);
4216 }
4217
4218 /*-----------------------------------------------------------------*/
4219 /* genXor - code for xclusive or                                   */
4220 /*-----------------------------------------------------------------*/
4221 static void genXor (iCode *ic, iCode *ifx)
4222 {
4223     operand *left, *right, *result;
4224     int size, offset=0;
4225     unsigned long lit = 0L;
4226
4227     FENTRY;
4228     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4229
4230     aopOp((left = IC_LEFT(ic)),ic,FALSE);
4231     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4232     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4233
4234     /* if left is a literal & right is not ||
4235     if left needs acc & right does not */
4236     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4237         (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4238         operand *tmp = right ;
4239         right = left;
4240         left = tmp;
4241     }
4242
4243     /* if result = right then exchange them */
4244     if(pic14_sameRegs(AOP(result),AOP(right))){
4245         operand *tmp = right ;
4246         right = left;
4247         left = tmp;
4248     }
4249
4250     /* if right is bit then exchange them */
4251     if (AOP_TYPE(right) == AOP_CRY &&
4252         AOP_TYPE(left) != AOP_CRY){
4253         operand *tmp = right ;
4254         right = left;
4255         left = tmp;
4256     }
4257     if(AOP_TYPE(right) == AOP_LIT)
4258         lit = ulFromVal (AOP(right)->aopu.aop_lit);
4259
4260     size = AOP_SIZE(result);
4261
4262     // if(bit ^ yy)
4263     // xx = bit ^ yy;
4264     if (AOP_TYPE(left) == AOP_CRY){
4265         if(AOP_TYPE(right) == AOP_LIT){
4266             // c = bit & literal;
4267             if(lit>>1){
4268                 // lit>>1  != 0 => result = 1
4269                 if(AOP_TYPE(result) == AOP_CRY){
4270                     if(size)
4271                     {emitpcode(POC_BSF,  popGet(AOP(result),offset));
4272                     pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
4273                     else if(ifx)
4274                         continueIfTrue(ifx);
4275                     goto release;
4276                 }
4277                 pic14_emitcode("setb","c");
4278             } else{
4279                 // lit == (0 or 1)
4280                 if(lit == 0){
4281                     // lit == 0, result = left
4282                     if(size && pic14_sameRegs(AOP(result),AOP(left)))
4283                         goto release;
4284                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4285                 } else{
4286                     // lit == 1, result = not(left)
4287                     if(size && pic14_sameRegs(AOP(result),AOP(left))){
4288                         emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
4289                         emitpcode(POC_XORWF,  popGet(AOP(result),offset));
4290                         pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4291                         goto release;
4292                     } else {
4293                         assert ( !"incomplete genXor" );
4294                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4295                         pic14_emitcode("cpl","c");
4296                     }
4297                 }
4298             }
4299
4300         } else {
4301             // right != literal
4302             symbol *tlbl = newiTempLabel(NULL);
4303             if (AOP_TYPE(right) == AOP_CRY){
4304                 // c = bit ^ bit;
4305                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4306             }
4307             else{
4308                 int sizer = AOP_SIZE(right);
4309                 // c = bit ^ val
4310                 // if val>>1 != 0, result = 1
4311                 pic14_emitcode("setb","c");
4312                 while(sizer){
4313                     MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4314                     if(sizer == 1)
4315                         // test the msb of the lsb
4316                         pic14_emitcode("anl","a,#0xfe");
4317                     pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
4318                     sizer--;
4319                 }
4320                 // val = (0,1)
4321                 pic14_emitcode("rrc","a");
4322             }
4323             pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4324             pic14_emitcode("cpl","c");
4325             pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
4326         }
4327         // bit = c
4328         // val = c
4329         if(size)
4330             pic14_outBitC(result);
4331         // if(bit | ...)
4332         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4333             genIfxJump(ifx, "c");
4334         goto release ;
4335     }
4336
4337     if(pic14_sameRegs(AOP(result),AOP(left))){
4338         /* if left is same as result */
4339         for(;size--; offset++) {
4340             if(AOP_TYPE(right) == AOP_LIT){
4341                 int t  = (lit >> (offset*8)) & 0x0FFL;
4342                 if(t == 0x00L)
4343                     continue;
4344                 else {
4345                         emitpcode(POC_MOVLW, popGetLit(t));
4346                         emitpcode(POC_XORWF,popGet(AOP(left),offset));
4347                 }
4348             } else {
4349                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
4350                 emitpcode(POC_XORWF,popGet(AOP(left),offset));
4351             }
4352         }
4353     } else {
4354         // left & result in different registers
4355         if(AOP_TYPE(result) == AOP_CRY){
4356             // result = bit
4357             // if(size), result in bit
4358             // if(!size && ifx), conditional oper: if(left ^ right)
4359             symbol *tlbl = newiTempLabel(NULL);
4360             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4361             if(size)
4362                 pic14_emitcode("setb","c");
4363             while(sizer--){
4364                 if((AOP_TYPE(right) == AOP_LIT) &&
4365                     (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4366                     MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4367                 } else {
4368                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4369                     pic14_emitcode("xrl","a,%s",
4370                         aopGet(AOP(left),offset,FALSE,FALSE));
4371                 }
4372                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
4373                 offset++;
4374             }
4375             if(size){
4376                 CLRC;
4377                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4378                 pic14_outBitC(result);
4379             } else if(ifx)
4380                 jmpTrueOrFalse(ifx, tlbl);
4381         } else for(;(size--);offset++){
4382             // normal case
4383             // result = left & right
4384             if(AOP_TYPE(right) == AOP_LIT){
4385                 int t = (lit >> (offset*8)) & 0x0FFL;
4386                 switch(t) {
4387                 case 0x00:
4388                     emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4389                     emitpcode(POC_MOVWF,popGet(AOP(result),offset));
4390                     break;
4391                 case 0xff:
4392                     emitpcode(POC_COMFW,popGet(AOP(left),offset));
4393                     emitpcode(POC_MOVWF,popGet(AOP(result),offset));
4394                     break;
4395                 default:
4396                     emitpcode(POC_MOVLW, popGetLit(t));
4397                     emitpcode(POC_XORFW,popGet(AOP(left),offset));
4398                     emitpcode(POC_MOVWF,popGet(AOP(result),offset));
4399                 }
4400                 continue;
4401             }
4402
4403             // faster than result <- left, anl result,right
4404             // and better if result is SFR
4405             emitpcode(POC_MOVFW,popGet(AOP(right),offset));
4406             emitpcode(POC_XORFW,popGet(AOP(left),offset));
4407             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
4408         }
4409     }
4410
4411 release :
4412     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4413     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4414     freeAsmop(result,NULL,ic,TRUE);
4415 }
4416
4417 /*-----------------------------------------------------------------*/
4418 /* genInline - write the inline code out                           */
4419 /*-----------------------------------------------------------------*/
4420 static void genInline (iCode *ic)
4421 {
4422   char *buffer, *bp, *bp1;
4423   bool inComment = FALSE;
4424
4425   FENTRY;
4426   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4427
4428   _G.inLine += (!options.asmpeep);
4429
4430   buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
4431
4432   while (*bp)
4433     {
4434       switch (*bp)
4435         {
4436         case ';':
4437           inComment = TRUE;
4438           ++bp;
4439           break;
4440
4441         case '\n':
4442           inComment = FALSE;
4443           *bp++ = '\0';
4444           if (*bp1)
4445             addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
4446           bp1 = bp;
4447           break;
4448
4449         default:
4450           /* Add \n for labels, not dirs such as c:\mydir */
4451           if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
4452             {
4453               ++bp;
4454               *bp = '\0';
4455               ++bp;
4456               /* print label, use this special format with NULL directive
4457                * to denote that the argument should not be indented with tab */
4458               addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
4459               bp1 = bp;
4460             }
4461           else
4462             ++bp;
4463           break;
4464         }
4465     }
4466   if ((bp1 != bp) && *bp1)
4467     addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
4468
4469   Safe_free (buffer);
4470
4471   _G.inLine -= (!options.asmpeep);
4472 }
4473
4474 /*-----------------------------------------------------------------*/
4475 /* genRRC - rotate right with carry                                */
4476 /*-----------------------------------------------------------------*/
4477 static void genRRC (iCode *ic)
4478 {
4479     operand *left , *result ;
4480     int size, offset = 0, same;
4481
4482     FENTRY;
4483     /* rotate right with carry */
4484     left = IC_LEFT(ic);
4485     result=IC_RESULT(ic);
4486     aopOp (left,ic,FALSE);
4487     aopOp (result,ic,FALSE);
4488
4489     DEBUGpic14_AopType(__LINE__,left,NULL,result);
4490
4491     same = pic14_sameRegs(AOP(result),AOP(left));
4492
4493     size = AOP_SIZE(result);
4494
4495     /* get the lsb and put it into the carry */
4496     emitpcode(POC_RRFW, popGet(AOP(left),size-1));
4497
4498     offset = 0 ;
4499
4500     while(size--) {
4501
4502         if(same) {
4503             emitpcode(POC_RRF, popGet(AOP(left),offset));
4504         } else {
4505             emitpcode(POC_RRFW, popGet(AOP(left),offset));
4506             emitpcode(POC_MOVWF, popGet(AOP(result),offset));
4507         }
4508
4509         offset++;
4510     }
4511
4512     freeAsmop(left,NULL,ic,TRUE);
4513     freeAsmop(result,NULL,ic,TRUE);
4514 }
4515
4516 /*-----------------------------------------------------------------*/
4517 /* genRLC - generate code for rotate left with carry               */
4518 /*-----------------------------------------------------------------*/
4519 static void genRLC (iCode *ic)
4520 {
4521     operand *left , *result ;
4522     int size, offset = 0;
4523     int same;
4524
4525     FENTRY;
4526     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4527     /* rotate right with carry */
4528     left = IC_LEFT(ic);
4529     result=IC_RESULT(ic);
4530     aopOp (left,ic,FALSE);
4531     aopOp (result,ic,FALSE);
4532
4533     DEBUGpic14_AopType(__LINE__,left,NULL,result);
4534
4535     same = pic14_sameRegs(AOP(result),AOP(left));
4536
4537     /* move it to the result */
4538     size = AOP_SIZE(result);
4539
4540     /* get the msb and put it into the carry */
4541     emitpcode(POC_RLFW, popGet(AOP(left),size-1));
4542
4543     offset = 0 ;
4544
4545     while(size--) {
4546
4547         if(same) {
4548             emitpcode(POC_RLF, popGet(AOP(left),offset));
4549         } else {
4550             emitpcode(POC_RLFW, popGet(AOP(left),offset));
4551             emitpcode(POC_MOVWF, popGet(AOP(result),offset));
4552         }
4553
4554         offset++;
4555     }
4556
4557
4558     freeAsmop(left,NULL,ic,TRUE);
4559     freeAsmop(result,NULL,ic,TRUE);
4560 }
4561
4562 /*-----------------------------------------------------------------*/
4563 /* genGetHbit - generates code get highest order bit               */
4564 /*-----------------------------------------------------------------*/
4565 static void genGetHbit (iCode *ic)
4566 {
4567     operand *left, *result;
4568     left = IC_LEFT(ic);
4569     result=IC_RESULT(ic);
4570     aopOp (left,ic,FALSE);
4571     aopOp (result,ic,FALSE);
4572
4573     FENTRY;
4574     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4575     /* get the highest order byte into a */
4576     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
4577     if(AOP_TYPE(result) == AOP_CRY){
4578         pic14_emitcode("rlc","a");
4579         pic14_outBitC(result);
4580     }
4581     else{
4582         pic14_emitcode("rl","a");
4583         pic14_emitcode("anl","a,#0x01");
4584         pic14_outAcc(result);
4585     }
4586
4587
4588     freeAsmop(left,NULL,ic,TRUE);
4589     freeAsmop(result,NULL,ic,TRUE);
4590 }
4591
4592 /*-----------------------------------------------------------------*/
4593 /* AccLsh - shift left accumulator by known count                  */
4594 /* MARK: pic14 always rotates through CARRY!                       */
4595 /*-----------------------------------------------------------------*/
4596 static void AccLsh (pCodeOp *pcop,int shCount)
4597 {
4598     FENTRY;
4599     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4600     shCount &= 0x0007;              // shCount : 0..7
4601     switch(shCount){
4602     case 0 :
4603         return;
4604         break;
4605     case 1 :
4606         emitCLRC;
4607         emitpcode(POC_RLF,pcop);
4608         return;
4609         break;
4610     case 2 :
4611         emitpcode(POC_RLF,pcop);
4612         emitpcode(POC_RLF,pcop);
4613         break;
4614     case 3 :
4615         emitpcode(POC_RLF,pcop);
4616         emitpcode(POC_RLF,pcop);
4617         emitpcode(POC_RLF,pcop);
4618         break;
4619     case 4 :
4620         emitpcode(POC_SWAPF,pcop);
4621         break;
4622     case 5 :
4623         emitpcode(POC_SWAPF,pcop);
4624         emitpcode(POC_RLF,pcop);
4625         break;
4626     case 6 :
4627         emitpcode(POC_SWAPF,pcop);
4628         emitpcode(POC_RLF,pcop);
4629         emitpcode(POC_RLF,pcop);
4630         break;
4631     case 7 :
4632         emitpcode(POC_RRFW,pcop);
4633         emitpcode(POC_RRF,pcop);
4634         break;
4635     }
4636     /* clear invalid bits */
4637     emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
4638     emitpcode(POC_ANDWF, pcop);
4639 }
4640
4641 /*-----------------------------------------------------------------*/
4642 /* AccRsh - shift right accumulator by known count                 */
4643 /* MARK: pic14 always rotates through CARRY!                       */
4644 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
4645 /*            1: mask out invalid bits (zero-extend)               */
4646 /*            2: sign-extend result (pretty slow)                  */
4647 /*-----------------------------------------------------------------*/
4648 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
4649 {
4650     FENTRY;
4651     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4652     shCount &= 0x0007;              // shCount : 0..7
4653     switch(shCount){
4654     case 0 :
4655         return;
4656         break;
4657     case 1 :
4658         /* load sign if needed */
4659         if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
4660         else if (mask_mode == 1) emitCLRC;
4661         emitpcode(POC_RRF,pcop);
4662         return;
4663         break;
4664     case 2 :
4665         /* load sign if needed */
4666         if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
4667         emitpcode(POC_RRF,pcop);
4668         /* load sign if needed */
4669         if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
4670         emitpcode(POC_RRF,pcop);
4671         if (mask_mode == 2) return;
4672         break;
4673     case 3 :
4674         /* load sign if needed */
4675         if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
4676         emitpcode(POC_RRF,pcop);
4677         /* load sign if needed */
4678         if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
4679         emitpcode(POC_RRF,pcop);
4680         /* load sign if needed */
4681         if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
4682         emitpcode(POC_RRF,pcop);
4683         if (mask_mode == 2) return;
4684         break;
4685     case 4 :
4686         emitpcode(POC_SWAPF,pcop);
4687         break;
4688     case 5 :
4689         emitpcode(POC_SWAPF,pcop);
4690         emitpcode(POC_RRF,pcop);
4691         break;
4692     case 6 :
4693         emitpcode(POC_SWAPF,pcop);
4694         emitpcode(POC_RRF,pcop);
4695         emitpcode(POC_RRF,pcop);
4696         break;
4697     case 7 :
4698         if (mask_mode == 2)
4699         {
4700             /* load sign */
4701             emitpcode(POC_RLFW,pcop);
4702             emitpcode(POC_CLRF,pcop);
4703             emitSKPNC;
4704             emitpcode(POC_COMF,pcop);
4705             return;
4706         } else {
4707             emitpcode(POC_RLFW,pcop);
4708             emitpcode(POC_RLF,pcop);
4709         }
4710         break;
4711     }
4712
4713     if (mask_mode == 0)
4714     {
4715         /* leave invalid bits undefined */
4716         return;
4717     }
4718
4719     /* clear invalid bits -- zero-extend */
4720     emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
4721     emitpcode(POC_ANDWF, pcop);
4722
4723     if (mask_mode == 2) {
4724       /* sign-extend */
4725       emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
4726       emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
4727       emitpcode(POC_IORWF, pcop);
4728     }
4729 }
4730
4731 /*-----------------------------------------------------------------*/
4732 /* movLeft2Result - move byte from left to result                  */
4733 /*-----------------------------------------------------------------*/
4734 static void movLeft2Result (operand *left, int offl,
4735                             operand *result, int offr)
4736 {
4737     FENTRY;
4738     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4739     if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
4740         aopGet(AOP(left),offl,FALSE,FALSE);
4741
4742         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
4743         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
4744     }
4745 }
4746
4747 /*-----------------------------------------------------------------*/
4748 /* shiftLeft_Left2ResultLit - shift left by known count            */
4749 /*-----------------------------------------------------------------*/
4750
4751 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
4752 {
4753     int size, same, offr, i;
4754
4755     size = AOP_SIZE(left);
4756     if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
4757
4758     same = pic14_sameRegs (AOP(left), AOP(result));
4759
4760     offr = shCount / 8;
4761     shCount = shCount & 0x07;
4762
4763     size -= offr;
4764
4765     switch (shCount)
4766     {
4767     case 0: /* takes 0 or 2N cycles (for offr==0) */
4768         if (!same || offr) {
4769             for (i=size-1; i >= 0; i--)
4770                 movLeft2Result (left, i, result, offr + i);
4771         } // if
4772         break;
4773
4774     case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
4775         if (same && offr) {
4776             shiftLeft_Left2ResultLit (left, result, 8 * offr);
4777             shiftLeft_Left2ResultLit (result, result, shCount);
4778             return; /* prevent clearing result again */
4779         } else {
4780             emitCLRC;
4781             for (i=0; i < size; i++) {
4782                 if (same && !offr) {
4783                     emitpcode (POC_RLF, popGet (AOP(left), i));
4784                 } else {
4785                     emitpcode (POC_RLFW, popGet (AOP(left), i));
4786                     emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
4787                 } // if
4788             } // for
4789         } // if (offr)
4790         break;
4791
4792     case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
4793         /* works in-place/with offr as well */
4794         emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
4795         emitpcode (POC_ANDLW, popGetLit (0xF0));
4796         emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
4797
4798         for (i = size - 2; i >= 0; i--)
4799         {
4800             emitpcode (POC_SWAPFW, popGet (AOP(left), i));
4801             emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
4802             emitpcode (POC_ANDLW, popGetLit (0x0F));
4803             emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
4804             emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
4805         } // for i
4806         break;
4807
4808     case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
4809         /* works in-place/with offr as well */
4810         emitpcode (POC_RRFW, popGet (AOP(left), size-1));
4811         for (i = size-2; i >= 0; i--) {
4812             emitpcode (POC_RRFW, popGet (AOP(left), i));
4813             emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
4814         } // for i
4815         emitpcode (POC_CLRF, popGet (AOP(result), offr));
4816         emitpcode (POC_RRF, popGet (AOP(result), offr));
4817         break;
4818
4819     default:
4820         shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
4821         shiftLeft_Left2ResultLit (result, result, 1);
4822         return; /* prevent clearing result again */
4823         break;
4824     } // switch
4825
4826     while (0 < offr--)
4827     {
4828         emitpcode (POC_CLRF, popGet (AOP(result), offr));
4829     } // while
4830 }
4831
4832 /*-----------------------------------------------------------------*/
4833 /* shiftRight_Left2ResultLit - shift right by known count          */
4834 /*-----------------------------------------------------------------*/
4835
4836 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
4837 {
4838     int size, same, offr, i;
4839
4840     size = AOP_SIZE(left);
4841     if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
4842
4843     same = pic14_sameRegs (AOP(left), AOP(result));
4844
4845     offr = shCount / 8;
4846     shCount = shCount & 0x07;
4847
4848     size -= offr;
4849
4850     if (size)
4851     {
4852         switch (shCount)
4853         {
4854         case 0: /* takes 0 or 2N cycles (for offr==0) */
4855             if (!same || offr) {
4856                 for (i=0; i < size; i++)
4857                     movLeft2Result (left, i + offr, result, i);
4858             } // if
4859             break;
4860
4861         case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
4862             emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
4863             if (same && offr) {
4864                 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
4865                 shiftRight_Left2ResultLit (result, result, shCount, sign);
4866                 return; /* prevent sign-extending result again */
4867             } else {
4868                 emitCLRC;
4869                 if (sign) {
4870                     emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
4871                     emitSETC;
4872                 }
4873                 for (i = size-1; i >= 0; i--) {
4874                     if (same && !offr) {
4875                         emitpcode (POC_RRF, popGet (AOP(left), i));
4876                     } else {
4877                         emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
4878                         emitpcode (POC_MOVWF, popGet (AOP(result), i));
4879                     }
4880                 } // for i
4881             } // if (offr)
4882             break;
4883
4884         case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
4885             /* works in-place/with offr as well */
4886             emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
4887             emitpcode (POC_ANDLW, popGetLit (0x0F));
4888             emitpcode (POC_MOVWF, popGet(AOP(result), 0));
4889
4890             for (i = 1; i < size; i++)
4891             {
4892                 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
4893                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
4894                 emitpcode (POC_ANDLW, popGetLit (0xF0));
4895                 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
4896                 emitpcode (POC_XORWF, popGet (AOP(result), i));
4897             } // for i
4898
4899             if (sign)
4900             {
4901                 emitpcode (POC_MOVLW, popGetLit (0xF0));
4902                 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
4903                 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
4904             } // if
4905             break;
4906
4907         case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
4908             /* works in-place/with offr as well */
4909             emitpcode (POC_RLFW, popGet (AOP(left), offr));
4910             for (i = 0; i < size-1; i++) {
4911                 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
4912                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
4913             } // for i
4914             emitpcode (POC_CLRF, popGet (AOP(result), size-1));
4915             if (!sign) {
4916                 emitpcode (POC_RLF, popGet (AOP(result), size-1));
4917             } else {
4918                 emitSKPNC;
4919                 emitpcode (POC_DECF, popGet (AOP(result), size-1));
4920             }
4921             break;
4922
4923         default:
4924             shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
4925             shiftRight_Left2ResultLit (result, result, 1, sign);
4926             return; /* prevent sign extending result again */
4927             break;
4928         } // switch
4929     } // if
4930
4931     addSign (result, size, sign);
4932 }
4933
4934 /*-----------------------------------------------------------------*
4935 * genMultiAsm - repeat assembly instruction for size of register.
4936 * if endian == 1, then the high byte (i.e base address + size of
4937 * register) is used first else the low byte is used first;
4938 *-----------------------------------------------------------------*/
4939 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
4940 {
4941
4942     int offset = 0;
4943
4944     FENTRY;
4945     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4946
4947     if(!reg)
4948         return;
4949
4950     if(!endian) {
4951         endian = 1;
4952     } else {
4953         endian = -1;
4954         offset = size-1;
4955     }
4956
4957     while(size--) {
4958         emitpcode(poc,    popGet(AOP(reg),offset));
4959         offset += endian;
4960     }
4961
4962 }
4963
4964 /*-----------------------------------------------------------------*/
4965 /* loadSignToC - load the operand's sign bit into CARRY            */
4966 /*-----------------------------------------------------------------*/
4967
4968 static void loadSignToC (operand *op)
4969 {
4970     FENTRY;
4971     assert (op && AOP(op) && AOP_SIZE(op));
4972
4973     emitCLRC;
4974     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
4975     emitSETC;
4976 }
4977
4978 /*-----------------------------------------------------------------*/
4979 /* genRightShift - generate code for right shifting                */
4980 /*-----------------------------------------------------------------*/
4981 static void genGenericShift (iCode *ic, int shiftRight)
4982 {
4983     operand *right, *left, *result;
4984     sym_link *retype ;
4985     int size;
4986     symbol *tlbl, *tlbl1, *inverselbl;
4987
4988     FENTRY;
4989     /* if signed then we do it the hard way preserve the
4990     sign bit moving it inwards */
4991     retype = getSpec(operandType(IC_RESULT(ic)));
4992     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4993
4994     /* signed & unsigned types are treated the same : i.e. the
4995     signed is NOT propagated inwards : quoting from the
4996     ANSI - standard : "for E1 >> E2, is equivalent to division
4997     by 2**E2 if unsigned or if it has a non-negative value,
4998     otherwise the result is implementation defined ", MY definition
4999     is that the sign does not get propagated */
5000
5001     right = IC_RIGHT(ic);
5002     left  = IC_LEFT(ic);
5003     result = IC_RESULT(ic);
5004
5005     aopOp(right,ic,FALSE);
5006     aopOp(left,ic,FALSE);
5007     aopOp(result,ic,FALSE);
5008
5009     /* if the shift count is known then do it
5010     as efficiently as possible */
5011     if (AOP_TYPE(right) == AOP_LIT) {
5012         int lit = (int) ulFromVal (AOP(right)->aopu.aop_lit);
5013         if (lit < 0)
5014         {
5015             lit = -lit;
5016             shiftRight = !shiftRight;
5017         }
5018
5019         if (shiftRight)
5020             shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
5021         else
5022             shiftLeft_Left2ResultLit (left, result, lit);
5023         //genRightShiftLiteral (left,right,result,ic, 0);
5024         return ;
5025     }
5026
5027     /* shift count is unknown then we have to form
5028     a loop get the loop count in B : Note: we take
5029     only the lower order byte since shifting
5030     more that 32 bits make no sense anyway, ( the
5031     largest size of an object can be only 32 bits ) */
5032
5033     /* we must not overwrite the shift counter */
5034     assert (!pic14_sameRegs(AOP(right),AOP(result)));
5035
5036     /* now move the left to the result if they are not the
5037     same */
5038     if (!pic14_sameRegs(AOP(left),AOP(result)))
5039     {
5040         size = min(AOP_SIZE(result), AOP_SIZE(left));
5041         while (size--) {
5042             mov2w(AOP(left), size);
5043             movwf(AOP(result), size);
5044         }
5045         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
5046     }
5047
5048     tlbl = newiTempLabel(NULL);
5049     tlbl1= newiTempLabel(NULL);
5050     inverselbl = NULL;
5051     size = AOP_SIZE(result);
5052
5053     mov2w(AOP(right),0);
5054     if (!SPEC_USIGN(operandType(right)))
5055     {
5056         inverselbl = newiTempLabel(NULL);
5057         /* signed shift count -- invert shift direction for c<0 */
5058         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
5059         emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
5060     } // if
5061     emitpcode(POC_SUBLW, popGetLit(0)); /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
5062     /* check for `a = b >> c' with `-c == 0' */
5063     emitSKPNZ;
5064     emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
5065     emitpLabel(tlbl->key);
5066     /* propagate the sign bit inwards for SIGNED result */
5067     if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
5068     genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
5069     emitpcode(POC_ADDLW,  popGetLit(1));    /* clears CARRY (unless W==0 afterwards) */
5070     emitSKPC;
5071     emitpcode(POC_GOTO,popGetLabel(tlbl->key));
5072
5073     if (!SPEC_USIGN(operandType(right)))
5074     {
5075         symbol *inv_loop = newiTempLabel(NULL);
5076
5077         shiftRight = !shiftRight;   /* invert shift direction */
5078
5079         /* we came here from the code above -- we are done */
5080         emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
5081
5082         /* emit code for shifting N<0 steps, count is already in W */
5083         emitpLabel(inverselbl->key);
5084         if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
5085         emitpLabel(inv_loop->key);
5086         /* propagate the sign bit inwards for SIGNED result */
5087         if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
5088         genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
5089         emitpcode(POC_ADDLW, popGetLit(1));
5090         emitSKPC;
5091         emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
5092     } // if
5093
5094     emitpLabel(tlbl1->key);
5095
5096     freeAsmop(left,NULL,ic,TRUE);
5097     freeAsmop (right,NULL,ic,TRUE);
5098     freeAsmop(result,NULL,ic,TRUE);
5099 }
5100
5101 static void genRightShift (iCode *ic)
5102 {
5103     genGenericShift(ic, 1);
5104 }
5105
5106 static void genLeftShift (iCode *ic)
5107 {
5108     genGenericShift(ic, 0);
5109 }
5110
5111 /*-----------------------------------------------------------------*/
5112 /* SetIrp - Set IRP bit                                            */
5113 /*-----------------------------------------------------------------*/
5114 static void SetIrp(operand *result)
5115 {
5116     FENTRY;
5117     if (AOP_TYPE(result) == AOP_LIT) {
5118         unsigned lit = (unsigned) double2ul (operandLitValue(result));
5119         if (lit&0x100)
5120             emitSETIRP;
5121         else
5122             emitCLRIRP;
5123     } else {
5124         if ((AOP_TYPE(result) == AOP_PCODE)
5125             && (AOP(result)->aopu.pcop->type == PO_LITERAL))
5126         {
5127             int addrs = PCOL(AOP(result)->aopu.pcop)->lit;
5128             if (addrs & 0x100)
5129                 emitSETIRP;
5130             else
5131                 emitCLRIRP;
5132         } else {
5133             emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
5134             if(AOP_SIZE(result) > 1) {
5135                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
5136                 emitSETIRP;
5137             }
5138         }
5139     }
5140 }
5141
5142 static void
5143 setup_fsr (operand *ptr)
5144 {
5145   mov2w_op(ptr, 0);
5146   emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
5147
5148   /* also setup-up IRP */
5149   SetIrp (ptr);
5150 }
5151
5152 /*-----------------------------------------------------------------*/
5153 /* emitPtrByteGet - emits code to get a byte into WREG from an     */
5154 /*                  arbitrary pointer (__code, __data, generic)    */
5155 /*-----------------------------------------------------------------*/
5156 static void
5157 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
5158 {
5159     FENTRY;
5160     switch (p_type)
5161     {
5162     case POINTER:
5163     case FPOINTER:
5164       if (!alreadyAddressed) setup_fsr (src);
5165       emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
5166       break;
5167
5168     case CPOINTER:
5169       assert( AOP_SIZE(src) == 2 );
5170       mov2w_op(src, 0);
5171       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
5172       mov2w_op(src, 1);
5173       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
5174       emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE));   /* GPOINTER tag for __code space */
5175       call_libraryfunc ("__gptrget1");
5176       break;
5177
5178     case GPOINTER:
5179       assert( AOP_SIZE(src) == 3 );
5180       mov2w_op(src, 0);
5181       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
5182       mov2w_op(src, 1);
5183       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
5184       mov2w_op(src, 2);
5185       call_libraryfunc ("__gptrget1");
5186       break;
5187
5188     default:
5189       assert( !"unhandled pointer type" );
5190       break;
5191     }
5192 }
5193
5194 /*-----------------------------------------------------------------*/
5195 /* emitPtrByteSet - emits code to set a byte from src through a    */
5196 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR).       */
5197 /*-----------------------------------------------------------------*/
5198 static void
5199 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
5200 {
5201     FENTRY;
5202     switch (p_type)
5203     {
5204     case POINTER:
5205     case FPOINTER:
5206       if (!alreadyAddressed) setup_fsr (dst);
5207       emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
5208       break;
5209
5210     case CPOINTER:
5211       assert( !"trying to assign to __code pointer" );
5212       break;
5213
5214     case GPOINTER:
5215       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
5216       mov2w_op(dst, 0);
5217       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
5218       mov2w_op(dst, 1);
5219       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
5220       mov2w_op(dst, 2);
5221       call_libraryfunc ("__gptrput1");
5222       break;
5223
5224     default:
5225       assert( !"unhandled pointer type" );
5226       break;
5227     }
5228 }
5229
5230 /*-----------------------------------------------------------------*/
5231 /* genUnpackBits - generates code for unpacking bits               */
5232 /*-----------------------------------------------------------------*/
5233 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
5234 {
5235   int rsize;            /* result size */
5236   sym_link *etype;      /* bitfield type information */
5237   int blen;             /* bitfield length */
5238   int bstr;             /* bitfield starting bit within byte */
5239
5240   FENTRY;
5241   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5242   etype = getSpec(operandType(result));
5243   rsize = getSize (operandType (result));
5244   blen = SPEC_BLEN (etype);
5245   bstr = SPEC_BSTR (etype);
5246
5247   /* single bit field case */
5248   if (blen == 1) {
5249     if (ifx) { /* that is for an if statement */
5250       pCodeOp *pcop;
5251       resolvedIfx rIfx;
5252       resolveIfx(&rIfx,ifx);
5253       if (ptype == -1) /* direct */
5254     pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
5255       else
5256     pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
5257       emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
5258       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5259       ifx->generated=1;
5260     } else {
5261       int i;
5262       assert (!pic14_sameRegs (AOP(result), AOP(left)));
5263       for (i=0; i < AOP_SIZE(result); i++)
5264     emitpcode (POC_CLRF, popGet (AOP(result), i));
5265
5266       switch (ptype)
5267       {
5268       case -1:
5269         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
5270     /* adjust result below */
5271         break;
5272
5273       case POINTER:
5274       case FPOINTER:
5275       case GPOINTER:
5276       case CPOINTER:
5277         emitPtrByteGet (left, ptype, FALSE);
5278     emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
5279     emitSKPZ;
5280     /* adjust result below */
5281         break;
5282
5283       default:
5284         assert( !"unhandled pointer type" );
5285       } // switch
5286
5287       /* move sign-/zero extended bit to result */
5288       if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
5289     emitpcode (POC_INCF, popGet (AOP(result), 0));
5290       } else {
5291     emitpcode (POC_DECF, popGet (AOP(result), 0));
5292       }
5293       addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
5294     }
5295     return;
5296   }
5297   else if (blen <= 8 && ((blen + bstr) <= 8))
5298   {
5299     /* blen > 1 */
5300     int i;
5301
5302     for (i=0; i < AOP_SIZE(result); i++)
5303       emitpcode (POC_CLRF, popGet (AOP(result), i));
5304
5305     switch (ptype)
5306     {
5307     case -1:
5308       mov2w(AOP(left), 0);
5309       break;
5310
5311     case POINTER:
5312     case FPOINTER:
5313     case GPOINTER:
5314     case CPOINTER:
5315       emitPtrByteGet (left, ptype, FALSE);
5316       break;
5317
5318     default:
5319       assert( !"unhandled pointer type" );
5320     } // switch
5321
5322     if (blen < 8)
5323       emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
5324     movwf(AOP(result), 0);
5325     AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
5326
5327     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
5328     {
5329       /* signed bitfield */
5330       assert (bstr + blen > 0);
5331       emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
5332       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
5333       emitpcode(POC_IORWF, popGet(AOP(result),0));
5334     }
5335     addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
5336     return;
5337   }
5338
5339   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
5340 }
5341
5342 #if 1
5343 /*-----------------------------------------------------------------*/
5344 /* genDataPointerGet - generates code when ptr offset is known     */
5345 /*-----------------------------------------------------------------*/
5346 static void genDataPointerGet (operand *left,
5347     operand *result,
5348     iCode *ic)
5349 {
5350     int size , offset = 0;
5351
5352     FENTRY;
5353     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5354
5355
5356     /* optimization - most of the time, left and result are the same
5357     * address, but different types. for the pic code, we could omit
5358     * the following
5359     */
5360     aopOp(result,ic,TRUE);
5361
5362     if (pic14_sameRegs (AOP(left), AOP(result)))
5363         return;
5364
5365     DEBUGpic14_AopType(__LINE__,left,NULL,result);
5366
5367     //emitpcode(POC_MOVFW, popGet(AOP(left),0));
5368
5369     size = AOP_SIZE(result);
5370     if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
5371
5372     offset = 0;
5373     while (size--) {
5374         emitpcode(POC_MOVFW, popGet(AOP(left),offset));
5375         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5376         offset++;
5377     }
5378
5379     freeAsmop(left,NULL,ic,TRUE);
5380     freeAsmop(result,NULL,ic,TRUE);
5381 }
5382 #endif
5383
5384 /*-----------------------------------------------------------------*/
5385 /* genNearPointerGet - pic14_emitcode for near pointer fetch       */
5386 /*-----------------------------------------------------------------*/
5387 static void genNearPointerGet (operand *left,
5388                                operand *result,
5389                                iCode *ic)
5390 {
5391     asmop *aop = NULL;
5392     sym_link *ltype = operandType(left);
5393     sym_link *rtype = operandType(result);
5394     sym_link *retype= getSpec(rtype);      /* bitfield type information */
5395     int direct = 0;
5396
5397     FENTRY;
5398     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5399
5400
5401     aopOp(left,ic,FALSE);
5402
5403     /* if left is rematerialisable and
5404     result is not bit variable type and
5405     the left is pointer to data space i.e
5406     lower 128 bytes of space */
5407     if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
5408         !IS_BITVAR(retype)         &&
5409         PIC_IS_DATA_PTR(ltype)) {
5410         genDataPointerGet (left,result,ic);
5411         return ;
5412     }
5413
5414     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5415     aopOp (result,ic,FALSE);
5416
5417     /* Check if can access directly instead of via a pointer */
5418     if ((AOP_TYPE(left) == AOP_PCODE)
5419         && (AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
5420         && (AOP_SIZE(result) == 1))
5421     {
5422         direct = 1;
5423     }
5424
5425     if (IS_BITFIELD(getSpec(operandType(result))))
5426     {
5427         genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
5428         goto release;
5429     }
5430
5431     /* If the pointer value is not in a the FSR then need to put it in */
5432     /* Must set/reset IRP bit for use with FSR. */
5433     if (!direct)
5434       setup_fsr (left);
5435
5436 //  sym_link *etype;
5437     /* if bitfield then unpack the bits */
5438     {
5439         /* we have can just get the values */
5440         int size = AOP_SIZE(result);
5441         int offset = 0 ;
5442
5443         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5444
5445         while(size--) {
5446             if (direct)
5447                 emitpcode(POC_MOVWF,popGet(AOP(left),0));
5448             else
5449                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
5450             if (AOP_TYPE(result) == AOP_LIT) {
5451                 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
5452             } else {
5453                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5454             }
5455             if (size && !direct)
5456                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
5457             offset++;
5458         }
5459     }
5460
5461     /* now some housekeeping stuff */
5462     if (aop) {
5463         /* we had to allocate for this iCode */
5464         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5465         freeAsmop(NULL,aop,ic,TRUE);
5466     } else {
5467         /* we did not allocate which means left
5468         already in a pointer register, then
5469         if size > 0 && this could be used again
5470         we have to point it back to where it
5471         belongs */
5472         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5473         if (AOP_SIZE(result) > 1 &&
5474             !OP_SYMBOL(left)->remat &&
5475             ( OP_SYMBOL(left)->liveTo > ic->seq ||
5476             ic->depth )) {
5477             int size = AOP_SIZE(result) - 1;
5478             while (size--)
5479                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
5480         }
5481     }
5482
5483 release:
5484     /* done */
5485     freeAsmop(left,NULL,ic,TRUE);
5486     freeAsmop(result,NULL,ic,TRUE);
5487
5488 }
5489
5490 /*-----------------------------------------------------------------*/
5491 /* genGenPointerGet - gget value from generic pointer space        */
5492 /*-----------------------------------------------------------------*/
5493 static void genGenPointerGet (operand *left,
5494                               operand *result, iCode *ic)
5495 {
5496     FENTRY;
5497     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5498     aopOp(left,ic,FALSE);
5499     aopOp(result,ic,FALSE);
5500
5501
5502     DEBUGpic14_AopType(__LINE__,left,NULL,result);
5503
5504     if (IS_BITFIELD(getSpec(operandType(result))))
5505     {
5506       genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
5507       return;
5508     }
5509
5510     {
5511       /* emit call to __gptrget */
5512       char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
5513       int size = AOP_SIZE(result);
5514       int idx = 0;
5515
5516       assert (size > 0 && size <= 4);
5517
5518       /* pass arguments */
5519       assert (AOP_SIZE(left) == 3);
5520       mov2w(AOP(left), 0);
5521       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
5522       mov2w(AOP(left), 1);
5523       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
5524       mov2w(AOP(left), 2);
5525       call_libraryfunc (func[size]);
5526
5527       /* save result */
5528       movwf (AOP(result), --size);
5529       while (size--) {
5530         emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
5531         movwf (AOP(result), size);
5532       } // while
5533     }
5534
5535     freeAsmop(left,NULL,ic,TRUE);
5536     freeAsmop(result,NULL,ic,TRUE);
5537
5538 }
5539
5540 /*-----------------------------------------------------------------*/
5541 /* genConstPointerGet - get value from const generic pointer space */
5542 /*-----------------------------------------------------------------*/
5543 static void genConstPointerGet (operand *left,
5544                                 operand *result, iCode *ic)
5545 {
5546     //sym_link *retype = getSpec(operandType(result));
5547     #if 0
5548     symbol *albl, *blbl;//, *clbl;
5549     pCodeOp *pcop;
5550     #endif
5551     PIC_OPCODE poc;
5552     int i, size, lit;
5553
5554     FENTRY;
5555     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5556     aopOp(left,ic,FALSE);
5557     aopOp(result,ic,FALSE);
5558
5559     size = AOP_SIZE(result);
5560
5561     DEBUGpic14_AopType(__LINE__,left,NULL,result);
5562
5563     DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
5564
5565     lit = op_isLitLike (left);
5566     poc = lit ? POC_MOVLW : POC_MOVFW;
5567
5568     if (IS_BITFIELD(getSpec(operandType(result))))
5569     {
5570         genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
5571         goto release;
5572     }
5573
5574     {
5575         char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
5576         int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
5577         assert (size > 0 && size <= 4);
5578
5579         mov2w_op(left, 0);
5580         emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
5581         mov2w_op(left, 1);
5582         emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
5583         emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
5584         call_libraryfunc (func[size]);
5585
5586         movwf(AOP(result),size-1);
5587         for (i = 1; i < size; i++)
5588         {
5589             emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
5590             movwf(AOP(result),size - 1 - i);
5591         } // for
5592     }
5593
5594 release:
5595     freeAsmop(left,NULL,ic,TRUE);
5596     freeAsmop(result,NULL,ic,TRUE);
5597
5598 }
5599 /*-----------------------------------------------------------------*/
5600 /* genPointerGet - generate code for pointer get                   */
5601 /*-----------------------------------------------------------------*/
5602 static void genPointerGet (iCode *ic)
5603 {
5604     operand *left, *result ;
5605     sym_link *type, *etype;
5606     int p_type = -1;
5607
5608     FENTRY;
5609     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5610
5611     left = IC_LEFT(ic);
5612     result = IC_RESULT(ic) ;
5613
5614     /* depending on the type of pointer we need to
5615     move it to the correct pointer register */
5616     type = operandType(left);
5617     etype = getSpec(type);
5618
5619     if (IS_PTR_CONST(type))
5620         DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
5621
5622     /* if left is of type of pointer then it is simple */
5623     if (IS_PTR(type) && !IS_FUNC(type->next))
5624         p_type = DCL_TYPE(type);
5625     else {
5626         /* we have to go by the storage class */
5627         p_type = PTR_TYPE(SPEC_OCLS(etype));
5628
5629         DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
5630
5631         if (SPEC_OCLS(etype)->codesp ) {
5632             DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
5633             //p_type = CPOINTER ;
5634         }
5635         else
5636             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
5637                 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
5638             /*p_type = FPOINTER ;*/
5639             else
5640                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
5641                     DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
5642                 /*        p_type = PPOINTER; */
5643                 else
5644                     if (SPEC_OCLS(etype) == idata )
5645                         DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
5646                     /*      p_type = IPOINTER; */
5647                     else
5648                         DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
5649                     /*      p_type = POINTER ; */
5650     }
5651
5652     /* now that we have the pointer type we assign
5653     the pointer values */
5654     switch (p_type) {
5655
5656     case POINTER:
5657     case FPOINTER:
5658     //case IPOINTER:
5659         genNearPointerGet (left,result,ic);
5660         break;
5661 /*
5662     case PPOINTER:
5663         genPagedPointerGet(left,result,ic);
5664         break;
5665
5666     case FPOINTER:
5667         genFarPointerGet (left,result,ic);
5668         break;
5669 */
5670     case CPOINTER:
5671         genConstPointerGet (left,result,ic);
5672         break;
5673
5674     case GPOINTER:
5675         genGenPointerGet (left,result,ic);
5676         break;
5677     default:
5678         assert ( !"unhandled pointer type" );
5679         break;
5680     }
5681
5682 }
5683
5684 /*-----------------------------------------------------------------*/
5685 /* genPackBits - generates code for packed bit storage             */
5686 /*-----------------------------------------------------------------*/
5687 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
5688 {
5689   int blen;             /* bitfield length */
5690   int bstr;             /* bitfield starting bit within byte */
5691   int litval;           /* source literal value (if AOP_LIT) */
5692   unsigned char mask;   /* bitmask within current byte */
5693
5694   FENTRY;
5695   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5696
5697   blen = SPEC_BLEN (etype);
5698   bstr = SPEC_BSTR (etype);
5699
5700   /* If the bitfield length is less than a byte and does not cross byte boundaries */
5701   if ((blen <= 8) && ((bstr + blen) <= 8))
5702   {
5703     mask = ((unsigned char) (0xFF << (blen + bstr)) |
5704         (unsigned char) (0xFF >> (8 - bstr)));
5705
5706     if (AOP_TYPE (right) == AOP_LIT)
5707     {
5708       /* Case with a bitfield length <8 and literal source */
5709       int lit = (int) ulFromVal (AOP (right)->aopu.aop_lit);
5710       if (blen == 1) {
5711         pCodeOp *pcop;
5712
5713     switch (p_type)
5714     {
5715     case -1:
5716       if (AOP(result)->type == AOP_PCODE)
5717         pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
5718       else
5719         pcop = popGet(AOP(result),0);
5720       emitpcode(lit?POC_BSF:POC_BCF,pcop);
5721       break;
5722
5723     case POINTER:
5724     case FPOINTER:
5725       setup_fsr (result);
5726       emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
5727       break;
5728
5729     case CPOINTER:
5730       assert( !"trying to assign to bitfield via pointer to __code space" );
5731       break;
5732
5733     case GPOINTER:
5734       emitPtrByteGet(result, p_type, FALSE);
5735       if (lit) {
5736         emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
5737       } else {
5738         emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
5739       }
5740       emitPtrByteSet(result, p_type, TRUE);
5741       break;
5742
5743     default:
5744       assert( !"unhandled pointer type" );
5745       break;
5746     } // switch (p_type)
5747       } else {
5748         /* blen > 1 */
5749     litval = lit << bstr;
5750     litval &= (~mask) & 0x00ff;
5751
5752     switch (p_type)
5753     {
5754     case -1:
5755       mov2w (AOP(result), 0);
5756       if ((litval|mask) != 0x00ff)
5757         emitpcode(POC_ANDLW, popGetLit (mask));
5758       if (litval != 0x00)
5759         emitpcode(POC_IORLW, popGetLit (litval));
5760       movwf (AOP(result), 0);
5761       break;
5762
5763     case POINTER:
5764     case FPOINTER:
5765     case GPOINTER:
5766       emitPtrByteGet(result, p_type, FALSE);
5767       if ((litval|mask) != 0x00ff)
5768         emitpcode(POC_ANDLW, popGetLit (mask));
5769       if (litval != 0x00)
5770         emitpcode(POC_IORLW, popGetLit (litval));
5771       emitPtrByteSet(result, p_type, TRUE);
5772       break;
5773
5774     case CPOINTER:
5775       assert( !"trying to assign to bitfield via pointer to __code space" );
5776       break;
5777
5778     default:
5779       assert( !"unhandled pointer type" );
5780       break;
5781     } // switch
5782       } // if (blen > 1)
5783     }
5784     else
5785     {
5786       /* right is no literal */
5787       if (blen==1) {
5788         switch (p_type)
5789     {
5790     case -1:
5791       /* Note more efficient code, of pre clearing bit then only setting it if required,
5792        * can only be done if it is known that the result is not a SFR */
5793       emitpcode(POC_RRFW,popGet(AOP(right),0));
5794       emitSKPC;
5795       emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
5796       emitSKPNC;
5797       emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
5798       break;
5799
5800     case POINTER:
5801     case FPOINTER:
5802     case GPOINTER:
5803       emitPtrByteGet (result, p_type, FALSE);
5804       emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
5805       emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
5806       emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
5807       emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
5808       emitPtrByteSet (result, p_type, TRUE);
5809       break;
5810
5811     case CPOINTER:
5812       assert( !"trying to assign to bitfield via pointer to __code space" );
5813       break;
5814
5815     default:
5816       assert( !"unhandled pointer type" );
5817       break;
5818     } // switch
5819     return;
5820       } else {
5821     /* Case with a bitfield 1 < length <= 8 and arbitrary source */
5822     pCodeOp *temp = popGetTempReg ();
5823
5824     mov2w (AOP(right), 0);
5825     if (blen < 8) {
5826       emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
5827     }
5828     emitpcode(POC_MOVWF, temp);
5829     if (bstr) {
5830       AccLsh (temp, bstr);
5831     }
5832
5833     switch (p_type)
5834     {
5835     case -1:
5836       mov2w (AOP(result), 0);
5837       emitpcode(POC_ANDLW, popGetLit (mask));
5838       emitpcode(POC_IORFW, temp);
5839       movwf (AOP(result), 0);
5840       break;
5841
5842     case POINTER:
5843     case FPOINTER:
5844     case GPOINTER:
5845       emitPtrByteGet (result, p_type, FALSE);
5846       emitpcode(POC_ANDLW, popGetLit (mask));
5847       emitpcode(POC_IORFW, temp);
5848       emitPtrByteSet (result, p_type, TRUE);
5849       break;
5850
5851     case CPOINTER:
5852       assert( !"trying to assign to bitfield via pointer to __code space" );
5853       break;
5854
5855     default:
5856       assert( !"unhandled pointer type" );
5857       break;
5858     } // switch
5859
5860     popReleaseTempReg (temp);
5861       } // if (blen > 1)
5862     } // if (AOP(right)->type != AOP_LIT)
5863     return;
5864   } // if (blen <= 8 && ((blen + bstr) <= 8))
5865
5866   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
5867 }
5868
5869 /*-----------------------------------------------------------------*/
5870 /* genDataPointerSet - remat pointer to data space                 */
5871 /*-----------------------------------------------------------------*/
5872 static void genDataPointerSet(operand *right,
5873     operand *result,
5874     iCode *ic)
5875 {
5876     int size, offset = 0 ;
5877     int ressize;
5878
5879     FENTRY;
5880     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5881     aopOp(right,ic,FALSE);
5882     aopOp(result,ic,FALSE);
5883
5884     assert (IS_SYMOP(result));
5885     assert (IS_PTR(OP_SYM_TYPE(result)));
5886
5887     if (AOP_TYPE(right) == AOP_LIT)
5888       size = 4;
5889     else
5890       size = AOP_SIZE(right);
5891     ressize = getSize(OP_SYM_ETYPE(result));
5892     if (size > ressize) size = ressize;
5893     //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
5894
5895     //assert( !"what's going on here?" );
5896
5897     /*
5898     if ( AOP_TYPE(result) == AOP_PCODE) {
5899     fprintf(stderr,"genDataPointerSet   %s, %d\n",
5900     AOP(result)->aopu.pcop->name,
5901     PCOI(AOP(result)->aopu.pcop)->offset);
5902     }
5903     */
5904
5905     // tsd, was l+1 - the underline `_' prefix was being stripped
5906     while (size--) {
5907         emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
5908
5909         if (AOP_TYPE(right) == AOP_LIT) {
5910             unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
5911             //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
5912             if(lit&0xff) {
5913                 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
5914                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
5915             } else {
5916                 emitpcode(POC_CLRF, popGet(AOP(result), offset));
5917             }
5918         } else {
5919             //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
5920             emitpcode(POC_MOVFW, popGet(AOP(right), offset));
5921             emitpcode(POC_MOVWF, popGet(AOP(result), offset));
5922         }
5923
5924         offset++;
5925     }
5926
5927     freeAsmop(right,NULL,ic,TRUE);
5928     freeAsmop(result,NULL,ic,TRUE);
5929 }
5930
5931 /*-----------------------------------------------------------------*/
5932 /* genNearPointerSet - pic14_emitcode for near pointer put         */
5933 /*-----------------------------------------------------------------*/
5934 static void genNearPointerSet (operand *right,
5935                                operand *result,
5936                                iCode *ic)
5937 {
5938     asmop *aop = NULL;
5939     sym_link *ptype = operandType(result);
5940     sym_link *retype = getSpec(operandType(right));
5941     sym_link *letype = getSpec(ptype);
5942     int direct = 0;
5943
5944
5945     FENTRY;
5946     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5947     aopOp(result,ic,FALSE);
5948
5949 #if 1
5950     /* if the result is rematerializable &
5951     in data space & not a bit variable */
5952     //if (AOP_TYPE(result) == AOP_IMMD &&
5953     if (AOP_TYPE(result) == AOP_PCODE &&
5954         PIC_IS_DATA_PTR(ptype) &&
5955         !IS_BITVAR (retype) &&
5956         !IS_BITVAR (letype)) {
5957         genDataPointerSet (right,result,ic);
5958         freeAsmop(result,NULL,ic,TRUE);
5959         return;
5960     }
5961 #endif
5962
5963     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5964     aopOp(right,ic,FALSE);
5965     DEBUGpic14_AopType(__LINE__,NULL,right,result);
5966
5967     /* Check if can access directly instead of via a pointer */
5968     if ((AOP_TYPE(result) == AOP_PCODE)
5969         && (AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
5970         && (AOP_SIZE(right) == 1))
5971     {
5972         direct = 1;
5973     }
5974
5975     if (IS_BITFIELD (letype))
5976     {
5977       genPackBits (letype, result, right, direct?-1:POINTER);
5978       return;
5979     }
5980
5981     /* If the pointer value is not in a the FSR then need to put it in */
5982     /* Must set/reset IRP bit for use with FSR. */
5983     /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
5984     if (!direct)
5985         setup_fsr (result);
5986
5987     {
5988         /* we have can just get the values */
5989         int size = AOP_SIZE(right);
5990         int offset = 0 ;
5991
5992         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5993         while (size--) {
5994             char *l = aopGet(AOP(right),offset,FALSE,TRUE);
5995             if (*l == '@' ) {
5996                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
5997             } else {
5998                 if (AOP_TYPE(right) == AOP_LIT) {
5999                     emitpcode(POC_MOVLW,popGet(AOP(right),offset));
6000                 } else {
6001                     emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6002                 }
6003                 if (direct)
6004                     emitpcode(POC_MOVWF,popGet(AOP(result),0));
6005                 else
6006                     emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
6007             }
6008             if (size && !direct)
6009                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
6010             offset++;
6011         }
6012     }
6013
6014     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6015     /* now some housekeeping stuff */
6016     if (aop) {
6017         /* we had to allocate for this iCode */
6018         freeAsmop(NULL,aop,ic,TRUE);
6019     } else {
6020         /* we did not allocate which means left
6021         already in a pointer register, then
6022         if size > 0 && this could be used again
6023         we have to point it back to where it
6024         belongs */
6025         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6026         if (AOP_SIZE(right) > 1 &&
6027             !OP_SYMBOL(result)->remat &&
6028             ( OP_SYMBOL(result)->liveTo > ic->seq ||
6029             ic->depth )) {
6030             int size = AOP_SIZE(right) - 1;
6031             while (size--)
6032                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
6033         }
6034     }
6035
6036     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6037     /* done */
6038
6039     freeAsmop(right,NULL,ic,TRUE);
6040     freeAsmop(result,NULL,ic,TRUE);
6041 }
6042
6043 /*-----------------------------------------------------------------*/
6044 /* genGenPointerSet - set value from generic pointer space         */
6045 /*-----------------------------------------------------------------*/
6046 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
6047 {
6048     sym_link *retype = getSpec(operandType(result));
6049
6050     FENTRY;
6051     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6052     aopOp(right,ic,FALSE);
6053     aopOp(result,ic,FALSE);
6054
6055
6056     DEBUGpic14_AopType(__LINE__,right,NULL,result);
6057
6058     if (IS_BITFIELD(retype))
6059     {
6060       genPackBits (retype, result, right, GPOINTER);
6061       return;
6062     }
6063
6064     {
6065       /* emit call to __gptrput */
6066       char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
6067       int size = AOP_SIZE(right);
6068       int idx = 0;
6069
6070       /* The following assertion fails for
6071        *   struct foo { char a; char b; } bar;
6072        *   void demo(struct foo *dst, char c) { dst->b = c; }
6073        * as size will be 1 (sizeof(c)), whereas dst->b will be accessed
6074        * using (((char *)dst)+1), whose OP_SYM_ETYPE still is struct foo
6075        * of size 2.
6076        * The frontend seems to guarantee that IC_LEFT has the correct size,
6077        * it works fine both for larger and smaller types of `char c'.
6078        * */
6079       //assert (size == getSize(OP_SYM_ETYPE(result)));
6080       assert (size > 0 && size <= 4);
6081
6082       /* pass arguments */
6083       /* - value (MSB in Gstack_base_addr-2, growing downwards) */
6084       {
6085         int off = size;
6086         idx = 2;
6087         while (off--)
6088         {
6089           mov2w_op (right, off);
6090           emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
6091         }
6092         idx = 0;
6093       }
6094       /* - address */
6095       assert (AOP_SIZE(result) == 3);
6096       mov2w(AOP(result), 0);
6097       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
6098       mov2w(AOP(result), 1);
6099       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
6100       mov2w(AOP(result), 2);
6101       call_libraryfunc (func[size]);
6102     }
6103
6104     freeAsmop(right,NULL,ic,TRUE);
6105     freeAsmop(result,NULL,ic,TRUE);
6106 }
6107
6108 /*-----------------------------------------------------------------*/
6109 /* genPointerSet - stores the value into a pointer location        */
6110 /*-----------------------------------------------------------------*/
6111 static void genPointerSet (iCode *ic)
6112 {
6113     operand *right, *result ;
6114     sym_link *type, *etype;
6115     int p_type;
6116
6117     FENTRY;
6118     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6119
6120     right = IC_RIGHT(ic);
6121     result = IC_RESULT(ic) ;
6122
6123     /* depending on the type of pointer we need to
6124     move it to the correct pointer register */
6125     type = operandType(result);
6126     etype = getSpec(type);
6127     /* if left is of type of pointer then it is simple */
6128     if (IS_PTR(type) && !IS_FUNC(type->next)) {
6129         p_type = DCL_TYPE(type);
6130     }
6131     else {
6132         /* we have to go by the storage class */
6133         p_type = PTR_TYPE(SPEC_OCLS(etype));
6134
6135         /*  if (SPEC_OCLS(etype)->codesp ) { */
6136         /*      p_type = CPOINTER ;  */
6137         /*  } */
6138         /*  else */
6139         /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6140         /*    p_type = FPOINTER ; */
6141         /*      else */
6142         /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6143         /*        p_type = PPOINTER ; */
6144         /*    else */
6145         /*        if (SPEC_OCLS(etype) == idata ) */
6146         /*      p_type = IPOINTER ; */
6147         /*        else */
6148         /*      p_type = POINTER ; */
6149     }
6150
6151     /* now that we have the pointer type we assign
6152     the pointer values */
6153     switch (p_type) {
6154
6155     case POINTER:
6156     case FPOINTER:
6157     //case IPOINTER:
6158         genNearPointerSet (right,result,ic);
6159         break;
6160 /*
6161     case PPOINTER:
6162         genPagedPointerSet (right,result,ic);
6163         break;
6164
6165     case FPOINTER:
6166         genFarPointerSet (right,result,ic);
6167         break;
6168 */
6169     case GPOINTER:
6170         genGenPointerSet (right,result,ic);
6171         break;
6172
6173     default:
6174         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6175             "genPointerSet: illegal pointer type");
6176     }
6177 }
6178
6179 /*-----------------------------------------------------------------*/
6180 /* genIfx - generate code for Ifx statement                        */
6181 /*-----------------------------------------------------------------*/
6182 static void genIfx (iCode *ic, iCode *popIc)
6183 {
6184     operand *cond = IC_COND(ic);
6185     int isbit =0;
6186
6187     FENTRY;
6188     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6189
6190     aopOp(cond,ic,FALSE);
6191
6192     /* get the value into acc */
6193     if (AOP_TYPE(cond) != AOP_CRY)
6194         pic14_toBoolean(cond);
6195     else
6196         isbit = 1;
6197
6198     /* if there was something to be popped then do it */
6199     if (popIc)
6200         genIpop(popIc);
6201
6202     if (isbit)
6203     {
6204         /* This assumes that CARRY is set iff cond is true */
6205         if (IC_TRUE(ic))
6206         {
6207             assert (!IC_FALSE(ic));
6208             emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
6209             //emitSKPNC;
6210             emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
6211         } else {
6212             assert (IC_FALSE(ic));
6213             emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
6214             //emitSKPC;
6215             emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
6216         }
6217         if (0)
6218         {
6219             static int hasWarned = 0;
6220             if (!hasWarned)
6221             {
6222                 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
6223                 hasWarned = 1;
6224             }
6225         }
6226     }
6227     else
6228     {
6229         /* now Z is set iff !cond */
6230         if (IC_TRUE(ic))
6231         {
6232             assert (!IC_FALSE(ic));
6233             emitSKPZ;
6234             emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
6235         } else {
6236             emitSKPNZ;
6237             emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
6238         }
6239     }
6240
6241     ic->generated = 1;
6242
6243     /* the result is now in the accumulator */
6244     freeAsmop(cond,NULL,ic,TRUE);
6245 }
6246
6247 /*-----------------------------------------------------------------*/
6248 /* genAddrOf - generates code for address of                       */
6249 /*-----------------------------------------------------------------*/
6250 static void genAddrOf (iCode *ic)
6251 {
6252     operand *right, *result, *left;
6253     int size, offset ;
6254
6255     FENTRY;
6256     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6257
6258
6259     //aopOp(IC_RESULT(ic),ic,FALSE);
6260
6261     aopOp((left=IC_LEFT(ic)),ic,FALSE);
6262     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6263     aopOp((result=IC_RESULT(ic)),ic,TRUE);
6264
6265     DEBUGpic14_AopType(__LINE__,left,right,result);
6266     assert (IS_SYMOP (left));
6267
6268     /* sanity check: generic pointers to code space are not yet supported,
6269      * pionters to codespace must not be assigned addresses of __data values. */
6270  #if 0
6271     fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
6272     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)));
6273     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)));
6274     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)));
6275     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)));
6276 #endif
6277
6278     if (IS_SYMOP(result) && IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
6279       fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
6280         IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
6281         OP_SYMBOL(left)->name);
6282     } else if (IS_SYMOP(result) && !IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
6283       fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
6284         IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
6285         OP_SYMBOL(left)->name);
6286     }
6287
6288     size = AOP_SIZE(IC_RESULT(ic));
6289     if (IS_SYMOP(result) && IS_GENPTR(OP_SYM_TYPE(result))) {
6290         /* strip tag */
6291         if (size > GPTRSIZE-1) size = GPTRSIZE-1;
6292     }
6293     offset = 0;
6294
6295     while (size--) {
6296         /* fixing bug #863624, reported from (errolv) */
6297         emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
6298         emitpcode(POC_MOVWF, popGet(AOP(result), offset));
6299
6300 #if 0
6301         emitpcode(POC_MOVLW, popGet(AOP(left),offset));
6302         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6303 #endif
6304         offset++;
6305     }
6306
6307     if (IS_SYMOP(result) && IS_GENPTR(OP_SYM_TYPE(result)))
6308     {
6309         /* provide correct tag */
6310         int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
6311         emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
6312         movwf (AOP(result), 2);
6313     }
6314
6315     freeAsmop(left,NULL,ic,FALSE);
6316     freeAsmop(result,NULL,ic,TRUE);
6317
6318 }
6319
6320 /*-----------------------------------------------------------------*/
6321 /* genAssign - generate code for assignment                        */
6322 /*-----------------------------------------------------------------*/
6323 static void genAssign (iCode *ic)
6324 {
6325     operand *result, *right;
6326     int size, offset,know_W;
6327     unsigned long lit = 0L;
6328
6329     result = IC_RESULT(ic);
6330     right  = IC_RIGHT(ic) ;
6331
6332     FENTRY;
6333     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6334
6335     /* if they are the same */
6336     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
6337         return ;
6338
6339     aopOp(right,ic,FALSE);
6340     aopOp(result,ic,TRUE);
6341
6342     DEBUGpic14_AopType(__LINE__,NULL,right,result);
6343
6344     /* if they are the same registers */
6345     if (pic14_sameRegs(AOP(right),AOP(result)))
6346         goto release;
6347
6348     /* special case: assign from __code */
6349     if (!IS_ITEMP(right)                /* --> iTemps never reside in __code */
6350         && IS_SYMOP (right)         /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
6351         && !IS_FUNC(OP_SYM_TYPE(right))     /* --> we would want its address instead of the first instruction */
6352         && !IS_CODEPTR(OP_SYM_TYPE(right))  /* --> get symbols address instread */
6353         && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
6354     {
6355       emitpComment ("genAssign from CODESPACE");
6356       genConstPointerGet (right, result, ic);
6357       goto release;
6358     }
6359
6360     /* just for symmetry reasons... */
6361     if (!IS_ITEMP(result)
6362         && IS_SYMOP (result)
6363         && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
6364     {
6365       assert ( !"cannot write to CODESPACE" );
6366     }
6367
6368     /* if the result is a bit */
6369     if (AOP_TYPE(result) == AOP_CRY) {
6370
6371     /* if the right size is a literal then
6372         we know what the value is */
6373         if (AOP_TYPE(right) == AOP_LIT) {
6374
6375             emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
6376                 popGet(AOP(result),0));
6377
6378             if (((int) operandLitValue(right)))
6379                 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
6380                 AOP(result)->aopu.aop_dir,
6381                 AOP(result)->aopu.aop_dir);
6382             else
6383                 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
6384                 AOP(result)->aopu.aop_dir,
6385                 AOP(result)->aopu.aop_dir);
6386             goto release;
6387         }
6388
6389         /* the right is also a bit variable */
6390         if (AOP_TYPE(right) == AOP_CRY) {
6391             emitpcode(POC_BCF,    popGet(AOP(result),0));
6392             emitpcode(POC_BTFSC,  popGet(AOP(right),0));
6393             emitpcode(POC_BSF,    popGet(AOP(result),0));
6394
6395             pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
6396                 AOP(result)->aopu.aop_dir,
6397                 AOP(result)->aopu.aop_dir);
6398             pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
6399                 AOP(right)->aopu.aop_dir,
6400                 AOP(right)->aopu.aop_dir);
6401             pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
6402                 AOP(result)->aopu.aop_dir,
6403                 AOP(result)->aopu.aop_dir);
6404             goto release ;
6405         }
6406
6407         /* we need to or */
6408         emitpcode(POC_BCF,    popGet(AOP(result),0));
6409         pic14_toBoolean(right);
6410         emitSKPZ;
6411         emitpcode(POC_BSF,    popGet(AOP(result),0));
6412         //aopPut(AOP(result),"a",0);
6413         goto release ;
6414     }
6415
6416     /* bit variables done */
6417     /* general case */
6418     size = AOP_SIZE(result);
6419     offset = 0 ;
6420     if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
6421         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6422         if(aopIdx(AOP(result),0) == 4) {
6423             DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6424             emitpcode(POC_MOVFW, popGet(AOP(right),offset));
6425             emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6426             goto release;
6427         } else
6428             DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
6429     }
6430
6431     know_W=-1;
6432     while (size--) {
6433
6434         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6435         if(AOP_TYPE(right) == AOP_LIT) {
6436             lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
6437             if(lit&0xff) {
6438                 if(know_W != (int)(lit&0xff))
6439                     emitpcode(POC_MOVLW,popGetLit(lit&0xff));
6440                 know_W = lit&0xff;
6441                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6442             } else
6443                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
6444
6445         } else if (AOP_TYPE(right) == AOP_CRY) {
6446             emitpcode(POC_CLRF, popGet(AOP(result),offset));
6447             if(offset == 0) {
6448                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
6449                 emitpcode(POC_INCF, popGet(AOP(result),0));
6450             }
6451         } else {
6452             mov2w_op (right, offset);
6453             emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6454         }
6455
6456         offset++;
6457     }
6458
6459
6460 release:
6461     freeAsmop (right,NULL,ic,FALSE);
6462     freeAsmop (result,NULL,ic,TRUE);
6463 }
6464
6465 /*-----------------------------------------------------------------*/
6466 /* genJumpTab - genrates code for jump table                       */
6467 /*-----------------------------------------------------------------*/
6468 static void genJumpTab (iCode *ic)
6469 {
6470     symbol *jtab;
6471     char *l;
6472
6473     FENTRY;
6474     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6475
6476     aopOp(IC_JTCOND(ic),ic,FALSE);
6477     /* get the condition into accumulator */
6478     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
6479     MOVA(l);
6480     /* multiply by three */
6481     pic14_emitcode("add","a,acc");
6482     pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
6483
6484     jtab = newiTempLabel(NULL);
6485     pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
6486     pic14_emitcode("jmp","@a+dptr");
6487     pic14_emitcode("","%05d_DS_:",jtab->key+100);
6488
6489     emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
6490     emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
6491     emitpcode(POC_MOVLW, popGetLabel(jtab->key));
6492     emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
6493     emitSKPNC;
6494     emitpcode(POC_INCF, popCopyReg(&pc_pclath));
6495     emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
6496     emitpLabel(jtab->key);
6497
6498     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
6499
6500     /* now generate the jump labels */
6501     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
6502     jtab = setNextItem(IC_JTLABELS(ic))) {
6503         pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
6504         emitpcode(POC_GOTO,popGetLabel(jtab->key));
6505
6506     }
6507
6508 }
6509
6510 /*-----------------------------------------------------------------*/
6511 /* genCast - gen code for casting                                  */
6512 /*-----------------------------------------------------------------*/
6513 static void genCast (iCode *ic)
6514 {
6515     operand *result = IC_RESULT(ic);
6516     sym_link *restype = operandType(result);
6517     sym_link *rtype = operandType(IC_RIGHT(ic));
6518     operand *right = IC_RIGHT(ic);
6519     int size, offset ;
6520
6521     FENTRY;
6522     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
6523     /* if they are equivalent then do nothing */
6524     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
6525         return ;
6526
6527     aopOp(right,ic,FALSE) ;
6528     aopOp(result,ic,FALSE);
6529
6530     DEBUGpic14_AopType(__LINE__,NULL,right,result);
6531
6532     /* if the result is a bit */
6533     if (AOP_TYPE(result) == AOP_CRY) {
6534         assert(!"assigning to bit variables is not supported");
6535     }
6536
6537     if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
6538         int offset = 1;
6539         size = AOP_SIZE(result);
6540
6541         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
6542
6543         emitpcode(POC_CLRF,   popGet(AOP(result),0));
6544         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
6545         emitpcode(POC_INCF,   popGet(AOP(result),0));
6546
6547         while (size--)
6548             emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
6549
6550         goto release;
6551     }
6552
6553     if (IS_PTR(restype))
6554     {
6555       operand *result = IC_RESULT(ic);
6556       //operand *left = IC_LEFT(ic);
6557       operand *right = IC_RIGHT(ic);
6558       int tag = 0xff;
6559
6560       /* copy common part */
6561       int max, size = AOP_SIZE(result);
6562       if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
6563       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
6564
6565       /* warn if we discard generic opinter tag */
6566       if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
6567       {
6568         //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
6569       } // if
6570
6571       max = size;
6572       while (size--)
6573       {
6574         mov2w_op (right, size);
6575         movwf (AOP(result), size);
6576       } // while
6577
6578       /* upcast into generic pointer type? */
6579       if (IS_GENPTR(restype)
6580         && (size < AOP_SIZE(result))
6581         && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
6582       {
6583         //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
6584         if (IS_PTR(rtype))
6585         {
6586           switch (DCL_TYPE(rtype))
6587           {
6588           case POINTER: /* __data */
6589           case FPOINTER:    /* __data */
6590         assert (AOP_SIZE(right) == 2);
6591         tag = GPTRTAG_DATA;
6592         break;
6593
6594           case CPOINTER:    /* __code */
6595         assert (AOP_SIZE(right) == 2);
6596         tag = GPTRTAG_CODE;
6597         break;
6598
6599           case GPOINTER:    /* unknown destination, __data or __code */
6600         /* assume __data space (address of immediate) */
6601         assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
6602         if (AOP(right)->code)
6603           tag = GPTRTAG_CODE;
6604         else
6605           tag = GPTRTAG_DATA;
6606         break;
6607
6608           default:
6609         assert (!"unhandled pointer type");
6610           } // switch
6611         } else {
6612           /* convert other values into pointers to __data space */
6613           tag = GPTRTAG_DATA;
6614         }
6615
6616         assert (AOP_SIZE(result) == 3);
6617         if (tag == 0) {
6618           emitpcode(POC_CLRF, popGet(AOP(result), 2));
6619         } else {
6620           emitpcode(POC_MOVLW, popGetLit(tag));
6621           movwf(AOP(result), 2);
6622         }
6623       } else {
6624         addSign(result, max, 0);
6625       } // if
6626       goto release;
6627     }
6628
6629     /* if they are the same size : or less */
6630     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
6631
6632         /* if they are in the same place */
6633         if (pic14_sameRegs(AOP(right),AOP(result)))
6634             goto release;
6635
6636         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
6637         if (IS_PTR_CONST(rtype))
6638             DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
6639         if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
6640             DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
6641
6642         if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
6643             emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
6644             emitpcode(POC_MOVWF, popGet(AOP(result),0));
6645             emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
6646             emitpcode(POC_MOVWF, popGet(AOP(result),1));
6647             if(AOP_SIZE(result) <2)
6648                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
6649
6650         } else {
6651
6652             /* if they in different places then copy */
6653             size = AOP_SIZE(result);
6654             offset = 0 ;
6655             while (size--) {
6656                 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
6657                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6658
6659                 //aopPut(AOP(result),
6660                 // aopGet(AOP(right),offset,FALSE,FALSE),
6661                 // offset);
6662
6663                 offset++;
6664             }
6665         }
6666         goto release;
6667     }
6668
6669     /* so we now know that the size of destination is greater
6670     than the size of the source. */
6671
6672     /* we move to result for the size of source */
6673     size = AOP_SIZE(right);
6674     offset = 0 ;
6675     while (size--) {
6676         emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
6677         emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
6678         offset++;
6679     }
6680
6681     addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
6682
6683 release:
6684     freeAsmop(right,NULL,ic,TRUE);
6685     freeAsmop(result,NULL,ic,TRUE);
6686
6687 }
6688
6689 /*-----------------------------------------------------------------*/
6690 /* genDjnz - generate decrement & jump if not zero instrucion      */
6691 /*-----------------------------------------------------------------*/
6692 static int genDjnz (iCode *ic, iCode *ifx)
6693 {
6694     symbol *lbl, *lbl1;
6695     FENTRY;
6696     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6697
6698     if (!ifx)
6699         return 0;
6700
6701         /* if the if condition has a false label
6702     then we cannot save */
6703     if (IC_FALSE(ifx))
6704         return 0;
6705
6706         /* if the minus is not of the form
6707     a = a - 1 */
6708     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
6709         !IS_OP_LITERAL(IC_RIGHT(ic)))
6710         return 0;
6711
6712     if (operandLitValue(IC_RIGHT(ic)) != 1)
6713         return 0;
6714
6715         /* if the size of this greater than one then no
6716     saving */
6717     if (getSize(operandType(IC_RESULT(ic))) > 1)
6718         return 0;
6719
6720     /* otherwise we can save BIG */
6721     lbl = newiTempLabel(NULL);
6722     lbl1= newiTempLabel(NULL);
6723
6724     aopOp(IC_RESULT(ic),ic,FALSE);
6725
6726     emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
6727     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
6728
6729     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
6730     ifx->generated = 1;
6731     return 1;
6732 }
6733
6734 /*-----------------------------------------------------------------*/
6735 /* genReceive - generate code for a receive iCode                  */
6736 /*-----------------------------------------------------------------*/
6737 static void genReceive (iCode *ic)
6738 {
6739     FENTRY;
6740     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6741
6742     if (isOperandInFarSpace(IC_RESULT(ic)) &&
6743         ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
6744         IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
6745
6746         int size = getSize(operandType(IC_RESULT(ic)));
6747         int offset =  fReturnSizePic - size;
6748         while (size--) {
6749             pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
6750                 fReturn[fReturnSizePic - offset - 1] : "acc"));
6751             offset++;
6752         }
6753         aopOp(IC_RESULT(ic),ic,FALSE);
6754         size = AOP_SIZE(IC_RESULT(ic));
6755         offset = 0;
6756         while (size--) {
6757             pic14_emitcode ("pop","acc");
6758             aopPut (AOP(IC_RESULT(ic)),"a",offset++);
6759         }
6760
6761     } else {
6762         _G.accInUse++;
6763         aopOp(IC_RESULT(ic),ic,FALSE);
6764         _G.accInUse--;
6765         GpsuedoStkPtr = ic->parmBytes; // address used arg on stack
6766         assignResultValue(IC_RESULT(ic));
6767     }
6768
6769     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
6770 }
6771
6772 /*-----------------------------------------------------------------*/
6773 /* genDummyRead - generate code for dummy read of volatiles        */
6774 /*-----------------------------------------------------------------*/
6775 static void
6776 genDummyRead (iCode * ic)
6777 {
6778     FENTRY;
6779     pic14_emitcode ("; genDummyRead","");
6780     pic14_emitcode ("; not implemented","");
6781
6782     ic = ic;
6783 }
6784
6785 /*-----------------------------------------------------------------*/
6786 /* genpic14Code - generate code for pic14 based controllers        */
6787 /*-----------------------------------------------------------------*/
6788 /*
6789 * At this point, ralloc.c has gone through the iCode and attempted
6790 * to optimize in a way suitable for a PIC. Now we've got to generate
6791 * PIC instructions that correspond to the iCode.
6792 *
6793 * Once the instructions are generated, we'll pass through both the
6794 * peep hole optimizer and the pCode optimizer.
6795 *-----------------------------------------------------------------*/
6796
6797 void genpic14Code (iCode *lic)
6798 {
6799     iCode *ic;
6800     int cln = 0;
6801     const char *cline;
6802
6803     FENTRY;
6804     lineHead = lineCurr = NULL;
6805
6806     pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
6807     addpBlock(pb);
6808
6809     /* if debug information required */
6810     if (options.debug && debugFile && currFunc) {
6811         debugFile->writeFunction (currFunc, lic);
6812     }
6813
6814
6815     for (ic = lic ; ic ; ic = ic->next ) {
6816
6817         //DEBUGpic14_emitcode(";ic","");
6818         //fprintf (stderr, "in ic loop\n");
6819         //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
6820         //ic->lineno, printCLine(ic->filename, ic->lineno));
6821
6822         if (!options.noCcodeInAsm && (cln != ic->lineno)) {
6823           cln = ic->lineno;
6824           //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
6825           cline = printCLine (ic->filename, ic->lineno);
6826           if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
6827           addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
6828           //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
6829         }
6830
6831         if (options.iCodeInAsm) {
6832           const char *iLine = printILine(ic);
6833           emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
6834                   dbuf_free(iLine);
6835         }
6836         /* if the result is marked as
6837         spilt and rematerializable or code for
6838         this has already been generated then
6839         do nothing */
6840         if (resultRemat(ic) || ic->generated )
6841             continue ;
6842
6843         /* depending on the operation */
6844         switch (ic->op) {
6845         case '!' :
6846             genNot(ic);
6847             break;
6848
6849         case '~' :
6850             genCpl(ic);
6851             break;
6852
6853         case UNARYMINUS:
6854             genUminus (ic);
6855             break;
6856
6857         case IPUSH:
6858             genIpush (ic);
6859             break;
6860
6861         case IPOP:
6862             /* IPOP happens only when trying to restore a
6863             spilt live range, if there is an ifx statement
6864             following this pop then the if statement might
6865             be using some of the registers being popped which
6866             would destory the contents of the register so
6867             we need to check for this condition and handle it */
6868             if (ic->next            &&
6869                 ic->next->op == IFX &&
6870                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
6871                 genIfx (ic->next,ic);
6872             else
6873                 genIpop (ic);
6874             break;
6875
6876         case CALL:
6877             genCall (ic);
6878             break;
6879
6880         case PCALL:
6881             genPcall (ic);
6882             break;
6883
6884         case FUNCTION:
6885             genFunction (ic);
6886             break;
6887
6888         case ENDFUNCTION:
6889             genEndFunction (ic);
6890             break;
6891
6892         case RETURN:
6893             genRet (ic);
6894             break;
6895
6896         case LABEL:
6897             genLabel (ic);
6898             break;
6899
6900         case GOTO:
6901             genGoto (ic);
6902             break;
6903
6904         case '+' :
6905             genPlus (ic) ;
6906             break;
6907
6908         case '-' :
6909             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
6910                 genMinus (ic);
6911             break;
6912
6913         case '*' :
6914             genMult (ic);
6915             break;
6916
6917         case '/' :
6918             genDiv (ic) ;
6919             break;
6920
6921         case '%' :
6922             genMod (ic);
6923             break;
6924
6925         case '>' :
6926             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
6927             break;
6928
6929         case '<' :
6930             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
6931             break;
6932
6933         case LE_OP:
6934         case GE_OP:
6935         case NE_OP:
6936
6937             /* note these two are xlated by algebraic equivalence
6938             during parsing SDCC.y */
6939             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
6940                 "got '>=' or '<=' shouldn't have come here");
6941             break;
6942
6943         case EQ_OP:
6944             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
6945             break;
6946
6947         case AND_OP:
6948             genAndOp (ic);
6949             break;
6950
6951         case OR_OP:
6952             genOrOp (ic);
6953             break;
6954
6955         case '^' :
6956             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
6957             break;
6958
6959         case '|' :
6960             genOr (ic,ifxForOp(IC_RESULT(ic),ic));
6961             break;
6962
6963         case BITWISEAND:
6964             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
6965             break;
6966
6967         case INLINEASM:
6968             genInline (ic);
6969             break;
6970
6971         case RRC:
6972             genRRC (ic);
6973             break;
6974
6975         case RLC:
6976             genRLC (ic);
6977             break;
6978
6979         case GETHBIT:
6980             genGetHbit (ic);
6981             break;
6982
6983         case LEFT_OP:
6984             genLeftShift (ic);
6985             break;
6986
6987         case RIGHT_OP:
6988             genRightShift (ic);
6989             break;
6990
6991         case GET_VALUE_AT_ADDRESS:
6992             genPointerGet(ic);
6993             break;
6994
6995         case '=' :
6996             if (POINTER_SET(ic))
6997                 genPointerSet(ic);
6998             else
6999                 genAssign(ic);
7000             break;
7001
7002         case IFX:
7003             genIfx (ic,NULL);
7004             break;
7005
7006         case ADDRESS_OF:
7007             genAddrOf (ic);
7008             break;
7009
7010         case JUMPTABLE:
7011             genJumpTab (ic);
7012             break;
7013
7014         case CAST:
7015             genCast (ic);
7016             break;
7017
7018         case RECEIVE:
7019             genReceive(ic);
7020             break;
7021
7022         case SEND:
7023             addSet(&_G.sendSet,ic);
7024             break;
7025
7026         case DUMMY_READ_VOLATILE:
7027             genDummyRead (ic);
7028             break;
7029
7030         default :
7031             fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
7032             ic = ic;
7033             break;
7034         }
7035     }
7036
7037
7038     /* now we are ready to call the
7039     peep hole optimizer */
7040     if (!options.nopeep) {
7041         peepHole (&lineHead);
7042     }
7043     /* now do the actual printing */
7044     printLine (lineHead,codeOutBuf);
7045
7046 #ifdef PCODE_DEBUG
7047     DFPRINTF((stderr,"printing pBlock\n\n"));
7048     printpBlock(stdout,pb);
7049 #endif
7050
7051     return;
7052 }
7053
7054 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
7055  * (meaning: representing its own address) or not (referencing its contents).
7056  * This can only be decided based on the operand's type. */
7057 static int
7058 aop_isLitLike (asmop *aop)
7059 {
7060   assert (aop);
7061   if (aop->type == AOP_LIT) return 1;
7062   if (aop->type == AOP_IMMD) return 1;
7063   if ((aop->type == AOP_PCODE) &&
7064         ((aop->aopu.pcop->type == PO_LITERAL)))
7065   {
7066     /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
7067      * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
7068     return 1;
7069   }
7070   return 0;
7071 }
7072
7073 int
7074 op_isLitLike (operand *op)
7075 {
7076   assert (op);
7077   if (aop_isLitLike (AOP(op))) return 1;
7078   if (IS_SYMOP(op) && IS_FUNC(OP_SYM_TYPE(op))) return 1;
7079   if (IS_SYMOP(op) && IS_PTR(OP_SYM_TYPE(op))
7080         && (AOP_TYPE(op) == AOP_PCODE)
7081         && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
7082     return 1;
7083   }
7084
7085   return 0;
7086 }
7087