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