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