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