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