* src/SDCCasm.[ch]: renamed from asm[ch], use dbuf_getline(), ...
[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 char *accUse[] = {"a","b"};
89
90 //static short rbank = -1;
91
92 static struct {
93     short r0Pushed;
94     short r1Pushed;
95     short accInUse;
96     short inLine;
97     short debugLine;
98     short nRegsSaved;
99     set *sendSet;
100 } _G;
101
102 /* Resolved ifx structure. This structure stores information
103 about an iCode ifx that makes it easier to generate code.
104 */
105 typedef struct resolvedIfx {
106     symbol *lbl;     /* pointer to a label */
107     int condition;   /* true or false ifx */
108     int generated;   /* set true when the code associated with the ifx
109                       * is generated */
110 } resolvedIfx;
111
112 extern int pic14_ptrRegReq ;
113 extern int pic14_nRegs;
114 extern struct dbuf_s *codeOutBuf;
115 static void saverbank (int, iCode *,bool);
116
117 static lineNode *lineHead = NULL;
118 static lineNode *lineCurr = NULL;
119
120 #if 0
121 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
122 0xE0, 0xC0, 0x80, 0x00};
123 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
124 0x07, 0x03, 0x01, 0x00};
125 #endif
126
127 static  pBlock *pb;
128
129 /*-----------------------------------------------------------------*/
130 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
131 /*                 exponent of 2 is returned, otherwise -1 is      */
132 /*                 returned.                                       */
133 /* note that this is similar to the function `powof2' in SDCCsymt  */
134 /* if(n == 2^y)                                                    */
135 /*   return y;                                                     */
136 /* return -1;                                                      */
137 /*-----------------------------------------------------------------*/
138 static int my_powof2 (unsigned long num)
139 {
140     if(num) {
141         if( (num & (num-1)) == 0) {
142             int nshifts = -1;
143             while(num) {
144                 num>>=1;
145                 nshifts++;
146             }
147             return nshifts;
148         }
149     }
150
151     return -1;
152 }
153
154 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
155 {
156
157     DEBUGpic14_emitcode ("; ","line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
158         line_no,
159         ((result) ? AopType(AOP_TYPE(result)) : "-"),
160         ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
161         ((result) ? AOP_SIZE(result) : 0),
162         ((left)   ? AopType(AOP_TYPE(left)) : "-"),
163         ((left)   ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
164         ((left)   ? AOP_SIZE(left) : 0),
165         ((right)  ? AopType(AOP_TYPE(right)) : "-"),
166         ((right)  ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
167         ((right)  ? AOP_SIZE(right) : 0));
168
169 }
170
171 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
172 {
173
174     DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
175         line_no,
176         ((result) ? AopType(AOP_TYPE(result)) : "-"),
177         ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
178         ((left)   ? AopType(AOP_TYPE(left)) : "-"),
179         ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
180         ((right)  ? AopType(AOP_TYPE(right)) : "-"),
181         ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
182
183 }
184
185 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
186 {
187     va_list ap;
188     char lb[INITIAL_INLINEASM];
189     unsigned char *lbp = (unsigned char *)lb;
190
191     if(!debug_verbose && !options.debug)
192         return;
193
194     va_start(ap,fmt);
195
196     if (inst && *inst) {
197         if (fmt && *fmt)
198             sprintf(lb,"%s\t",inst);
199         else
200             sprintf(lb,"%s",inst);
201         vsprintf(lb+(strlen(lb)),fmt,ap);
202     }  else
203         vsprintf(lb,fmt,ap);
204
205     while (isspace(*lbp)) lbp++;
206
207     if (lbp && *lbp)
208         lineCurr = (lineCurr ?
209         connectLine(lineCurr,newLineNode(lb)) :
210     (lineHead = newLineNode(lb)));
211     lineCurr->isInline = _G.inLine;
212     lineCurr->isDebug  = _G.debugLine;
213
214     addpCode2pBlock(pb,newpCodeCharP(lb));
215
216     va_end(ap);
217 }
218
219 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
220 {
221 #if defined (HAVE_VSNPRINTF)
222   vsnprintf (buf, size, fmt, ap);
223 #elif defined (HAVE_VSPRINTF)
224   vsprintf (buf, size, fmt, ap);
225   if (strlen (buf) >= size)
226   {
227     fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
228   }
229 #elif defined (HAVE_SNPRINTF)
230   snprintf (buf, size, "vs(n)printf required");
231 #elif defined (HAVE_SRINTF)
232   sprintf (buf, "vs(n)printf required");
233   if (strlen (buf) >= size)
234   {
235     fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
236   }
237 #else
238   assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
239 #endif
240 }
241
242 void emitpComment (const char *fmt, ...)
243 {
244   va_list va;
245   char buffer[4096];
246
247   va_start (va, fmt);
248   if (pb) {
249     Safe_vsnprintf (buffer, 4096, fmt, va);
250     //fprintf (stderr, "%s\n" ,buffer);
251     addpCode2pBlock (pb, newpCodeCharP (buffer));
252 #if 0
253   } else {
254     Safe_vsnprintf (buffer, 4096, fmt, va);
255     fprintf (stderr, "No current pBlock -- discarding comment [%s]\n", buffer);
256 #endif
257   }
258   va_end (va);
259 }
260
261 void emitpLabel(int key)
262 {
263     addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
264 }
265
266 /* gen.h defines a macro emitpcode that should be used to call emitpcode
267  * as this allows for easy debugging (ever asked the question: where was
268  * this instruction geenrated? Here is the answer... */
269 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
270 {
271     if(pcop)
272         addpCode2pBlock(pb,newpCode(poc,pcop));
273     else {
274         static int has_warned = 0;
275
276         DEBUGpic14_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
277         if (!has_warned) {
278             has_warned = 1;
279             fprintf( stderr, "WARNING: encountered NULL pcop--this is probably a compiler bug...\n" );
280         }
281     }
282 }
283
284 void emitpcodeNULLop(PIC_OPCODE poc)
285 {
286
287     addpCode2pBlock(pb,newpCode(poc,NULL));
288
289 }
290
291
292 /*-----------------------------------------------------------------*/
293 /* pic14_emitcode - writes the code into a file : for now it is simple    */
294 /*-----------------------------------------------------------------*/
295 void pic14_emitcode (char *inst,char *fmt, ...)
296 {
297     va_list ap;
298     char lb[INITIAL_INLINEASM];
299     char *lbp = lb;
300
301     va_start(ap,fmt);
302
303     if (inst && *inst) {
304         if (fmt && *fmt)
305             sprintf(lb,"%s\t",inst);
306         else
307             sprintf(lb,"%s",inst);
308         vsprintf(lb+(strlen(lb)),fmt,ap);
309     }  else
310         vsprintf(lb,fmt,ap);
311
312     while (isspace(*lbp)) lbp++;
313
314     if (lbp && *lbp)
315         lineCurr = (lineCurr ?
316         connectLine(lineCurr,newLineNode(lb)) :
317     (lineHead = newLineNode(lb)));
318     lineCurr->isInline = _G.inLine;
319     lineCurr->isDebug  = _G.debugLine;
320     lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
321
322     if(debug_verbose)
323         addpCode2pBlock(pb,newpCodeCharP(lb));
324
325     va_end(ap);
326 }
327
328 /*-----------------------------------------------------------------*/
329 /* pic14_emitDebuggerSymbol - associate the current code location  */
330 /*   with a debugger symbol                                        */
331 /*-----------------------------------------------------------------*/
332 void
333 pic14_emitDebuggerSymbol (char * debugSym)
334 {
335     _G.debugLine = 1;
336     pic14_emitcode ("", ";%s ==.", debugSym);
337     _G.debugLine = 0;
338 }
339
340 #if 0
341 /*-----------------------------------------------------------------*/
342 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
343 /*-----------------------------------------------------------------*/
344 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
345 {
346     bool r0iu = FALSE , r1iu = FALSE;
347     bool r0ou = FALSE , r1ou = FALSE;
348
349     /* the logic: if r0 & r1 used in the instruction
350     then we are in trouble otherwise */
351
352     /* first check if r0 & r1 are used by this
353     instruction, in which case we are in trouble */
354     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
355         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
356     {
357         goto endOfWorld;
358     }
359
360     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
361     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
362
363     /* if no usage of r0 then return it */
364     if (!r0iu && !r0ou) {
365         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
366         (*aopp)->type = AOP_R0;
367
368         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
369     }
370
371     /* if no usage of r1 then return it */
372     if (!r1iu && !r1ou) {
373         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
374         (*aopp)->type = AOP_R1;
375
376         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
377     }
378
379     /* now we know they both have usage */
380     /* if r0 not used in this instruction */
381     if (!r0iu) {
382         /* push it if not already pushed */
383         if (!_G.r0Pushed) {
384             //pic14_emitcode ("push","%s",
385             //        pic14_regWithIdx(R0_IDX)->dname);
386             _G.r0Pushed++ ;
387         }
388
389         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
390         (*aopp)->type = AOP_R0;
391
392         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
393     }
394
395     /* if r1 not used then */
396
397     if (!r1iu) {
398         /* push it if not already pushed */
399         if (!_G.r1Pushed) {
400             //pic14_emitcode ("push","%s",
401             //        pic14_regWithIdx(R1_IDX)->dname);
402             _G.r1Pushed++ ;
403         }
404
405         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
406         (*aopp)->type = AOP_R1;
407         return pic14_regWithIdx(R1_IDX);
408     }
409
410 endOfWorld :
411     /* I said end of world but not quite end of world yet */
412     /* if this is a result then we can push it on the stack*/
413     if (result) {
414         (*aopp)->type = AOP_STK;
415         return NULL;
416     }
417
418     /* other wise this is true end of the world */
419     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
420         "getFreePtr should never reach here");
421     exit(0);
422 }
423 #endif
424
425 /*-----------------------------------------------------------------*/
426 /* newAsmop - creates a new asmOp                                  */
427 /*-----------------------------------------------------------------*/
428 asmop *newAsmop (short type)
429 {
430     asmop *aop;
431
432     aop = Safe_calloc(1,sizeof(asmop));
433     aop->type = type;
434     return aop;
435 }
436
437 static void genSetDPTR(int n)
438 {
439     if (!n)
440     {
441         pic14_emitcode(";", "Select standard DPTR");
442         pic14_emitcode("mov", "dps, #0x00");
443     }
444     else
445     {
446         pic14_emitcode(";", "Select alternate DPTR");
447         pic14_emitcode("mov", "dps, #0x01");
448     }
449 }
450
451 /*-----------------------------------------------------------------*/
452 /* resolveIfx - converts an iCode ifx into a form more useful for  */
453 /*              generating code                                    */
454 /*-----------------------------------------------------------------*/
455 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
456 {
457     if(!resIfx)
458         return;
459
460     //  DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
461
462     resIfx->condition = 1;  /* assume that the ifx is true */
463     resIfx->generated = 0;  /* indicate that the ifx has not been used */
464
465     if(!ifx) {
466         resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL);  / * oops, there is no ifx. so create a label */
467                                             /*
468                                             DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
469                                             __FUNCTION__,__LINE__,resIfx->lbl->key);
470         */
471     } else {
472         if(IC_TRUE(ifx)) {
473             resIfx->lbl = IC_TRUE(ifx);
474         } else {
475             resIfx->lbl = IC_FALSE(ifx);
476             resIfx->condition = 0;
477         }
478         /*
479         if(IC_TRUE(ifx))
480         DEBUGpic14_emitcode("; ***","ifx true is non-null");
481         if(IC_FALSE(ifx))
482         DEBUGpic14_emitcode("; ***","ifx false is non-null");
483         */
484     }
485
486     //  DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
487
488 }
489 /*-----------------------------------------------------------------*/
490 /* pointerCode - returns the code for a pointer type               */
491 /*-----------------------------------------------------------------*/
492 #if 0
493 static int pointerCode (sym_link *etype)
494 {
495
496     return PTR_TYPE(SPEC_OCLS(etype));
497
498 }
499 #endif
500
501 /*-----------------------------------------------------------------*/
502 /* aopForSym - for a true symbol                                   */
503 /*-----------------------------------------------------------------*/
504 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
505 {
506     asmop *aop;
507     memmap *space= SPEC_OCLS(sym->etype);
508
509     DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
510     /* if already has one */
511     if (sym->aop)
512         return sym->aop;
513
514     //DEBUGpic14_emitcode(";","%d",__LINE__);
515     /* if it is in direct space */
516     if (IN_DIRSPACE(space)) {
517         sym->aop = aop = newAsmop (AOP_DIR);
518         aop->aopu.aop_dir = sym->rname ;
519         aop->size = getSize(sym->type);
520         DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
521         return aop;
522     }
523
524     /* special case for a function */
525     if (IS_FUNC(sym->type)) {
526
527         sym->aop = aop = newAsmop(AOP_PCODE);
528         aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
529         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
530         PCOI(aop->aopu.pcop)->_function = 1;
531         PCOI(aop->aopu.pcop)->index = 0;
532         aop->size = FPTRSIZE;
533         /*
534         sym->aop = aop = newAsmop(AOP_IMMD);
535         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
536         strcpy(aop->aopu.aop_immd,sym->rname);
537         aop->size = FPTRSIZE;
538         */
539         DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
540         return aop;
541     }
542
543     if (IS_ARRAY(sym->type)) {
544         sym->aop = aop = newAsmop(AOP_PCODE);
545         aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
546         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
547         PCOI(aop->aopu.pcop)->_function = 0;
548         PCOI(aop->aopu.pcop)->index = 0;
549         aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
550
551         DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
552         return aop;
553     }
554
555     /* only remaining is far space */
556     /* in which case DPTR gets the address */
557     sym->aop = aop = newAsmop(AOP_PCODE);
558
559     aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
560     PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
561     PCOI(aop->aopu.pcop)->index = 0;
562
563     DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
564         __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
565
566     allocDirReg (IC_LEFT(ic));
567
568     aop->size = FPTRSIZE;
569     /*
570     DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
571     sym->aop = aop = newAsmop(AOP_DPTR);
572     pic14_emitcode ("mov","dptr,#%s", sym->rname);
573     aop->size = getSize(sym->type);
574
575       DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
576     */
577
578     /* if it is in code space */
579     if (IN_CODESPACE(space))
580         aop->code = 1;
581
582     return aop;
583 }
584
585 /*-----------------------------------------------------------------*/
586 /* aopForRemat - rematerialzes an object                           */
587 /*-----------------------------------------------------------------*/
588 static asmop *aopForRemat (operand *op) // x symbol *sym)
589 {
590     symbol *sym = OP_SYMBOL(op);
591     iCode *ic = NULL;
592     asmop *aop = newAsmop(AOP_PCODE);
593     int val = 0;
594     int offset = 0;
595
596     ic = sym->rematiCode;
597
598     DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
599     if(IS_OP_POINTER(op)) {
600         DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
601     }
602     for (;;) {
603         if (ic->op == '+') {
604             val += (int) operandLitValue(IC_RIGHT(ic));
605         } else if (ic->op == '-') {
606             val -= (int) operandLitValue(IC_RIGHT(ic));
607         } else
608             break;
609
610         ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
611     }
612
613     offset = OP_SYMBOL(IC_LEFT(ic))->offset;
614     aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
615     PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
616     PCOI(aop->aopu.pcop)->index = val;
617
618     DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
619         __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
620         val, IS_PTR_CONST(operandType(op)));
621
622     //  DEBUGpic14_emitcode(";","aop type  %s",AopType(AOP_TYPE(IC_LEFT(ic))));
623
624     allocDirReg (IC_LEFT(ic));
625
626     return aop;
627 }
628
629 int aopIdx (asmop *aop, int offset)
630 {
631     if(!aop)
632         return -1;
633
634     if(aop->type !=  AOP_REG)
635         return -2;
636
637     return aop->aopu.aop_reg[offset]->rIdx;
638
639 }
640 /*-----------------------------------------------------------------*/
641 /* regsInCommon - two operands have some registers in common       */
642 /*-----------------------------------------------------------------*/
643 static bool regsInCommon (operand *op1, operand *op2)
644 {
645     symbol *sym1, *sym2;
646     int i;
647
648     /* if they have registers in common */
649     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
650         return FALSE ;
651
652     sym1 = OP_SYMBOL(op1);
653     sym2 = OP_SYMBOL(op2);
654
655     if (sym1->nRegs == 0 || sym2->nRegs == 0)
656         return FALSE ;
657
658     for (i = 0 ; i < sym1->nRegs ; i++) {
659         int j;
660         if (!sym1->regs[i])
661             continue ;
662
663         for (j = 0 ; j < sym2->nRegs ;j++ ) {
664             if (!sym2->regs[j])
665                 continue ;
666
667             if (sym2->regs[j] == sym1->regs[i])
668                 return TRUE ;
669         }
670     }
671
672     return FALSE ;
673 }
674
675 /*-----------------------------------------------------------------*/
676 /* operandsEqu - equivalent                                        */
677 /*-----------------------------------------------------------------*/
678 static bool operandsEqu ( operand *op1, operand *op2)
679 {
680     symbol *sym1, *sym2;
681
682     /* if they not symbols */
683     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
684         return FALSE;
685
686     sym1 = OP_SYMBOL(op1);
687     sym2 = OP_SYMBOL(op2);
688
689     /* if both are itemps & one is spilt
690     and the other is not then false */
691     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
692         sym1->isspilt != sym2->isspilt )
693         return FALSE ;
694
695     /* if they are the same */
696     if (sym1 == sym2)
697         return TRUE ;
698
699     if (sym1->rname[0] && sym2->rname[0]
700         && strcmp (sym1->rname, sym2->rname) == 0)
701         return TRUE;
702
703
704     /* if left is a tmp & right is not */
705     if (IS_ITEMP(op1)  &&
706         !IS_ITEMP(op2) &&
707         sym1->isspilt  &&
708         (sym1->usl.spillLoc == sym2))
709         return TRUE;
710
711     if (IS_ITEMP(op2)  &&
712         !IS_ITEMP(op1) &&
713         sym2->isspilt  &&
714         sym1->level > 0 &&
715         (sym2->usl.spillLoc == sym1))
716         return TRUE ;
717
718     return FALSE ;
719 }
720
721 /*-----------------------------------------------------------------*/
722 /* pic14_sameRegs - two asmops have the same registers             */
723 /*-----------------------------------------------------------------*/
724 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
725 {
726     int i;
727
728     if (aop1 == aop2)
729         return TRUE ;
730
731     if (aop1->type != AOP_REG ||
732         aop2->type != AOP_REG )
733         return FALSE ;
734
735     if (aop1->size != aop2->size )
736         return FALSE ;
737
738     for (i = 0 ; i < aop1->size ; i++ )
739         if (aop1->aopu.aop_reg[i] !=
740             aop2->aopu.aop_reg[i] )
741             return FALSE ;
742
743         return TRUE ;
744 }
745
746 /*-----------------------------------------------------------------*/
747 /* aopOp - allocates an asmop for an operand  :                    */
748 /*-----------------------------------------------------------------*/
749 void aopOp (operand *op, iCode *ic, bool result)
750 {
751     asmop *aop;
752     symbol *sym;
753     int i;
754
755     if (!op)
756         return ;
757
758     /* if this a literal */
759     if (IS_OP_LITERAL(op)) {
760         op->aop = aop = newAsmop(AOP_LIT);
761         aop->aopu.aop_lit = op->operand.valOperand;
762         aop->size = getSize(operandType(op));
763         return;
764     }
765
766     {
767         sym_link *type = operandType(op);
768         if(IS_PTR_CONST(type))
769             DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
770     }
771
772     /* if already has a asmop then continue */
773     if (op->aop)
774         return ;
775
776     /* if the underlying symbol has a aop */
777     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
778         DEBUGpic14_emitcode(";","%d",__LINE__);
779         op->aop = OP_SYMBOL(op)->aop;
780         return;
781     }
782
783     /* if this is a true symbol */
784     if (IS_TRUE_SYMOP(op)) {
785         //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
786         op->aop = aopForSym(ic,OP_SYMBOL(op),result);
787         return ;
788     }
789
790     /* this is a temporary : this has
791     only four choices :
792     a) register
793     b) spillocation
794     c) rematerialize
795     d) conditional
796     e) can be a return use only */
797
798     sym = OP_SYMBOL(op);
799
800
801     /* if the type is a conditional */
802     if (sym->regType == REG_CND) {
803         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
804         aop->size = 0;
805         return;
806     }
807
808     /* if it is spilt then two situations
809     a) is rematerialize
810     b) has a spill location */
811     if (sym->isspilt || sym->nRegs == 0) {
812
813         DEBUGpic14_emitcode(";","%d",__LINE__);
814         /* rematerialize it NOW */
815         if (sym->remat) {
816
817             sym->aop = op->aop = aop = aopForRemat (op);
818             aop->size = getSize(sym->type);
819             //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
820             return;
821         }
822
823 #if 0
824         /* WREG is not usable as an ordinary operand with PIC architecture,
825          * one might introduce a scratch register that can be used to make
826          * WREG accesible as an operand... disable WREG for now */
827         if (sym->accuse) {
828             int i;
829             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
830             aop->size = getSize(sym->type);
831             for ( i = 0 ; i < 2 ; i++ )
832                 aop->aopu.aop_str[i] = accUse[i];
833             DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
834             return;
835         }
836 #endif
837
838         if (sym->ruonly ) {
839             if(sym->isptr) {    // && sym->uptr
840                 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
841                 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
842
843                 //PCOI(aop->aopu.pcop)->_const = 0;
844                 //PCOI(aop->aopu.pcop)->index = 0;
845                 /*
846                 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
847                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
848                 */
849                 //allocDirReg (IC_LEFT(ic));
850
851                 aop->size = getSize(sym->type);
852                 DEBUGpic14_emitcode(";","%d",__LINE__);
853                 return;
854
855             } else {
856
857                 unsigned i;
858
859                 aop = op->aop = sym->aop = newAsmop(AOP_STR);
860                 aop->size = getSize(sym->type);
861                 for ( i = 0 ; i < fReturnSizePic ; i++ )
862                     aop->aopu.aop_str[i] = fReturn[i];
863
864                 DEBUGpic14_emitcode(";","%d",__LINE__);
865                 return;
866             }
867         }
868
869         /* else spill location  */
870         if (sym->usl.spillLoc)
871         {
872             asmop *oldAsmOp = NULL;
873
874             if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
875             {
876                 /* force a new aop if sizes differ */
877                 oldAsmOp = sym->usl.spillLoc->aop;
878                 sym->usl.spillLoc->aop = NULL;
879             }
880             DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
881                 __FUNCTION__,__LINE__,
882                 sym->usl.spillLoc->rname,
883                 sym->rname, sym->usl.spillLoc->offset);
884
885             sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
886             if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
887             {
888                 /* Don't reuse the new aop, go with the last one */
889                 sym->usl.spillLoc->aop = oldAsmOp;
890             }
891             //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
892             aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname,
893                 getSize(sym->type),
894                 sym->usl.spillLoc->offset);
895             aop->size = getSize(sym->type);
896
897             return;
898         }
899     }
900
901     {
902         sym_link *type = operandType(op);
903         if(IS_PTR_CONST(type))
904             DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
905     }
906
907     /* must be in a register */
908     DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
909     sym->aop = op->aop = aop = newAsmop(AOP_REG);
910     aop->size = sym->nRegs;
911     for ( i = 0 ; i < sym->nRegs ;i++)
912         aop->aopu.aop_reg[i] = sym->regs[i];
913 }
914
915 /*-----------------------------------------------------------------*/
916 /* freeAsmop - free up the asmop given to an operand               */
917 /*----------------------------------------------------------------*/
918 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
919 {
920     asmop *aop ;
921
922     if (!op)
923         aop = aaop;
924     else
925         aop = op->aop;
926
927     if (!aop)
928         return ;
929
930     if (aop->freed)
931         goto dealloc;
932
933     aop->freed = 1;
934
935     /* depending on the asmop type only three cases need work AOP_RO
936     , AOP_R1 && AOP_STK */
937 #if 0
938     switch (aop->type) {
939     case AOP_R0 :
940         if (_G.r0Pushed ) {
941             if (pop) {
942                 pic14_emitcode ("pop","ar0");
943                 _G.r0Pushed--;
944             }
945         }
946         bitVectUnSetBit(ic->rUsed,R0_IDX);
947         break;
948
949     case AOP_R1 :
950         if (_G.r1Pushed ) {
951             if (pop) {
952                 pic14_emitcode ("pop","ar1");
953                 _G.r1Pushed--;
954             }
955         }
956         bitVectUnSetBit(ic->rUsed,R1_IDX);
957         break;
958
959     case AOP_STK :
960         {
961             int sz = aop->size;
962             int stk = aop->aopu.aop_stk + aop->size;
963             bitVectUnSetBit(ic->rUsed,R0_IDX);
964             bitVectUnSetBit(ic->rUsed,R1_IDX);
965
966             getFreePtr(ic,&aop,FALSE);
967
968             if (options.stack10bit)
969             {
970                 /* I'm not sure what to do here yet... */
971                 /* #STUB */
972                 fprintf(stderr,
973                     "*** Warning: probably generating bad code for "
974                     "10 bit stack mode.\n");
975             }
976
977             if (stk) {
978                 pic14_emitcode ("mov","a,_bp");
979                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
980                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
981             } else {
982                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
983             }
984
985             while (sz--) {
986                 pic14_emitcode("pop","acc");
987                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
988                 if (!sz) break;
989                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
990             }
991             op->aop = aop;
992             freeAsmop(op,NULL,ic,TRUE);
993             if (_G.r0Pushed) {
994                 pic14_emitcode("pop","ar0");
995                 _G.r0Pushed--;
996             }
997
998             if (_G.r1Pushed) {
999                 pic14_emitcode("pop","ar1");
1000                 _G.r1Pushed--;
1001             }
1002         }
1003     }
1004 #endif
1005
1006 dealloc:
1007     /* all other cases just dealloc */
1008     if (op ) {
1009         op->aop = NULL;
1010         if (IS_SYMOP(op)) {
1011             OP_SYMBOL(op)->aop = NULL;
1012             /* if the symbol has a spill */
1013             if (SPIL_LOC(op))
1014                 SPIL_LOC(op)->aop = NULL;
1015         }
1016     }
1017 }
1018
1019 /*-----------------------------------------------------------------*/
1020 /* aopGet - for fetching value of the aop                          */
1021 /*-----------------------------------------------------------------*/
1022 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1023 {
1024     char *s = buffer ;
1025     char *rs;
1026
1027     //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1028     /* offset is greater than
1029     size then zero */
1030     assert(aop);
1031     if (offset > (aop->size - 1) &&
1032         aop->type != AOP_LIT)
1033         return zero;
1034
1035     /* depending on type */
1036     switch (aop->type) {
1037
1038     case AOP_R0:
1039     case AOP_R1:
1040         DEBUGpic14_emitcode(";","%d",__LINE__);
1041         /* if we need to increment it */
1042         while (offset > aop->coff) {
1043             pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);
1044             aop->coff++;
1045         }
1046
1047         while (offset < aop->coff) {
1048             pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1049             aop->coff--;
1050         }
1051
1052         aop->coff = offset ;
1053         if (aop->paged) {
1054             pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1055             return (dname ? "acc" : "a");
1056         }
1057         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1058         rs = Safe_calloc(1,strlen(s)+1);
1059         strcpy(rs,s);
1060         return rs;
1061
1062     case AOP_DPTR:
1063     case AOP_DPTR2:
1064         DEBUGpic14_emitcode(";","%d",__LINE__);
1065         if (aop->type == AOP_DPTR2)
1066         {
1067             genSetDPTR(1);
1068         }
1069
1070         while (offset > aop->coff) {
1071             pic14_emitcode ("inc","dptr");
1072             aop->coff++;
1073         }
1074
1075         while (offset < aop->coff) {
1076             pic14_emitcode("lcall","__decdptr");
1077             aop->coff--;
1078         }
1079
1080         aop->coff = offset;
1081         if (aop->code) {
1082             pic14_emitcode("clr","a");
1083             pic14_emitcode("movc","a,@a+dptr");
1084         }
1085         else {
1086             pic14_emitcode("movx","a,@dptr");
1087         }
1088
1089         if (aop->type == AOP_DPTR2)
1090         {
1091             genSetDPTR(0);
1092         }
1093
1094         return (dname ? "acc" : "a");
1095
1096
1097     case AOP_IMMD:
1098         if (bit16)
1099             sprintf (s,"%s",aop->aopu.aop_immd);
1100         else
1101             if (offset)
1102                 sprintf(s,"(%s >> %d)",
1103                 aop->aopu.aop_immd,
1104                 offset*8);
1105             else
1106                 sprintf(s,"%s",
1107                 aop->aopu.aop_immd);
1108             DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1109             rs = Safe_calloc(1,strlen(s)+1);
1110             strcpy(rs,s);
1111             return rs;
1112
1113     case AOP_DIR:
1114         if (offset) {
1115             sprintf(s,"(%s + %d)",
1116                 aop->aopu.aop_dir,
1117                 offset);
1118             DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1119         } else
1120             sprintf(s,"%s",aop->aopu.aop_dir);
1121         rs = Safe_calloc(1,strlen(s)+1);
1122         strcpy(rs,s);
1123         return rs;
1124
1125     case AOP_REG:
1126         //if (dname)
1127         //    return aop->aopu.aop_reg[offset]->dname;
1128         //else
1129         return aop->aopu.aop_reg[offset]->name;
1130
1131     case AOP_CRY:
1132         //pic14_emitcode(";","%d",__LINE__);
1133         return aop->aopu.aop_dir;
1134
1135     case AOP_ACC:
1136         DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1137         return "AOP_accumulator_bug";
1138
1139     case AOP_LIT:
1140         sprintf(s, "0x%02x", pic14aopLiteral (aop->aopu.aop_lit, offset));
1141         rs = Safe_strdup(s);
1142         return rs;
1143
1144     case AOP_STR:
1145         aop->coff = offset ;
1146         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1147             dname)
1148             return "acc";
1149         DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1150
1151         return aop->aopu.aop_str[offset];
1152
1153     case AOP_PCODE:
1154         {
1155             pCodeOp *pcop = aop->aopu.pcop;
1156             DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1157             if(pcop->name) {
1158                 if (pcop->type == PO_IMMEDIATE) {
1159                     offset += PCOI(pcop)->index;
1160                 }
1161                 if (offset) {
1162                     DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1163                     sprintf(s,"(%s+%d)", pcop->name,offset);
1164                 } else {
1165                     DEBUGpic14_emitcode(";","%s",pcop->name);
1166                     sprintf(s,"%s", pcop->name);
1167                 }
1168             } else
1169                 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1170
1171         }
1172         rs = Safe_calloc(1,strlen(s)+1);
1173         strcpy(rs,s);
1174         return rs;
1175
1176   }
1177
1178   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1179       "aopget got unsupported aop->type");
1180   exit(0);
1181 }
1182
1183
1184 /*-----------------------------------------------------------------*/
1185 /* popGetTempReg - create a new temporary pCodeOp                  */
1186 /*-----------------------------------------------------------------*/
1187 pCodeOp *popGetTempReg(void)
1188 {
1189
1190     pCodeOp *pcop;
1191
1192     pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1193     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1194         PCOR(pcop)->r->wasUsed=1;
1195         PCOR(pcop)->r->isFree=0;
1196     }
1197
1198     return pcop;
1199 }
1200
1201 /*-----------------------------------------------------------------*/
1202 /* popReleaseTempReg - create a new temporary pCodeOp                  */
1203 /*-----------------------------------------------------------------*/
1204 void popReleaseTempReg(pCodeOp *pcop)
1205 {
1206
1207     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1208         PCOR(pcop)->r->isFree = 1;
1209
1210 }
1211 /*-----------------------------------------------------------------*/
1212 /* popGetLabel - create a new pCodeOp of type PO_LABEL             */
1213 /*-----------------------------------------------------------------*/
1214 pCodeOp *popGetLabel(unsigned int key)
1215 {
1216
1217     DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1218
1219     if(key>(unsigned int)max_key)
1220         max_key = key;
1221
1222     return newpCodeOpLabel(NULL,key+100+labelOffset);
1223 }
1224
1225 /*-------------------------------------------------------------------*/
1226 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1227 /*-------------------------------------------------------------------*/
1228 pCodeOp *popGetHighLabel(unsigned int key)
1229 {
1230     pCodeOp *pcop;
1231     pcop = popGetLabel(key);
1232     PCOLAB(pcop)->offset = 1;
1233     return pcop;
1234 }
1235
1236 /*-----------------------------------------------------------------*/
1237 /* popGetLit - asm operator to pcode operator conversion               */
1238 /*-----------------------------------------------------------------*/
1239 pCodeOp *popGetLit(unsigned int lit)
1240 {
1241
1242     return newpCodeOpLit((unsigned char)lit);
1243 }
1244
1245 /*-----------------------------------------------------------------*/
1246 /* popGetImmd - asm operator to pcode immediate conversion         */
1247 /*-----------------------------------------------------------------*/
1248 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1249 {
1250
1251     return newpCodeOpImmd(name, offset,index, 0, is_func);
1252 }
1253
1254 extern set *externs;
1255
1256 /*-----------------------------------------------------------------*/
1257 /* popGetWithString - asm operator to pcode operator conversion            */
1258 /*-----------------------------------------------------------------*/
1259 pCodeOp *popGetWithString(char *str, int isExtern)
1260 {
1261     pCodeOp *pcop;
1262
1263
1264     if(!str) {
1265         fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1266         exit (1);
1267     }
1268
1269     pcop = newpCodeOp(str,PO_STR);
1270     PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1271
1272     return pcop;
1273 }
1274
1275 pCodeOp *popGetExternal (char *str, int isReg)
1276 {
1277     pCodeOp *pcop;
1278
1279     if (isReg) {
1280         pcop = newpCodeOpRegFromStr(str);
1281     } else {
1282         pcop = popGetWithString (str, 1);
1283     }
1284
1285     if (str) {
1286       symbol *sym;
1287
1288       for (sym = setFirstItem (externs); sym; sym = setNextItem (externs))
1289       {
1290         if (!strcmp (str, sym->rname)) break;
1291       }
1292
1293       if (!sym)
1294       {
1295         sym = newSymbol(str, 0);
1296         strncpy(sym->rname, str, SDCC_NAME_MAX);
1297         addSet (&externs, sym);
1298       } // if
1299       sym->used++;
1300     }
1301     return pcop;
1302 }
1303
1304 /*-----------------------------------------------------------------*/
1305 /* popRegFromString -                                              */
1306 /*-----------------------------------------------------------------*/
1307 pCodeOp *popRegFromString(char *str, int size, int offset)
1308 {
1309
1310     pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1311     pcop->type = PO_DIR;
1312
1313     DEBUGpic14_emitcode(";","%d",__LINE__);
1314
1315     if(!str)
1316         str = "BAD_STRING";
1317
1318     pcop->name = Safe_calloc(1,strlen(str)+1);
1319     strcpy(pcop->name,str);
1320
1321     //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1322
1323     PCOR(pcop)->r = dirregWithName(pcop->name);
1324     if(PCOR(pcop)->r == NULL) {
1325         //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1326         PCOR(pcop)->r = allocRegByName (pcop->name,size);
1327         DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1328     } else {
1329         DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1330     }
1331     PCOR(pcop)->instance = offset;
1332
1333     return pcop;
1334 }
1335
1336 /*-----------------------------------------------------------------*/
1337 /*-----------------------------------------------------------------*/
1338 pCodeOp *popRegFromIdx(int rIdx)
1339 {
1340     pCodeOp *pcop;
1341
1342     DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1343         __FUNCTION__,__LINE__,rIdx);
1344
1345     pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1346
1347     PCOR(pcop)->rIdx = rIdx;
1348     PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1349     PCOR(pcop)->r->isFree = 0;
1350     PCOR(pcop)->r->wasUsed = 1;
1351
1352     pcop->type = PCOR(pcop)->r->pc_type;
1353
1354
1355     return pcop;
1356 }
1357
1358 /*-----------------------------------------------------------------*/
1359 /* popGet - asm operator to pcode operator conversion              */
1360 /*-----------------------------------------------------------------*/
1361 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1362 {
1363     //char *s = buffer ;
1364     //char *rs;
1365
1366     pCodeOp *pcop;
1367
1368     //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1369     /* offset is greater than
1370     size then zero */
1371
1372     assert (aop);
1373
1374
1375     /* XXX: still needed for BIT operands (AOP_CRY) */
1376     if (offset > (aop->size - 1) &&
1377         aop->type != AOP_LIT &&
1378         aop->type != AOP_PCODE)
1379     {
1380         printf( "%s: (offset[%d] > AOP_SIZE(op)[%d]-1) && AOP_TYPE(op) != AOP_LIT)\n", __FUNCTION__, offset, aop->size);
1381         return NULL;  //zero;
1382     }
1383
1384     /* depending on type */
1385     switch (aop->type) {
1386
1387     case AOP_R0:
1388     case AOP_R1:
1389     case AOP_DPTR:
1390     case AOP_DPTR2:
1391     case AOP_ACC:
1392         DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1393         return NULL;
1394
1395     case AOP_IMMD:
1396         DEBUGpic14_emitcode(";","%d",__LINE__);
1397         return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1398
1399     case AOP_DIR:
1400         return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1401 #if 0
1402         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1403         pcop->type = PO_DIR;
1404
1405         pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1406         strcpy(pcop->name,aop->aopu.aop_dir);
1407         PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1408         if(PCOR(pcop)->r == NULL) {
1409             //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1410             PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1411             DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1412         } else {
1413             DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1414         }
1415         PCOR(pcop)->instance = offset;
1416
1417         return pcop;
1418 #endif
1419
1420     case AOP_REG:
1421         {
1422             int rIdx;
1423             assert (offset < aop->size);
1424             rIdx = aop->aopu.aop_reg[offset]->rIdx;
1425
1426             pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1427             PCOR(pcop)->rIdx = rIdx;
1428             PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1429             PCOR(pcop)->r->wasUsed=1;
1430             PCOR(pcop)->r->isFree=0;
1431
1432             PCOR(pcop)->instance = offset;
1433             pcop->type = PCOR(pcop)->r->pc_type;
1434             //rs = aop->aopu.aop_reg[offset]->name;
1435             DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1436             return pcop;
1437         }
1438
1439     case AOP_CRY:
1440         pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1441         PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1442         //if(PCOR(pcop)->r == NULL)
1443         //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1444         return pcop;
1445
1446     case AOP_LIT:
1447         return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1448
1449     case AOP_STR:
1450         DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1451         return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1452         /*
1453         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1454         PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1455         PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1456         pcop->type = PCOR(pcop)->r->pc_type;
1457         pcop->name = PCOR(pcop)->r->name;
1458
1459           return pcop;
1460         */
1461
1462     case AOP_PCODE:
1463         pcop = NULL;
1464         DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1465             __LINE__,
1466             ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1467         //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1468         switch (aop->aopu.pcop->type)
1469         {
1470         case PO_IMMEDIATE:
1471           pcop = pCodeOpCopy (aop->aopu.pcop);
1472           /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1473            * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1474           PCOI(pcop)->index += offset;
1475           //PCOI(pcop)->offset = 0;
1476           break;
1477         case PO_DIR:
1478           pcop = pCodeOpCopy (aop->aopu.pcop);
1479           PCOR(pcop)->instance = offset;
1480           break;
1481         default:
1482           assert ( !"unhandled pCode type" );
1483           break;
1484         } // switch
1485         return pcop;
1486     }
1487
1488     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1489         "popGet got unsupported aop->type");
1490     exit(0);
1491 }
1492
1493 /*-----------------------------------------------------------------*/
1494 /* popGetAddr - access the low/high word of a symbol (immediate)   */
1495 /*              (for non-PO_IMMEDIATEs this is the same as popGet) */
1496 /*-----------------------------------------------------------------*/
1497 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1498 {
1499   if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1500   {
1501     pCodeOp *pcop = aop->aopu.pcop;
1502     assert (offset <= GPTRSIZE);
1503
1504     /* special case: index >= 2 should return GPOINTER-style values */
1505     if (offset == 2)
1506     {
1507       pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1508       return pcop;
1509     }
1510
1511     pcop = pCodeOpCopy (pcop);
1512     /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1513      * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1514     PCOI(pcop)->offset += offset;
1515     PCOI(pcop)->index += index;
1516     //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);
1517     return pcop;
1518   } else {
1519     return popGet (aop, offset + index);
1520   }
1521 }
1522
1523 /*-----------------------------------------------------------------*/
1524 /* aopPut - puts a string for a aop                                */
1525 /*-----------------------------------------------------------------*/
1526 void aopPut (asmop *aop, char *s, int offset)
1527 {
1528     char *d = buffer ;
1529     symbol *lbl ;
1530
1531     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1532
1533     if (aop->size && offset > ( aop->size - 1)) {
1534         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1535             "aopPut got offset > aop->size");
1536         exit(0);
1537     }
1538
1539     /* will assign value to value */
1540     /* depending on where it is ofcourse */
1541     switch (aop->type) {
1542     case AOP_DIR:
1543         if (offset) {
1544             sprintf(d,"(%s + %d)",
1545                 aop->aopu.aop_dir,offset);
1546             fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1547
1548         } else
1549             sprintf(d,"%s",aop->aopu.aop_dir);
1550
1551         if (strcmp(d,s)) {
1552             DEBUGpic14_emitcode(";","%d",__LINE__);
1553             if(strcmp(s,"W"))
1554                 pic14_emitcode("movf","%s,w",s);
1555             pic14_emitcode("movwf","%s",d);
1556
1557             if(strcmp(s,"W")) {
1558                 pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1559                 if(offset >= aop->size) {
1560                     emitpcode(POC_CLRF,popGet(aop,offset));
1561                     break;
1562                 } else {
1563                     emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1564                 }
1565             }
1566             emitpcode(POC_MOVWF,popGet(aop,offset));
1567
1568         }
1569         break;
1570
1571     case AOP_REG:
1572         if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1573             //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1574             /*
1575             if (*s == '@'         ||
1576             strcmp(s,"r0") == 0 ||
1577             strcmp(s,"r1") == 0 ||
1578             strcmp(s,"r2") == 0 ||
1579             strcmp(s,"r3") == 0 ||
1580             strcmp(s,"r4") == 0 ||
1581             strcmp(s,"r5") == 0 ||
1582             strcmp(s,"r6") == 0 ||
1583             strcmp(s,"r7") == 0 )
1584             pic14_emitcode("mov","%s,%s  ; %d",
1585             aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1586             else
1587             */
1588
1589             if(strcmp(s,"W")==0 )
1590                 pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1591
1592             pic14_emitcode("movwf","%s",
1593                 aop->aopu.aop_reg[offset]->name);
1594
1595             if(strcmp(s,zero)==0) {
1596                 emitpcode(POC_CLRF,popGet(aop,offset));
1597
1598             } else if(strcmp(s,"W")==0) {
1599                 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1600                 pcop->type = PO_GPR_REGISTER;
1601
1602                 PCOR(pcop)->rIdx = -1;
1603                 PCOR(pcop)->r = NULL;
1604
1605                 DEBUGpic14_emitcode(";","%d",__LINE__);
1606                 pcop->name = Safe_strdup(s);
1607                 emitpcode(POC_MOVFW,pcop);
1608                 emitpcode(POC_MOVWF,popGet(aop,offset));
1609             } else if(strcmp(s,one)==0) {
1610                 emitpcode(POC_CLRF,popGet(aop,offset));
1611                 emitpcode(POC_INCF,popGet(aop,offset));
1612             } else {
1613                 emitpcode(POC_MOVWF,popGet(aop,offset));
1614             }
1615         }
1616         break;
1617
1618     case AOP_DPTR:
1619     case AOP_DPTR2:
1620
1621         if (aop->type == AOP_DPTR2)
1622         {
1623             genSetDPTR(1);
1624         }
1625
1626         if (aop->code) {
1627             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1628                 "aopPut writting to code space");
1629             exit(0);
1630         }
1631
1632         while (offset > aop->coff) {
1633             aop->coff++;
1634             pic14_emitcode ("inc","dptr");
1635         }
1636
1637         while (offset < aop->coff) {
1638             aop->coff-- ;
1639             pic14_emitcode("lcall","__decdptr");
1640         }
1641
1642         aop->coff = offset;
1643
1644         /* if not in accumulater */
1645         MOVA(s);
1646
1647         pic14_emitcode ("movx","@dptr,a");
1648
1649         if (aop->type == AOP_DPTR2)
1650         {
1651             genSetDPTR(0);
1652         }
1653         break;
1654
1655     case AOP_R0:
1656     case AOP_R1:
1657         while (offset > aop->coff) {
1658             aop->coff++;
1659             pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1660         }
1661         while (offset < aop->coff) {
1662             aop->coff-- ;
1663             pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1664         }
1665         aop->coff = offset;
1666
1667         if (aop->paged) {
1668             MOVA(s);
1669             pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1670
1671         } else
1672             if (*s == '@') {
1673                 MOVA(s);
1674                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1675             } else
1676                 if (strcmp(s,"r0") == 0 ||
1677                     strcmp(s,"r1") == 0 ||
1678                     strcmp(s,"r2") == 0 ||
1679                     strcmp(s,"r3") == 0 ||
1680                     strcmp(s,"r4") == 0 ||
1681                     strcmp(s,"r5") == 0 ||
1682                     strcmp(s,"r6") == 0 ||
1683                     strcmp(s,"r7") == 0 ) {
1684                     char buffer[10];
1685                     sprintf(buffer,"a%s",s);
1686                     pic14_emitcode("mov","@%s,%s",
1687                         aop->aopu.aop_ptr->name,buffer);
1688                 } else
1689                     pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1690
1691                 break;
1692
1693     case AOP_STK:
1694         if (strcmp(s,"a") == 0)
1695             pic14_emitcode("push","acc");
1696         else
1697             pic14_emitcode("push","%s",s);
1698
1699         break;
1700
1701     case AOP_CRY:
1702         /* if bit variable */
1703         if (!aop->aopu.aop_dir) {
1704             pic14_emitcode("clr","a");
1705             pic14_emitcode("rlc","a");
1706         } else {
1707             if (s == zero)
1708                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1709             else
1710                 if (s == one)
1711                     pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1712                 else
1713                     if (!strcmp(s,"c"))
1714                         pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1715                     else {
1716                         lbl = newiTempLabel(NULL);
1717
1718                         if (strcmp(s,"a")) {
1719                             MOVA(s);
1720                         }
1721                         pic14_emitcode("clr","c");
1722                         pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1723                         pic14_emitcode("cpl","c");
1724                         pic14_emitcode("","%05d_DS_:",lbl->key+100);
1725                         pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1726                     }
1727         }
1728         break;
1729
1730     case AOP_STR:
1731         aop->coff = offset;
1732         if (strcmp(aop->aopu.aop_str[offset],s))
1733             pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1734         break;
1735
1736     case AOP_ACC:
1737         aop->coff = offset;
1738         if (!offset && (strcmp(s,"acc") == 0))
1739             break;
1740
1741         if (strcmp(aop->aopu.aop_str[offset],s))
1742             pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1743         break;
1744
1745     default :
1746         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1747             "aopPut got unsupported aop->type");
1748         exit(0);
1749     }
1750
1751 }
1752
1753 /*-----------------------------------------------------------------*/
1754 /* mov2w_op - generate either a MOVLW or MOVFW based operand type  */
1755 /*-----------------------------------------------------------------*/
1756 static void mov2w_op (operand *op, int offset)
1757 {
1758     assert (op);
1759     FENTRY;
1760
1761     /* for PO_IMMEDIATEs: use address or value? */
1762     if (op_isLitLike (op))
1763     {
1764         /* access address of op */
1765         if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1766         if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1767         {
1768             if (offset == GPTRSIZE-1)
1769                 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1770             else
1771                 emitpcode (POC_MOVLW, popGetLit (0));
1772         }
1773         else
1774             emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1775     } else {
1776         /* access value stored in op */
1777         mov2w (AOP(op), offset);
1778     }
1779 }
1780
1781
1782 /*-----------------------------------------------------------------*/
1783 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1784 /*-----------------------------------------------------------------*/
1785 void mov2w (asmop *aop, int offset)
1786 {
1787
1788     if(!aop)
1789         return;
1790
1791     DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1792
1793     if ( aop_isLitLike (aop) )
1794         emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1795     else
1796         emitpcode(POC_MOVFW,popGet(aop,offset));
1797
1798 }
1799
1800 static void movwf (asmop *op, int offset)
1801 {
1802     emitpcode (POC_MOVWF, popGet(op, offset));
1803 }
1804
1805 static pCodeOp *get_argument_pcop (int idx)
1806 {
1807     assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1808     return popRegFromIdx (Gstack_base_addr - (idx - 1));
1809 }
1810
1811 static pCodeOp *get_return_val_pcop (int offset)
1812 {
1813     assert (offset > 0 && "the most significant byte is returned via WREG");
1814     return popRegFromIdx (Gstack_base_addr - (offset - 1));
1815 }
1816
1817 static void pass_argument (operand *op, int offset, int idx)
1818 {
1819     if (op)
1820         mov2w_op (op, offset);
1821     if (idx != 0)
1822         emitpcode(POC_MOVWF, get_argument_pcop (idx));
1823 }
1824
1825 static void get_returnvalue (operand *op, int offset, int idx)
1826 {
1827     if (idx != 0)
1828         emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1829     movwf(AOP(op), offset);
1830 }
1831
1832 static void call_libraryfunc (char *name)
1833 {
1834     symbol *sym;
1835
1836     /* library code might reside in different page... */
1837     emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1838     /* call the library function */
1839     emitpcode (POC_CALL, popGetExternal (name, 0));
1840     /* might return from different page... */
1841     emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1842
1843     /* create symbol, mark it as `extern' */
1844     sym = findSym(SymbolTab, NULL, name);
1845     if (!sym) {
1846     sym = newSymbol(name, 0);
1847     strncpy(sym->rname, name, SDCC_NAME_MAX);
1848     addSym(SymbolTab, sym, sym->rname, 0, 0, 0);
1849     addSet(&externs, sym);
1850     } // if
1851     sym->used++;
1852 }
1853
1854 #if 0
1855 /*-----------------------------------------------------------------*/
1856 /* reAdjustPreg - points a register back to where it should        */
1857 /*-----------------------------------------------------------------*/
1858 static void reAdjustPreg (asmop *aop)
1859 {
1860     int size ;
1861
1862     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1863     aop->coff = 0;
1864     if ((size = aop->size) <= 1)
1865         return ;
1866     size-- ;
1867     switch (aop->type) {
1868     case AOP_R0 :
1869     case AOP_R1 :
1870         while (size--)
1871             pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1872         break;
1873     case AOP_DPTR :
1874     case AOP_DPTR2:
1875         if (aop->type == AOP_DPTR2)
1876         {
1877             genSetDPTR(1);
1878         }
1879         while (size--)
1880         {
1881             pic14_emitcode("lcall","__decdptr");
1882         }
1883
1884         if (aop->type == AOP_DPTR2)
1885         {
1886             genSetDPTR(0);
1887         }
1888         break;
1889
1890     }
1891
1892 }
1893 #endif
1894
1895
1896 #if 0
1897 /*-----------------------------------------------------------------*/
1898 /* opIsGptr: returns non-zero if the passed operand is             */
1899 /* a generic pointer type.                                         */
1900 /*-----------------------------------------------------------------*/
1901 static int opIsGptr(operand *op)
1902 {
1903     sym_link *type = operandType(op);
1904
1905     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1906     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1907     {
1908         return 1;
1909     }
1910     return 0;
1911 }
1912 #endif
1913
1914 /*-----------------------------------------------------------------*/
1915 /* pic14_getDataSize - get the operand data size                   */
1916 /*-----------------------------------------------------------------*/
1917 int pic14_getDataSize(operand *op)
1918 {
1919     int size;
1920
1921     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1922
1923 #if 0
1924     size = getSize(OP_SYM_ETYPE(op));
1925     return size;
1926     //return AOP_SIZE(op);
1927
1928     // tsd- in the pic port, the genptr size is 1, so this code here
1929     // fails. ( in the 8051 port, the size was 4).
1930 #else
1931     size = AOP_SIZE(op);
1932     if (IS_GENPTR(OP_SYM_TYPE(op)))
1933     {
1934         sym_link *type = operandType(op);
1935         if (IS_GENPTR(type))
1936         {
1937             /* generic pointer; arithmetic operations
1938             * should ignore the high byte (pointer type).
1939             */
1940             size--;
1941             DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1942         }
1943     }
1944     return size;
1945 #endif
1946 }
1947
1948 /*-----------------------------------------------------------------*/
1949 /* pic14_outAcc - output Acc                                       */
1950 /*-----------------------------------------------------------------*/
1951 void pic14_outAcc(operand *result)
1952 {
1953     int size,offset;
1954     DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1955     DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1956
1957
1958     size = pic14_getDataSize(result);
1959     if(size){
1960         emitpcode(POC_MOVWF,popGet(AOP(result),0));
1961         size--;
1962         offset = 1;
1963         /* unsigned or positive */
1964         while(size--)
1965             emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1966     }
1967
1968 }
1969
1970 /*-----------------------------------------------------------------*/
1971 /* pic14_outBitC - output a bit C                                  */
1972 /*-----------------------------------------------------------------*/
1973 void pic14_outBitC(operand *result)
1974 {
1975
1976     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1977     /* if the result is bit */
1978     if (AOP_TYPE(result) == AOP_CRY)
1979         aopPut(AOP(result),"c",0);
1980     else {
1981         pic14_emitcode("clr","a  ; %d", __LINE__);
1982         pic14_emitcode("rlc","a");
1983         pic14_outAcc(result);
1984     }
1985 }
1986
1987 /*-----------------------------------------------------------------*/
1988 /* pic14_toBoolean - emit code for orl a,operator(sizeop)          */
1989 /*-----------------------------------------------------------------*/
1990 void pic14_toBoolean(operand *oper)
1991 {
1992     int size = AOP_SIZE(oper);
1993     int offset = 0;
1994
1995     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1996
1997     assert (size > 0);
1998
1999     if (size == 1) {
2000         /* MOVFW does not load the flags... */
2001         if (AOP_TYPE(oper) == AOP_ACC) {
2002             emitpcode(POC_IORLW, popGetLit(0));
2003             offset = 1;
2004         } else {
2005             emitpcode(POC_MOVLW, popGetLit(0));
2006             offset = 0;
2007         }
2008     } else {
2009         if ( AOP_TYPE(oper) != AOP_ACC) {
2010             emitpcode(POC_MOVFW,popGet(AOP(oper),0));
2011             offset = 1;
2012         }
2013     }
2014
2015     while (offset < size) {
2016         emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
2017     }
2018     /* Z is set iff (oper == 0) */
2019 }
2020
2021
2022 /*-----------------------------------------------------------------*/
2023 /* genNot - generate code for ! operation                          */
2024 /*-----------------------------------------------------------------*/
2025 static void genNot (iCode *ic)
2026 {
2027     //symbol *tlbl;
2028     int size;
2029
2030     FENTRY;
2031
2032     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2033     /* assign asmOps to operand & result */
2034     aopOp (IC_LEFT(ic),ic,FALSE);
2035     aopOp (IC_RESULT(ic),ic,TRUE);
2036
2037     DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2038     /* if in bit space then a special case */
2039     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2040         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2041             emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2042             emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2043         } else {
2044             emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2045             emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2046             emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2047         }
2048         goto release;
2049     }
2050
2051     size = AOP_SIZE(IC_LEFT(ic));
2052     mov2w (AOP(IC_LEFT(ic)),0);
2053     while (--size > 0)
2054     {
2055       if (op_isLitLike (IC_LEFT(ic)))
2056         emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2057       else
2058         emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2059     }
2060     emitpcode(POC_MOVLW, popGetLit (0));
2061     emitSKPNZ;
2062     emitpcode(POC_MOVLW, popGetLit (1));
2063     movwf(AOP(IC_RESULT(ic)), 0);
2064
2065     for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2066     {
2067       emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2068     }
2069     goto release;
2070
2071 release:
2072     /* release the aops */
2073     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2074     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2075 }
2076
2077
2078 /*-----------------------------------------------------------------*/
2079 /* genCpl - generate code for complement                           */
2080 /*-----------------------------------------------------------------*/
2081 static void genCpl (iCode *ic)
2082 {
2083     operand *left, *result;
2084     int size, offset=0;
2085
2086     FENTRY;
2087
2088     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2089     aopOp((left = IC_LEFT(ic)),ic,FALSE);
2090     aopOp((result=IC_RESULT(ic)),ic,TRUE);
2091
2092     /* if both are in bit space then
2093     a special case */
2094     if (AOP_TYPE(result) == AOP_CRY &&
2095         AOP_TYPE(left) == AOP_CRY ) {
2096
2097         pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir);
2098         pic14_emitcode("cpl","c");
2099         pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir);
2100         goto release;
2101     }
2102
2103     size = AOP_SIZE(result);
2104     if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2105     while (size--) {
2106
2107         if(AOP_TYPE(left) == AOP_ACC)
2108             emitpcode(POC_XORLW, popGetLit(0xff));
2109         else
2110             emitpcode(POC_COMFW,popGet(AOP(left),offset));
2111
2112         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2113         offset++;
2114     }
2115     addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2116
2117
2118 release:
2119     /* release the aops */
2120     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2121     freeAsmop(result,NULL,ic,TRUE);
2122 }
2123
2124 /*-----------------------------------------------------------------*/
2125 /* genUminusFloat - unary minus for floating points                */
2126 /*-----------------------------------------------------------------*/
2127 static void genUminusFloat(operand *op,operand *result)
2128 {
2129     int size ,offset =0 ;
2130     char *l;
2131
2132     FENTRY;
2133
2134     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2135     /* for this we just need to flip the
2136     first it then copy the rest in place */
2137     size = AOP_SIZE(op) - 1;
2138     l = aopGet(AOP(op),3,FALSE,FALSE);
2139
2140     MOVA(l);
2141
2142     pic14_emitcode("cpl","acc.7");
2143     aopPut(AOP(result),"a",3);
2144
2145     while(size--) {
2146         aopPut(AOP(result),
2147             aopGet(AOP(op),offset,FALSE,FALSE),
2148             offset);
2149         offset++;
2150     }
2151 }
2152
2153 /*-----------------------------------------------------------------*/
2154 /* genUminus - unary minus code generation                         */
2155 /*-----------------------------------------------------------------*/
2156 static void genUminus (iCode *ic)
2157 {
2158     int size, i;
2159     sym_link *optype, *rtype;
2160
2161     FENTRY;
2162
2163     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2164     /* assign asmops */
2165     aopOp(IC_LEFT(ic),ic,FALSE);
2166     aopOp(IC_RESULT(ic),ic,TRUE);
2167
2168     /* if both in bit space then special
2169     case */
2170     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2171         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2172
2173         emitpcode(POC_BCF,   popGet(AOP(IC_RESULT(ic)),0));
2174         emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2175         emitpcode(POC_BSF,   popGet(AOP(IC_RESULT(ic)),0));
2176
2177         goto release;
2178     }
2179
2180     optype = operandType(IC_LEFT(ic));
2181     rtype = operandType(IC_RESULT(ic));
2182
2183     /* if float then do float stuff */
2184     if (IS_FLOAT(optype)) {
2185         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2186         goto release;
2187     }
2188
2189     /* otherwise subtract from zero by taking the 2's complement */
2190     size = AOP_SIZE(IC_LEFT(ic));
2191
2192     for(i=0; i<size; i++) {
2193         if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2194             emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
2195         else {
2196             emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2197             emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2198         }
2199     }
2200
2201     emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
2202     for(i=1; i<size; i++) {
2203         emitSKPNZ;
2204         emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
2205     }
2206
2207 release:
2208     /* release the aops */
2209     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2210     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2211 }
2212
2213 /*-----------------------------------------------------------------*/
2214 /* saveRegisters - will look for a call and save the registers     */
2215 /*-----------------------------------------------------------------*/
2216 static void saveRegisters(iCode *lic)
2217 {
2218     int i;
2219     iCode *ic;
2220     bitVect *rsave;
2221     sym_link *dtype;
2222
2223     FENTRY;
2224
2225     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2226     /* look for call */
2227     for (ic = lic ; ic ; ic = ic->next)
2228         if (ic->op == CALL || ic->op == PCALL)
2229             break;
2230
2231         if (!ic) {
2232             fprintf(stderr,"found parameter push with no function call\n");
2233             return ;
2234         }
2235
2236         /* if the registers have been saved already then
2237         do nothing */
2238         if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2239             return ;
2240
2241             /* find the registers in use at this time
2242         and push them away to safety */
2243         rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2244             ic->rUsed);
2245
2246         ic->regsSaved = 1;
2247         if (options.useXstack) {
2248             if (bitVectBitValue(rsave,R0_IDX))
2249                 pic14_emitcode("mov","b,r0");
2250             pic14_emitcode("mov","r0,%s",spname);
2251             for (i = 0 ; i < pic14_nRegs ; i++) {
2252                 if (bitVectBitValue(rsave,i)) {
2253                     if (i == R0_IDX)
2254                         pic14_emitcode("mov","a,b");
2255                     else
2256                         pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2257                     pic14_emitcode("movx","@r0,a");
2258                     pic14_emitcode("inc","r0");
2259                 }
2260             }
2261             pic14_emitcode("mov","%s,r0",spname);
2262             if (bitVectBitValue(rsave,R0_IDX))
2263                 pic14_emitcode("mov","r0,b");
2264         }// else
2265         //for (i = 0 ; i < pic14_nRegs ; i++) {
2266         //    if (bitVectBitValue(rsave,i))
2267         //  pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2268         //}
2269
2270         dtype = operandType(IC_LEFT(ic));
2271         if (currFunc && dtype &&
2272             (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2273             IFFUNC_ISISR(currFunc->type) &&
2274             !ic->bankSaved)
2275
2276             saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2277
2278 }
2279 /*-----------------------------------------------------------------*/
2280 /* unsaveRegisters - pop the pushed registers                      */
2281 /*-----------------------------------------------------------------*/
2282 static void unsaveRegisters (iCode *ic)
2283 {
2284     int i;
2285     bitVect *rsave;
2286
2287     FENTRY;
2288
2289     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2290     /* find the registers in use at this time
2291     and push them away to safety */
2292     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2293         ic->rUsed);
2294
2295     if (options.useXstack) {
2296         pic14_emitcode("mov","r0,%s",spname);
2297         for (i =  pic14_nRegs ; i >= 0 ; i--) {
2298             if (bitVectBitValue(rsave,i)) {
2299                 pic14_emitcode("dec","r0");
2300                 pic14_emitcode("movx","a,@r0");
2301                 if (i == R0_IDX)
2302                     pic14_emitcode("mov","b,a");
2303                 else
2304                     pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2305             }
2306
2307         }
2308         pic14_emitcode("mov","%s,r0",spname);
2309         if (bitVectBitValue(rsave,R0_IDX))
2310             pic14_emitcode("mov","r0,b");
2311     } //else
2312     //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2313     //  if (bitVectBitValue(rsave,i))
2314     //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2315     //}
2316
2317 }
2318
2319
2320 /*-----------------------------------------------------------------*/
2321 /* pushSide -                */
2322 /*-----------------------------------------------------------------*/
2323 static void pushSide(operand * oper, int size)
2324 {
2325 #if 0
2326     int offset = 0;
2327     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2328     while (size--) {
2329         char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2330         if (AOP_TYPE(oper) != AOP_REG &&
2331             AOP_TYPE(oper) != AOP_DIR &&
2332             strcmp(l,"a") ) {
2333             pic14_emitcode("mov","a,%s",l);
2334             pic14_emitcode("push","acc");
2335         } else
2336             pic14_emitcode("push","%s",l);
2337     }
2338 #endif
2339 }
2340
2341 /*-----------------------------------------------------------------*/
2342 /* assignResultValue -               */
2343 /*-----------------------------------------------------------------*/
2344 static void assignResultValue(operand * oper)
2345 {
2346     int size = AOP_SIZE(oper);
2347     int offset = 0;
2348
2349     FENTRY;
2350
2351     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2352
2353     DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2354
2355     /* assign MSB first (passed via WREG) */
2356     while (size--) {
2357         get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2358         GpsuedoStkPtr++;
2359     }
2360 }
2361
2362
2363 /*-----------------------------------------------------------------*/
2364 /* genIpush - genrate code for pushing this gets a little complex  */
2365 /*-----------------------------------------------------------------*/
2366 static void genIpush (iCode *ic)
2367 {
2368     FENTRY;
2369
2370     DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2371 #if 0
2372     int size, offset = 0 ;
2373     char *l;
2374
2375
2376     /* if this is not a parm push : ie. it is spill push
2377     and spill push is always done on the local stack */
2378     if (!ic->parmPush) {
2379
2380         /* and the item is spilt then do nothing */
2381         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2382             return ;
2383
2384         aopOp(IC_LEFT(ic),ic,FALSE);
2385         size = AOP_SIZE(IC_LEFT(ic));
2386         /* push it on the stack */
2387         while(size--) {
2388             l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2389             if (*l == '#') {
2390                 MOVA(l);
2391                 l = "acc";
2392             }
2393             pic14_emitcode("push","%s",l);
2394         }
2395         return ;
2396     }
2397
2398     /* this is a paramter push: in this case we call
2399     the routine to find the call and save those
2400     registers that need to be saved */
2401     saveRegisters(ic);
2402
2403     /* then do the push */
2404     aopOp(IC_LEFT(ic),ic,FALSE);
2405
2406
2407     // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2408     size = AOP_SIZE(IC_LEFT(ic));
2409
2410     while (size--) {
2411         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2412         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2413             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2414             strcmp(l,"a") ) {
2415             pic14_emitcode("mov","a,%s",l);
2416             pic14_emitcode("push","acc");
2417         } else
2418             pic14_emitcode("push","%s",l);
2419     }
2420
2421     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2422 #endif
2423 }
2424
2425 /*-----------------------------------------------------------------*/
2426 /* genIpop - recover the registers: can happen only for spilling   */
2427 /*-----------------------------------------------------------------*/
2428 static void genIpop (iCode *ic)
2429 {
2430     FENTRY;
2431
2432     DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2433     assert (!"genIpop -- unimplemented");
2434 #if 0
2435     int size,offset ;
2436
2437
2438     /* if the temp was not pushed then */
2439     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2440         return ;
2441
2442     aopOp(IC_LEFT(ic),ic,FALSE);
2443     size = AOP_SIZE(IC_LEFT(ic));
2444     offset = (size-1);
2445     while (size--)
2446         pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2447         FALSE,TRUE));
2448
2449     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2450 #endif
2451 }
2452
2453 /*-----------------------------------------------------------------*/
2454 /* unsaverbank - restores the resgister bank from stack            */
2455 /*-----------------------------------------------------------------*/
2456 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2457 {
2458     FENTRY;
2459
2460     DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2461 #if 0
2462     int i;
2463     asmop *aop ;
2464     regs *r = NULL;
2465
2466     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2467     if (popPsw) {
2468         if (options.useXstack) {
2469             aop = newAsmop(0);
2470             r = getFreePtr(ic,&aop,FALSE);
2471
2472
2473             pic14_emitcode("mov","%s,_spx",r->name);
2474             pic14_emitcode("movx","a,@%s",r->name);
2475             pic14_emitcode("mov","psw,a");
2476             pic14_emitcode("dec","%s",r->name);
2477
2478         }else
2479             pic14_emitcode ("pop","psw");
2480     }
2481
2482     for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2483         if (options.useXstack) {
2484             pic14_emitcode("movx","a,@%s",r->name);
2485             //pic14_emitcode("mov","(%s+%d),a",
2486             //     regspic14[i].base,8*bank+regspic14[i].offset);
2487             pic14_emitcode("dec","%s",r->name);
2488
2489         } else
2490             pic14_emitcode("pop",""); //"(%s+%d)",
2491         //regspic14[i].base,8*bank); //+regspic14[i].offset);
2492     }
2493
2494     if (options.useXstack) {
2495
2496         pic14_emitcode("mov","_spx,%s",r->name);
2497         freeAsmop(NULL,aop,ic,TRUE);
2498
2499     }
2500 #endif
2501 }
2502
2503 /*-----------------------------------------------------------------*/
2504 /* saverbank - saves an entire register bank on the stack          */
2505 /*-----------------------------------------------------------------*/
2506 static void saverbank (int bank, iCode *ic, bool pushPsw)
2507 {
2508     FENTRY;
2509
2510     DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2511 #if 0
2512     int i;
2513     asmop *aop ;
2514     regs *r = NULL;
2515
2516     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2517     if (options.useXstack) {
2518
2519         aop = newAsmop(0);
2520         r = getFreePtr(ic,&aop,FALSE);
2521         pic14_emitcode("mov","%s,_spx",r->name);
2522
2523     }
2524
2525     for (i = 0 ; i < pic14_nRegs ;i++) {
2526         if (options.useXstack) {
2527             pic14_emitcode("inc","%s",r->name);
2528             //pic14_emitcode("mov","a,(%s+%d)",
2529             //       regspic14[i].base,8*bank+regspic14[i].offset);
2530             pic14_emitcode("movx","@%s,a",r->name);
2531         } else
2532             pic14_emitcode("push","");// "(%s+%d)",
2533         //regspic14[i].base,8*bank+regspic14[i].offset);
2534     }
2535
2536     if (pushPsw) {
2537         if (options.useXstack) {
2538             pic14_emitcode("mov","a,psw");
2539             pic14_emitcode("movx","@%s,a",r->name);
2540             pic14_emitcode("inc","%s",r->name);
2541             pic14_emitcode("mov","_spx,%s",r->name);
2542             freeAsmop (NULL,aop,ic,TRUE);
2543
2544         } else
2545             pic14_emitcode("push","psw");
2546
2547         pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2548     }
2549     ic->bankSaved = 1;
2550 #endif
2551 }
2552
2553 /*-----------------------------------------------------------------*/
2554 /* genCall - generates a call statement                            */
2555 /*-----------------------------------------------------------------*/
2556 static void genCall (iCode *ic)
2557 {
2558     sym_link *dtype;
2559     symbol *sym;
2560     char *name;
2561     int isExtern;
2562
2563     FENTRY;
2564
2565     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2566
2567     /* if caller saves & we have not saved then */
2568     if (!ic->regsSaved)
2569         saveRegisters(ic);
2570
2571         /* if we are calling a function that is not using
2572         the same register bank then we need to save the
2573     destination registers on the stack */
2574     dtype = operandType(IC_LEFT(ic));
2575     if (currFunc && dtype &&
2576         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2577         IFFUNC_ISISR(currFunc->type) &&
2578         !ic->bankSaved)
2579
2580         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2581
2582     /* if send set is not empty the assign */
2583     if (_G.sendSet) {
2584         iCode *sic;
2585         /* For the Pic port, there is no data stack.
2586         * So parameters passed to functions are stored
2587         * in registers. (The pCode optimizer will get
2588         * rid of most of these :).
2589         */
2590         int psuedoStkPtr=-1;
2591         int firstTimeThruLoop = 1;
2592
2593         _G.sendSet = reverseSet(_G.sendSet);
2594
2595         /* First figure how many parameters are getting passed */
2596         for (sic = setFirstItem(_G.sendSet) ; sic ;
2597         sic = setNextItem(_G.sendSet)) {
2598
2599             aopOp(IC_LEFT(sic),sic,FALSE);
2600             psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2601             freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2602         }
2603
2604         for (sic = setFirstItem(_G.sendSet) ; sic ;
2605         sic = setNextItem(_G.sendSet)) {
2606             int size, offset = 0;
2607
2608             aopOp(IC_LEFT(sic),sic,FALSE);
2609             size = AOP_SIZE(IC_LEFT(sic));
2610
2611             while (size--) {
2612                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2613                     AopType(AOP_TYPE(IC_LEFT(sic))));
2614
2615                 if(!firstTimeThruLoop) {
2616                     /* If this is not the first time we've been through the loop
2617                     * then we need to save the parameter in a temporary
2618                     * register. The last byte of the last parameter is
2619                     * passed in W. */
2620                     emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2621
2622                 }
2623                 firstTimeThruLoop=0;
2624
2625                 mov2w_op (IC_LEFT(sic),  offset);
2626                 offset++;
2627             }
2628             freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2629         }
2630         _G.sendSet = NULL;
2631     }
2632     /* make the call */
2633     sym = OP_SYMBOL(IC_LEFT(ic));
2634     name = sym->rname[0] ? sym->rname : sym->name;
2635     /*
2636      * As SDCC emits code as soon as it reaches the end of each
2637      * function's definition, prototyped functions that are implemented
2638      * after the current one are always considered EXTERN, which
2639      * introduces many unneccessary PAGESEL instructions.
2640      * XXX: Use a post pass to iterate over all `CALL _name' statements
2641      * and insert `PAGESEL _name' and `PAGESEL $' around the CALL
2642      * only iff there is no definition of the function in the whole
2643      * file (might include this in the PAGESEL pass).
2644      */
2645     isExtern = IS_EXTERN(sym->etype) || pic14_inISR;
2646     if (isExtern) {
2647         /* Extern functions and ISRs maybe on a different page;
2648          * must call pagesel */
2649         emitpcode(POC_PAGESEL,popGetWithString(name,1));
2650     }
2651     emitpcode(POC_CALL,popGetWithString(name,isExtern));
2652     if (isExtern) {
2653         /* May have returned from a different page;
2654          * must use pagesel to restore PCLATH before next
2655          * goto or call instruction */
2656         emitpcode(POC_PAGESEL,popGetWithString("$",0));
2657     }
2658     GpsuedoStkPtr=0;
2659     /* if we need assign a result value */
2660     if ((IS_ITEMP(IC_RESULT(ic)) &&
2661         (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2662         OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2663         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2664
2665         _G.accInUse++;
2666         aopOp(IC_RESULT(ic),ic,FALSE);
2667         _G.accInUse--;
2668
2669         assignResultValue(IC_RESULT(ic));
2670
2671         DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2672             AopType(AOP_TYPE(IC_RESULT(ic))));
2673
2674         freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2675     }
2676
2677     /* if register bank was saved then pop them */
2678     if (ic->bankSaved)
2679         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2680
2681     /* if we hade saved some registers then unsave them */
2682     if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2683         unsaveRegisters (ic);
2684
2685
2686 }
2687
2688 /*-----------------------------------------------------------------*/
2689 /* genPcall - generates a call by pointer statement                */
2690 /*-----------------------------------------------------------------*/
2691 static void genPcall (iCode *ic)
2692 {
2693     sym_link *dtype;
2694     symbol *albl = newiTempLabel(NULL);
2695     symbol *blbl = newiTempLabel(NULL);
2696     PIC_OPCODE poc;
2697     pCodeOp *pcop;
2698     operand *left;
2699
2700     FENTRY;
2701
2702     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2703     /* if caller saves & we have not saved then */
2704     if (!ic->regsSaved)
2705         saveRegisters(ic);
2706
2707         /* if we are calling a function that is not using
2708         the same register bank then we need to save the
2709     destination registers on the stack */
2710     dtype = operandType(IC_LEFT(ic));
2711     if (currFunc && dtype &&
2712         IFFUNC_ISISR(currFunc->type) &&
2713         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2714         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2715
2716     left = IC_LEFT(ic);
2717     aopOp(left,ic,FALSE);
2718     DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2719
2720     poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2721
2722     pushSide(IC_LEFT(ic), FPTRSIZE);
2723
2724     /* if send set is not empty, assign parameters */
2725     if (_G.sendSet) {
2726
2727         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2728         /* no way to pass args - W always gets used to make the call */
2729     }
2730     /* first idea - factor out a common helper function and call it.
2731     But don't know how to get it generated only once in its own block
2732
2733     if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2734         char *rname;
2735         char *buffer;
2736         rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2737         DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2738         buffer = Safe_calloc(1,strlen(rname)+16);
2739         sprintf(buffer, "%s_goto_helper", rname);
2740         addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2741         free(buffer);
2742     }
2743     */
2744     emitpcode(POC_CALL,popGetLabel(albl->key));
2745     pcop = popGetLabel(blbl->key);
2746     emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2747     emitpcode(POC_GOTO,pcop);
2748     emitpLabel(albl->key);
2749
2750     emitpcode(poc,popGetAddr(AOP(left),1,0));
2751     emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2752     emitpcode(poc,popGetAddr(AOP(left),0,0));
2753     emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2754
2755     emitpLabel(blbl->key);
2756
2757     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2758
2759     /* if we need to assign a result value */
2760     if ((IS_ITEMP(IC_RESULT(ic)) &&
2761         (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2762         OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2763         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2764
2765         _G.accInUse++;
2766         aopOp(IC_RESULT(ic),ic,FALSE);
2767         _G.accInUse--;
2768
2769         GpsuedoStkPtr = 0;
2770
2771         assignResultValue(IC_RESULT(ic));
2772
2773         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2774     }
2775
2776     /* if register bank was saved then unsave them */
2777     if (currFunc && dtype &&
2778         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2779         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2780
2781         /* if we hade saved some registers then
2782     unsave them */
2783     if (ic->regsSaved)
2784         unsaveRegisters (ic);
2785
2786 }
2787
2788 /*-----------------------------------------------------------------*/
2789 /* resultRemat - result  is rematerializable                       */
2790 /*-----------------------------------------------------------------*/
2791 static int resultRemat (iCode *ic)
2792 {
2793     //  DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2794     FENTRY;
2795
2796     if (SKIP_IC(ic) || ic->op == IFX)
2797         return 0;
2798
2799     if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2800         symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2801         if (sym->remat && !POINTER_SET(ic))
2802             return 1;
2803     }
2804
2805     return 0;
2806 }
2807
2808 #if 0
2809 /*-----------------------------------------------------------------*/
2810 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2811 /*-----------------------------------------------------------------*/
2812 static bool inExcludeList(char *s)
2813 {
2814     DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2815     int i =0;
2816
2817     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2818     if (options.excludeRegs[i] &&
2819         STRCASECMP(options.excludeRegs[i],"none") == 0)
2820         return FALSE ;
2821
2822     for ( i = 0 ; options.excludeRegs[i]; i++) {
2823         if (options.excludeRegs[i] &&
2824             STRCASECMP(s,options.excludeRegs[i]) == 0)
2825             return TRUE;
2826     }
2827     return FALSE ;
2828 }
2829 #endif
2830
2831 /*-----------------------------------------------------------------*/
2832 /* genFunction - generated code for function entry                 */
2833 /*-----------------------------------------------------------------*/
2834 static void genFunction (iCode *ic)
2835 {
2836     symbol *sym;
2837     sym_link *ftype;
2838
2839     FENTRY;
2840
2841     DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2842
2843     labelOffset += (max_key+4);
2844     max_key=0;
2845     GpsuedoStkPtr=0;
2846     _G.nRegsSaved = 0;
2847     /* create the function header */
2848     pic14_emitcode(";","-----------------------------------------");
2849     pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2850     pic14_emitcode(";","-----------------------------------------");
2851
2852     /* prevent this symbol from being emitted as 'extern' */
2853     pic14_stringInSet(sym->rname, &pic14_localFunctions, 1);
2854
2855     pic14_emitcode("","%s:",sym->rname);
2856     addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2857
2858     /* mark symbol as NOT extern (even if it was declared so previously) */
2859     assert(IS_SPEC(sym->etype));
2860     SPEC_EXTR(sym->etype) = 0;
2861     sym->cdef = 0;
2862     if (!SPEC_OCLS(sym->etype)) SPEC_OCLS(sym->etype) = code;
2863     addSetIfnotP(&SPEC_OCLS(sym->etype)->syms, sym);
2864
2865     ftype = operandType(IC_LEFT(ic));
2866
2867     /* if critical function then turn interrupts off */
2868     if (IFFUNC_ISCRITICAL(ftype))
2869         pic14_emitcode("clr","ea");
2870
2871         /* here we need to generate the equates for the
2872     register bank if required */
2873 #if 0
2874     if (FUNC_REGBANK(ftype) != rbank) {
2875         int i ;
2876
2877         rbank = FUNC_REGBANK(ftype);
2878         for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2879             if (strcmp(regspic14[i].base,"0") == 0)
2880                 pic14_emitcode("","%s = 0x%02x",
2881                 regspic14[i].dname,
2882                 8*rbank+regspic14[i].offset);
2883             else
2884                 pic14_emitcode ("","%s = %s + 0x%02x",
2885                 regspic14[i].dname,
2886                 regspic14[i].base,
2887                 8*rbank+regspic14[i].offset);
2888         }
2889     }
2890 #endif
2891
2892     /* if this is an interrupt service routine */
2893     pic14_inISR = 0;
2894     if (IFFUNC_ISISR(sym->type)) {
2895         pic14_inISR = 1;
2896         emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2897         emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2898         /* XXX: Why? Does this assume that ssave and psave reside
2899          * in a shared bank or bank0? We cannot guarantee the
2900          * latter...
2901          */
2902         emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2903         emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2904         //emitpcode(POC_MOVWF,  popGetExternal("___sdcc_saved_status",1 ));
2905         emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2906         /* during an interrupt PCLATH must be cleared before a goto or call statement */
2907         emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));
2908         emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2909         //emitpcode(POC_MOVWF,  popGetExternal("___sdcc_saved_pclath", 1));
2910         emitpcode(POC_MOVFW,  popCopyReg(&pc_fsr));
2911         emitpcode(POC_MOVWF,  popGetExternal("___sdcc_saved_fsr", 1));
2912
2913         pBlockConvert2ISR(pb);
2914         pic14_hasInterrupt = 1;
2915     } else {
2916     /* if callee-save to be used for this function
2917         then save the registers being used in this function */
2918         if (IFFUNC_CALLEESAVES(sym->type)) {
2919             int i;
2920
2921             /* if any registers used */
2922             if (sym->regsUsed) {
2923                 /* save the registers used */
2924                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2925                     if (bitVectBitValue(sym->regsUsed,i) ||
2926                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2927                         //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2928                         _G.nRegsSaved++;
2929                     }
2930                 }
2931             }
2932         }
2933     }
2934
2935     /* set the register bank to the desired value */
2936     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2937         pic14_emitcode("push","psw");
2938         pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);
2939     }
2940
2941     if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2942
2943         if (options.useXstack) {
2944             pic14_emitcode("mov","r0,%s",spname);
2945             pic14_emitcode("mov","a,_bp");
2946             pic14_emitcode("movx","@r0,a");
2947             pic14_emitcode("inc","%s",spname);
2948         }
2949         else
2950         {
2951             /* set up the stack */
2952             pic14_emitcode ("push","_bp");   /* save the callers stack  */
2953         }
2954         pic14_emitcode ("mov","_bp,%s",spname);
2955     }
2956
2957     /* adjust the stack for the function */
2958     if (sym->stack) {
2959
2960         int i = sym->stack;
2961         if (i > 256 )
2962             werror(W_STACK_OVERFLOW,sym->name);
2963
2964         if (i > 3 && sym->recvSize < 4) {
2965
2966             pic14_emitcode ("mov","a,sp");
2967             pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2968             pic14_emitcode ("mov","sp,a");
2969
2970         }
2971         else
2972             while(i--)
2973                 pic14_emitcode("inc","sp");
2974     }
2975
2976     if (sym->xstack) {
2977
2978         pic14_emitcode ("mov","a,_spx");
2979         pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2980         pic14_emitcode ("mov","_spx,a");
2981     }
2982
2983 }
2984
2985 /*-----------------------------------------------------------------*/
2986 /* genEndFunction - generates epilogue for functions               */
2987 /*-----------------------------------------------------------------*/
2988 static void genEndFunction (iCode *ic)
2989 {
2990     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2991
2992     FENTRY;
2993
2994     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2995
2996     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2997     {
2998         pic14_emitcode ("mov","%s,_bp",spname);
2999     }
3000
3001     /* if use external stack but some variables were
3002     added to the local stack then decrement the
3003     local stack */
3004     if (options.useXstack && sym->stack) {
3005         pic14_emitcode("mov","a,sp");
3006         pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3007         pic14_emitcode("mov","sp,a");
3008     }
3009
3010
3011     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3012         if (options.useXstack) {
3013             pic14_emitcode("mov","r0,%s",spname);
3014             pic14_emitcode("movx","a,@r0");
3015             pic14_emitcode("mov","_bp,a");
3016             pic14_emitcode("dec","%s",spname);
3017         }
3018         else
3019         {
3020             pic14_emitcode ("pop","_bp");
3021         }
3022     }
3023
3024     /* restore the register bank    */
3025     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3026         pic14_emitcode ("pop","psw");
3027
3028     if (IFFUNC_ISISR(sym->type)) {
3029
3030         /* now we need to restore the registers */
3031         /* if this isr has no bank i.e. is going to
3032         run with bank 0 , then we need to save more
3033 registers :-) */
3034         if (!FUNC_REGBANK(sym->type)) {
3035
3036         /* if this function does not call any other
3037         function then we can be economical and
3038             save only those registers that are used */
3039             if (! IFFUNC_HASFCALL(sym->type)) {
3040                 int i;
3041
3042                 /* if any registers used */
3043                 if (sym->regsUsed) {
3044                     /* save the registers used */
3045                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3046                         if (bitVectBitValue(sym->regsUsed,i) ||
3047                             (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3048                             pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3049                     }
3050                 }
3051
3052             } else {
3053             /* this function has    a function call cannot
3054             determines register usage so we will have the
3055                 entire bank */
3056                 unsaverbank(0,ic,FALSE);
3057             }
3058         }
3059
3060         /* if debug then send end of function */
3061         if (options.debug && debugFile && currFunc) {
3062             debugFile->writeEndFunction (currFunc, ic, 1);
3063         }
3064
3065         emitpcode(POC_MOVFW,  popGetExternal("___sdcc_saved_fsr", 1));
3066         emitpcode(POC_MOVWF,  popCopyReg(&pc_fsr));
3067         //emitpcode(POC_MOVFW,  popGetExternal("___sdcc_saved_pclath", 1));
3068         emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
3069         emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
3070         emitpcode(POC_CLRF,   popCopyReg(&pc_status)); // see genFunction
3071         //emitpcode(POC_SWAPFW, popGetExternal("___sdcc_saved_status", 1));
3072         emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3073         emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
3074         emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
3075         emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3076         addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3077         emitpcodeNULLop(POC_RETFIE);
3078     }
3079     else {
3080         if (IFFUNC_ISCRITICAL(sym->type))
3081             pic14_emitcode("setb","ea");
3082
3083         if (IFFUNC_CALLEESAVES(sym->type)) {
3084             int i;
3085
3086             /* if any registers used */
3087             if (sym->regsUsed) {
3088                 /* save the registers used */
3089                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3090                     if (bitVectBitValue(sym->regsUsed,i) ||
3091                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3092                         pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3093                 }
3094             }
3095
3096         }
3097
3098         /* if debug then send end of function */
3099         if (options.debug && debugFile && currFunc) {
3100             debugFile->writeEndFunction (currFunc, ic, 1);
3101         }
3102
3103         pic14_emitcode ("return","");
3104         emitpcodeNULLop(POC_RETURN);
3105
3106         /* Mark the end of a function */
3107         addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3108     }
3109
3110 }
3111
3112 /*-----------------------------------------------------------------*/
3113 /* genRet - generate code for return statement                     */
3114 /*-----------------------------------------------------------------*/
3115 static void genRet (iCode *ic)
3116 {
3117     int size,offset = 0;
3118
3119     FENTRY;
3120
3121     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3122     /* if we have no return value then
3123     just generate the "ret" */
3124     if (!IC_LEFT(ic))
3125         goto jumpret;
3126
3127         /* we have something to return then
3128     move the return value into place */
3129     aopOp(IC_LEFT(ic),ic,FALSE);
3130     size = AOP_SIZE(IC_LEFT(ic));
3131
3132     for (offset = 0; offset < size; offset++)
3133     {
3134         pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3135     }
3136
3137     freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3138
3139 jumpret:
3140     /* generate a jump to the return label
3141     if the next is not the return statement */
3142     if (!(ic->next && ic->next->op == LABEL &&
3143         IC_LABEL(ic->next) == returnLabel)) {
3144
3145         emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3146     }
3147
3148 }
3149
3150 /*-----------------------------------------------------------------*/
3151 /* genLabel - generates a label                                    */
3152 /*-----------------------------------------------------------------*/
3153 static void genLabel (iCode *ic)
3154 {
3155     FENTRY;
3156
3157     /* special case never generate */
3158     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3159     if (IC_LABEL(ic) == entryLabel)
3160         return ;
3161
3162     emitpLabel(IC_LABEL(ic)->key);
3163     pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3164 }
3165
3166 /*-----------------------------------------------------------------*/
3167 /* genGoto - generates a goto                                      */
3168 /*-----------------------------------------------------------------*/
3169 //tsd
3170 static void genGoto (iCode *ic)
3171 {
3172     FENTRY;
3173
3174     emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3175     pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3176 }
3177
3178
3179 /*-----------------------------------------------------------------*/
3180 /* genMultbits :- multiplication of bits                           */
3181 /*-----------------------------------------------------------------*/
3182 static void genMultbits (operand *left,
3183                          operand *right,
3184                          operand *result)
3185 {
3186     FENTRY;
3187     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3188
3189     if(!pic14_sameRegs(AOP(result),AOP(right)))
3190         emitpcode(POC_BSF,  popGet(AOP(result),0));
3191
3192     emitpcode(POC_BTFSC,popGet(AOP(right),0));
3193     emitpcode(POC_BTFSS,popGet(AOP(left),0));
3194     emitpcode(POC_BCF,  popGet(AOP(result),0));
3195
3196 }
3197
3198
3199 /*-----------------------------------------------------------------*/
3200 /* genMultOneByte : 8 bit multiplication & division                */
3201 /*-----------------------------------------------------------------*/
3202 static void genMultOneByte (operand *left,
3203                             operand *right,
3204                             operand *result)
3205 {
3206     char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3207
3208     // symbol *lbl ;
3209     int size,offset,i;
3210
3211
3212     FENTRY;
3213
3214     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3215     DEBUGpic14_AopType(__LINE__,left,right,result);
3216     DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3217
3218     /* (if two literals, the value is computed before) */
3219     /* if one literal, literal on the right */
3220     if (AOP_TYPE(left) == AOP_LIT){
3221         operand *t = right;
3222         right = left;
3223         left = t;
3224     }
3225
3226     assert (AOP_SIZE(left) == AOP_SIZE(right));
3227
3228     size = min(AOP_SIZE(result),AOP_SIZE(left));
3229     offset = Gstack_base_addr - (2*size - 1);
3230
3231     /* pass right operand as argument */
3232     for (i=0; i < size; i++)
3233     {
3234         mov2w (AOP(right), i);
3235         emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3236     } // for
3237
3238     /* pass left operand as argument */
3239     for (i=0; i < size; i++)
3240     {
3241         mov2w (AOP(left), i);
3242         if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3243     } // for
3244     assert (offset == Gstack_base_addr);
3245
3246     /* call library routine */
3247     assert (size > 0 && size <= 4);
3248     call_libraryfunc (func[size]);
3249
3250     /* assign result */
3251     movwf (AOP(result), size-1);
3252     for (i=0; i < size - 1; i++)
3253     {
3254         emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3255         movwf (AOP(result), size - 2 - i);
3256     } // for
3257
3258     /* now (zero-/sign) extend the result to its size */
3259     addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3260 }
3261
3262 /*-----------------------------------------------------------------*/
3263 /* genMult - generates code for multiplication                     */
3264 /*-----------------------------------------------------------------*/
3265 static void genMult (iCode *ic)
3266 {
3267     operand *left = IC_LEFT(ic);
3268     operand *right = IC_RIGHT(ic);
3269     operand *result= IC_RESULT(ic);
3270
3271     FENTRY;
3272
3273     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3274     /* assign the amsops */
3275     aopOp (left,ic,FALSE);
3276     aopOp (right,ic,FALSE);
3277     aopOp (result,ic,TRUE);
3278
3279     DEBUGpic14_AopType(__LINE__,left,right,result);
3280
3281     /* special cases first */
3282     /* both are bits */
3283     if (AOP_TYPE(left) == AOP_CRY &&
3284         AOP_TYPE(right)== AOP_CRY) {
3285         genMultbits(left,right,result);
3286         goto release ;
3287     }
3288
3289     /* if both are of size == 1 */
3290     if (AOP_SIZE(left) == 1 &&
3291         AOP_SIZE(right) == 1 ) {
3292         genMultOneByte(left,right,result);
3293         goto release ;
3294     }
3295
3296     /* should have been converted to function call */
3297     assert(0) ;
3298
3299 release :
3300     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3301     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3302     freeAsmop(result,NULL,ic,TRUE);
3303 }
3304
3305 /*-----------------------------------------------------------------*/
3306 /* genDivbits :- division of bits                                  */
3307 /*-----------------------------------------------------------------*/
3308 static void genDivbits (operand *left,
3309                         operand *right,
3310                         operand *result)
3311 {
3312
3313     char *l;
3314
3315     FENTRY;
3316
3317     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3318     /* the result must be bit */
3319     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3320     l = aopGet(AOP(left),0,FALSE,FALSE);
3321
3322     MOVA(l);
3323
3324     pic14_emitcode("div","ab");
3325     pic14_emitcode("rrc","a");
3326     aopPut(AOP(result),"c",0);
3327 }
3328
3329 /*-----------------------------------------------------------------*/
3330 /* genDivOneByte : 8 bit division                                  */
3331 /*-----------------------------------------------------------------*/
3332 static void genDivOneByte (operand *left,
3333                            operand *right,
3334                            operand *result)
3335 {
3336     int size;
3337     int sign;
3338
3339     FENTRY;
3340     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3341
3342     assert (AOP_SIZE(right) == 1);
3343     assert (AOP_SIZE(left) == 1);
3344
3345     size = min(AOP_SIZE(result),AOP_SIZE(left));
3346     sign = !(SPEC_USIGN(operandType(left))
3347         && SPEC_USIGN(operandType(right)));
3348
3349     if (AOP_TYPE(right) == AOP_LIT)
3350     {
3351         /* XXX: might add specialized code */
3352     }
3353
3354     if (!sign)
3355     {
3356         /* unsigned division */
3357     #if 1
3358         mov2w(AOP(right),0);
3359         emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3360         mov2w(AOP(left),0);
3361         call_libraryfunc("__divuchar");
3362         movwf(AOP(result),0);
3363     #else
3364         pCodeOp *temp;
3365         symbol *lbl;
3366
3367         temp = popGetTempReg();
3368         lbl = newiTempLabel(NULL);
3369
3370         /* XXX: improve this naive approach:
3371            [result] = [a] / [b]
3372             ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3373
3374            In PIC assembler:
3375            movf  left,W
3376            movwf temp       // temp <-- left
3377            movf  right,W    // W <-- right
3378            clrf  result
3379            label1:
3380            incf  result
3381            subwf temp,F     // temp <-- temp - W
3382            skipNC       // subwf clears CARRY (i.e. sets BORROW) if temp < W
3383            goto  label1
3384            decf result      // we just subtract once too often
3385          */
3386
3387         /* XXX: This loops endlessly on DIVIDE BY ZERO */
3388         /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3389
3390         mov2w(AOP(left),0);
3391         emitpcode(POC_MOVWF, temp);
3392         mov2w(AOP(right),0);
3393         emitpcode(POC_CLRF, popGet(AOP(result),0));
3394
3395         emitpLabel(lbl->key);
3396         emitpcode(POC_INCF, popGet(AOP(result),0));
3397         emitpcode(POC_SUBWF, temp);
3398         emitSKPNC;
3399         emitpcode(POC_GOTO, popGetLabel(lbl->key));
3400         emitpcode(POC_DECF, popGet(AOP(result),0));
3401         popReleaseTempReg(temp);
3402     #endif
3403     }
3404     else
3405     {
3406         /* signed division */
3407         mov2w(AOP(right),0);
3408         emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3409         mov2w(AOP(left),0);
3410         call_libraryfunc("__divschar");
3411         movwf(AOP(result),0);
3412     }
3413
3414     /* now performed the signed/unsigned division -- extend result */
3415     addSign(result, 1, sign);
3416 }
3417
3418 /*-----------------------------------------------------------------*/
3419 /* genDiv - generates code for division                */
3420 /*-----------------------------------------------------------------*/
3421 static void genDiv (iCode *ic)
3422 {
3423     operand *left = IC_LEFT(ic);
3424     operand *right = IC_RIGHT(ic);
3425     operand *result= IC_RESULT(ic);
3426
3427     FENTRY;
3428     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3429     /* assign the amsops */
3430     aopOp (left,ic,FALSE);
3431     aopOp (right,ic,FALSE);
3432     aopOp (result,ic,TRUE);
3433
3434     /* special cases first */
3435     /* both are bits */
3436     if (AOP_TYPE(left) == AOP_CRY &&
3437         AOP_TYPE(right)== AOP_CRY) {
3438         genDivbits(left,right,result);
3439         goto release ;
3440     }
3441
3442     /* if both are of size == 1 */
3443     if (AOP_SIZE(left) == 1 &&
3444         AOP_SIZE(right) == 1 ) {
3445         genDivOneByte(left,right,result);
3446         goto release ;
3447     }
3448
3449     /* should have been converted to function call */
3450     assert(0);
3451 release :
3452     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3453     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3454     freeAsmop(result,NULL,ic,TRUE);
3455 }
3456
3457 /*-----------------------------------------------------------------*/
3458 /* genModOneByte : 8 bit modulus                                   */
3459 /*-----------------------------------------------------------------*/
3460 static void genModOneByte (operand *left,
3461                            operand *right,
3462                            operand *result)
3463 {
3464     int size;
3465     int sign;
3466
3467     FENTRY;
3468     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3469
3470     assert (AOP_SIZE(right) == 1);
3471     assert (AOP_SIZE(left) == 1);
3472
3473     size = min(AOP_SIZE(result),AOP_SIZE(left));
3474     sign = !(SPEC_USIGN(operandType(left))
3475         && SPEC_USIGN(operandType(right)));
3476
3477     if (AOP_TYPE(right) == AOP_LIT)
3478     {
3479         /* XXX: might add specialized code */
3480     }
3481
3482     if (!sign)
3483     {
3484         /* unsigned division */
3485     #if 1
3486         mov2w(AOP(right),0);
3487         emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3488         mov2w(AOP(left),0);
3489         call_libraryfunc("__moduchar");
3490         movwf(AOP(result),0);
3491     #else
3492         pCodeOp *temp;
3493         symbol *lbl;
3494
3495         lbl = newiTempLabel(NULL);
3496
3497         assert(!pic14_sameRegs(AOP(right),AOP(result)));
3498
3499         /* XXX: improve this naive approach:
3500            [result] = [a] % [b]
3501             ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3502
3503            In PIC assembler:
3504            movf  left,W
3505            movwf result     // result <-- left
3506            movf  right,W    // W <-- right
3507            label1:
3508            subwf result,F   // result <-- result - W
3509            skipNC       // subwf clears CARRY (i.e. sets BORROW) if result < W
3510            goto  label1
3511            addwf result, F  // we just subtract once too often
3512          */
3513
3514         /* XXX: This loops endlessly on DIVIDE BY ZERO */
3515         /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3516
3517         if (!pic14_sameRegs(AOP(left), AOP(result)))
3518         {
3519             mov2w(AOP(left),0);
3520             emitpcode(POC_MOVWF, popGet(AOP(result),0));
3521         }
3522         mov2w(AOP(right),0);
3523
3524         emitpLabel(lbl->key);
3525         emitpcode(POC_SUBWF, popGet(AOP(result),0));
3526         emitSKPNC;
3527         emitpcode(POC_GOTO, popGetLabel(lbl->key));
3528         emitpcode(POC_ADDWF, popGet(AOP(result),0));
3529     #endif
3530     }
3531     else
3532     {
3533         /* signed division */
3534         mov2w(AOP(right),0);
3535         emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3536         mov2w(AOP(left),0);
3537         call_libraryfunc("__modschar");
3538         movwf(AOP(result),0);
3539     }
3540
3541     /* now we performed the signed/unsigned modulus -- extend result */
3542     addSign(result, 1, sign);
3543 }
3544
3545 /*-----------------------------------------------------------------*/
3546 /* genMod - generates code for division                            */
3547 /*-----------------------------------------------------------------*/
3548 static void genMod (iCode *ic)
3549 {
3550     operand *left = IC_LEFT(ic);
3551     operand *right = IC_RIGHT(ic);
3552     operand *result= IC_RESULT(ic);
3553
3554     FENTRY;
3555     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3556     /* assign the amsops */
3557     aopOp (left,ic,FALSE);
3558     aopOp (right,ic,FALSE);
3559     aopOp (result,ic,TRUE);
3560
3561     /* if both are of size == 1 */
3562     if (AOP_SIZE(left) == 1 &&
3563         AOP_SIZE(right) == 1 ) {
3564         genModOneByte(left,right,result);
3565         goto release ;
3566     }
3567
3568     /* should have been converted to function call */
3569     assert(0);
3570
3571 release :
3572     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3573     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3574     freeAsmop(result,NULL,ic,TRUE);
3575 }
3576
3577 /*-----------------------------------------------------------------*/
3578 /* genIfxJump :- will create a jump depending on the ifx           */
3579 /*-----------------------------------------------------------------*/
3580 /*
3581 note: May need to add parameter to indicate when a variable is in bit space.
3582 */
3583 static void genIfxJump (iCode *ic, char *jval)
3584 {
3585
3586     FENTRY;
3587     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3588     /* if true label then we jump if condition
3589     supplied is true */
3590     if ( IC_TRUE(ic) ) {
3591
3592         if(strcmp(jval,"a") == 0)
3593             emitSKPZ;
3594         else if (strcmp(jval,"c") == 0)
3595             emitSKPC;
3596         else {
3597             DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3598             emitpcode(POC_BTFSC,    newpCodeOpBit(jval,-1,1));
3599         }
3600
3601         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3602         pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3603
3604     }
3605     else {
3606         /* false label is present */
3607         if(strcmp(jval,"a") == 0)
3608             emitSKPNZ;
3609         else if (strcmp(jval,"c") == 0)
3610             emitSKPNC;
3611         else {
3612             DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3613             emitpcode(POC_BTFSS,    newpCodeOpBit(jval,-1,1));
3614         }
3615
3616         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3617         pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3618
3619     }
3620
3621
3622     /* mark the icode as generated */
3623     ic->generated = 1;
3624 }
3625
3626 #if 0
3627 /*-----------------------------------------------------------------*/
3628 /* genSkip                                                         */
3629 /*-----------------------------------------------------------------*/
3630 static void genSkip(iCode *ifx,int status_bit)
3631 {
3632     FENTRY;
3633     if(!ifx)
3634         return;
3635
3636     if ( IC_TRUE(ifx) ) {
3637         switch(status_bit) {
3638         case 'z':
3639             emitSKPNZ;
3640             break;
3641
3642         case 'c':
3643             emitSKPNC;
3644             break;
3645
3646         case 'd':
3647             emitSKPDC;
3648             break;
3649
3650         }
3651
3652         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3653         pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3654
3655     } else {
3656
3657         switch(status_bit) {
3658
3659         case 'z':
3660             emitSKPZ;
3661             break;
3662
3663         case 'c':
3664             emitSKPC;
3665             break;
3666
3667         case 'd':
3668             emitSKPDC;
3669             break;
3670         }
3671         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3672         pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3673
3674     }
3675
3676 }
3677 #endif
3678
3679 /*-----------------------------------------------------------------*/
3680 /* genSkipc                                                        */
3681 /*-----------------------------------------------------------------*/
3682 static void genSkipc(resolvedIfx *rifx)
3683 {
3684     FENTRY;
3685     if(!rifx)
3686         return;
3687
3688     if(rifx->condition)
3689         emitSKPNC;
3690     else
3691         emitSKPC;
3692
3693     emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3694     emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3695     rifx->generated = 1;
3696 }
3697
3698 #if 0
3699 /*-----------------------------------------------------------------*/
3700 /* genSkipz2                                                       */
3701 /*-----------------------------------------------------------------*/
3702 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3703 {
3704     FENTRY;
3705     if(!rifx)
3706         return;
3707
3708     if( (rifx->condition ^ invert_condition) & 1)
3709         emitSKPZ;
3710     else
3711         emitSKPNZ;
3712
3713     emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3714     rifx->generated = 1;
3715 }
3716 #endif
3717
3718 #if 0
3719 /*-----------------------------------------------------------------*/
3720 /* genSkipz                                                        */
3721 /*-----------------------------------------------------------------*/
3722 static void genSkipz(iCode *ifx, int condition)
3723 {
3724     FENTRY;
3725     assert (ifx != NULL);
3726
3727     if(condition)
3728         emitSKPNZ;
3729     else
3730         emitSKPZ;
3731
3732     if ( IC_TRUE(ifx) )
3733         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3734     else
3735         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3736
3737     if ( IC_TRUE(ifx) )
3738         pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3739     else
3740         pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3741
3742 }
3743 #endif
3744
3745 #if 0
3746 /*-----------------------------------------------------------------*/
3747 /* genSkipCond                                                     */
3748 /*-----------------------------------------------------------------*/
3749 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3750 {
3751     FENTRY;
3752     if(!rifx)
3753         return;
3754
3755     if(rifx->condition)
3756         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3757     else
3758         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3759
3760
3761     emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3762     rifx->generated = 1;
3763 }
3764 #endif
3765
3766 #if 0
3767 /*-----------------------------------------------------------------*/
3768 /* genChkZeroes :- greater or less than comparison                 */
3769 /*     For each byte in a literal that is zero, inclusive or the   */
3770 /*     the corresponding byte in the operand with W                */
3771 /*     returns true if any of the bytes are zero                   */
3772 /*-----------------------------------------------------------------*/
3773 static int genChkZeroes(operand *op, int lit,  int size)
3774 {
3775
3776     int i;
3777     int flag =1;
3778
3779     while(size--) {
3780         i = (lit >> (size*8)) & 0xff;
3781
3782         if(i==0) {
3783             if(flag)
3784                 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3785             else
3786                 emitpcode(POC_IORFW, popGet(AOP(op),size));
3787             flag = 0;
3788         }
3789     }
3790
3791     return (flag==0);
3792 }
3793 #endif
3794
3795
3796 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3797 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
3798 #define DEBUGpc           emitpComment
3799
3800 /*-----------------------------------------------------------------*/
3801 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
3802 /*                  aop (if it's NOT a literal) or from lit (if    */
3803 /*                  aop is a literal)                              */
3804 /*-----------------------------------------------------------------*/
3805 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3806   if (aop->type == AOP_LIT) {
3807     emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3808   } else {
3809     emitpcode (POC_MOVFW, popGet (aop, offset));
3810   }
3811 }
3812
3813 /* genCmp performs a left < right comparison, stores
3814  * the outcome in result (if != NULL) and generates
3815  * control flow code for the ifx (if != NULL).
3816  *
3817  * This version leaves in sequences like
3818  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3819  * which should be optmized by the peephole
3820  * optimizer - RN 2005-01-01 */
3821 static void genCmp (operand *left,operand *right,
3822                     operand *result, iCode *ifx, int sign)
3823 {
3824   resolvedIfx rIfx;
3825   int size;
3826   int offs;
3827   symbol *templbl;
3828   operand *dummy;
3829   unsigned long lit;
3830   unsigned long mask;
3831   int performedLt;
3832   int invert_result = 0;
3833
3834   FENTRY;
3835
3836   assert (AOP_SIZE(left) == AOP_SIZE(right));
3837   assert (left && right);
3838
3839   size = AOP_SIZE(right) - 1;
3840   mask = (0x100UL << (size*8)) - 1;
3841   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3842   performedLt = 1;
3843   templbl = NULL;
3844   lit = 0;
3845
3846   resolveIfx (&rIfx, ifx);
3847
3848   /**********************************************************************
3849    * handle bits - bit compares are promoted to int compares seemingly! *
3850    **********************************************************************/
3851 #if 0
3852   // THIS IS COMPLETELY UNTESTED!
3853   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3854     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3855     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3856     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3857
3858     emitSETC;
3859     // 1 < {0,1} is false --> clear C by skipping the next instruction
3860     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3861     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3862     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3863     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3864     emitCLRC; // only skipped for left=0 && right=1
3865
3866     goto correct_result_in_carry;
3867   } // if
3868 #endif
3869
3870   /*************************************************
3871    * make sure that left is register (or the like) *
3872    *************************************************/
3873   if (!isAOP_REGlike(left)) {
3874     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3875     assert (isAOP_LIT(left));
3876     assert (isAOP_REGlike(right));
3877     // swap left and right
3878     // left < right <==> right > left <==> (right >= left + 1)
3879     lit = ulFromVal(AOP(left)->aopu.aop_lit);
3880
3881     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
3882       // MAXVALUE < right? always false
3883       if (performedLt) emitCLRC; else emitSETC;
3884       goto correct_result_in_carry;
3885     } // if
3886
3887     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
3888     // that's why we handled it above.
3889     lit++;
3890
3891     dummy = left;
3892     left = right;
3893     right = dummy;
3894
3895     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
3896   } else if (isAOP_LIT(right)) {
3897     lit = ulFromVal(AOP(right)->aopu.aop_lit);
3898   } // if
3899
3900   assert (isAOP_REGlike(left)); // left must be register or the like
3901   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
3902
3903   /*************************************************
3904    * special cases go here                         *
3905    *************************************************/
3906
3907   if (isAOP_LIT(right)) {
3908     if (!sign) {
3909       // unsigned comparison to a literal
3910       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
3911       if (lit == 0) {
3912     // unsigned left < 0? always false
3913     if (performedLt) emitCLRC; else emitSETC;
3914     goto correct_result_in_carry;
3915       }
3916     } else {
3917       // signed comparison to a literal
3918       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
3919       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
3920     // signed left < 0x80000000? always false
3921     if (performedLt) emitCLRC; else emitSETC;
3922     goto correct_result_in_carry;
3923       } else if (lit == 0) {
3924     // compare left < 0; set CARRY if SIGNBIT(left) is set
3925     if (performedLt) emitSETC; else emitCLRC;
3926     emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
3927     if (performedLt) emitCLRC; else emitSETC;
3928     goto correct_result_in_carry;
3929       }
3930     } // if (!sign)
3931   } // right is literal
3932
3933   /*************************************************
3934    * perform a general case comparison             *
3935    * make sure we get CARRY==1 <==> left >= right  *
3936    *************************************************/
3937   // compare most significant bytes
3938   //DEBUGpc ("comparing bytes at offset %d", size);
3939   if (!sign) {
3940     // unsigned comparison
3941     pic14_mov2w_regOrLit (AOP(right), lit, size);
3942     emitpcode (POC_SUBFW, popGet (AOP(left), size));
3943   } else {
3944     // signed comparison
3945     // (add 2^n to both operands then perform an unsigned comparison)
3946     if (isAOP_LIT(right)) {
3947       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
3948       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
3949
3950       if (litbyte == 0x80) {
3951     // left >= 0x80 -- always true, but more bytes to come
3952     mov2w (AOP(left), size);
3953     emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
3954     emitSETC;
3955       } else {
3956     // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
3957     mov2w (AOP(left), size);
3958     emitpcode (POC_ADDLW, popGetLit (0x80));
3959     emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
3960       } // if
3961     } else {
3962       pCodeOp *pctemp = popGetTempReg();
3963       mov2w (AOP(left), size);
3964       emitpcode (POC_ADDLW, popGetLit (0x80));
3965       emitpcode (POC_MOVWF, pctemp);
3966       mov2w (AOP(right), size);
3967       emitpcode (POC_ADDLW, popGetLit (0x80));
3968       emitpcode (POC_SUBFW, pctemp);
3969       popReleaseTempReg(pctemp);
3970     }
3971   } // if (!sign)
3972
3973   // compare remaining bytes (treat as unsigned case from above)
3974   templbl = newiTempLabel ( NULL );
3975   offs = size;
3976   while (offs--) {
3977     //DEBUGpc ("comparing bytes at offset %d", offs);
3978     emitSKPZ;
3979     emitpcode (POC_GOTO, popGetLabel (templbl->key));
3980     pic14_mov2w_regOrLit (AOP(right), lit, offs);
3981     emitpcode (POC_SUBFW, popGet (AOP(left), offs));
3982   } // while (offs)
3983   emitpLabel (templbl->key);
3984   goto result_in_carry;
3985
3986 result_in_carry:
3987
3988   /****************************************************
3989    * now CARRY contains the result of the comparison: *
3990    * SUBWF sets CARRY iff                             *
3991    * F-W >= 0 <==> F >= W <==> !(F < W)               *
3992    * (F=left, W=right)                                *
3993    ****************************************************/
3994
3995   if (performedLt) {
3996     invert_result = 1;
3997     // value will be used in the following genSkipc()
3998     rIfx.condition ^= 1;
3999   } // if
4000
4001 correct_result_in_carry:
4002
4003   // assign result to variable (if neccessary)
4004   if (result && AOP_TYPE(result) != AOP_CRY) {
4005     //DEBUGpc ("assign result");
4006     size = AOP_SIZE(result);
4007     while (size--) {
4008       emitpcode (POC_CLRF, popGet (AOP(result), size));
4009     } // while
4010     if (invert_result) {
4011       emitSKPC;
4012       emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4013     } else {
4014       emitpcode (POC_RLF, popGet (AOP(result), 0));
4015     }
4016   } // if (result)
4017
4018   // perform conditional jump
4019   if (ifx) {
4020     //DEBUGpc ("generate control flow");
4021     genSkipc (&rIfx);
4022     ifx->generated = 1;
4023   } // if
4024 }
4025
4026
4027 #if 0
4028 /* OLD VERSION -- BUGGY, DO NOT USE */
4029
4030 /*-----------------------------------------------------------------*/
4031 /* genCmp :- greater or less than comparison                       */
4032 /*-----------------------------------------------------------------*/
4033 static void genCmp (operand *left,operand *right,
4034                     operand *result, iCode *ifx, int sign)
4035 {
4036     int size; //, offset = 0 ;
4037     unsigned long lit = 0L,i = 0;
4038     resolvedIfx rFalseIfx;
4039     //  resolvedIfx rTrueIfx;
4040     symbol *truelbl;
4041
4042     FENTRY;
4043     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4044     /*
4045     if(ifx) {
4046     DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4047     DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4048     }
4049     */
4050
4051     resolveIfx(&rFalseIfx,ifx);
4052     truelbl  = newiTempLabel(NULL);
4053     size = max(AOP_SIZE(left),AOP_SIZE(right));
4054
4055     DEBUGpic14_AopType(__LINE__,left,right,result);
4056
4057 #define _swapp
4058
4059     /* if literal is on the right then swap with left */
4060     if ((AOP_TYPE(right) == AOP_LIT)) {
4061         operand *tmp = right ;
4062         unsigned long mask = (0x100 << (8*(size-1))) - 1;
4063         lit = ulFromVal(AOP(right)->aopu.aop_lit);
4064 #ifdef _swapp
4065
4066         lit = (lit - 1) & mask;
4067         right = left;
4068         left = tmp;
4069         rFalseIfx.condition ^= 1;
4070 #endif
4071
4072     } else if ((AOP_TYPE(left) == AOP_LIT)) {
4073         lit = ulFromVal(AOP(left)->aopu.aop_lit);
4074     }
4075
4076
4077     //if(IC_TRUE(ifx) == NULL)
4078     /* if left & right are bit variables */
4079     if (AOP_TYPE(left) == AOP_CRY &&
4080         AOP_TYPE(right) == AOP_CRY ) {
4081         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4082         pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4083     } else {
4084     /* subtract right from left if at the
4085     end the carry flag is set then we know that
4086         left is greater than right */
4087
4088         symbol *lbl  = newiTempLabel(NULL);
4089
4090 #ifndef _swapp
4091         if(AOP_TYPE(right) == AOP_LIT) {
4092
4093             //lit = ulFromVal(AOP(right)->aopu.aop_lit);
4094
4095             DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4096
4097             /* special cases */
4098
4099             if(lit == 0) {
4100
4101                 if(sign != 0)
4102                     genSkipCond(&rFalseIfx,left,size-1,7);
4103                 else
4104                     /* no need to compare to 0...*/
4105                     /* NOTE: this is a de-generate compare that most certainly
4106                     *       creates some dead code. */
4107                     emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4108
4109                 if(ifx) ifx->generated = 1;
4110                 return;
4111
4112             }
4113             size--;
4114
4115             if(size == 0) {
4116                 //i = (lit >> (size*8)) & 0xff;
4117                 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4118
4119                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4120
4121                 i = ((0-lit) & 0xff);
4122                 if(sign) {
4123                     if( i == 0x81) {
4124                     /* lit is 0x7f, all signed chars are less than
4125                         * this except for 0x7f itself */
4126                         emitpcode(POC_XORLW, popGetLit(0x7f));
4127                         genSkipz2(&rFalseIfx,0);
4128                     } else {
4129                         emitpcode(POC_ADDLW, popGetLit(0x80));
4130                         emitpcode(POC_ADDLW, popGetLit(i^0x80));
4131                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4132                     }
4133
4134                 } else {
4135                     if(lit == 1) {
4136                         genSkipz2(&rFalseIfx,1);
4137                     } else {
4138                         emitpcode(POC_ADDLW, popGetLit(i));
4139                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4140                     }
4141                 }
4142
4143                 if(ifx) ifx->generated = 1;
4144                 return;
4145             }
4146
4147             /* chars are out of the way. now do ints and longs */
4148
4149
4150             DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4151
4152             /* special cases */
4153
4154             if(sign) {
4155
4156                 if(lit == 0) {
4157                     genSkipCond(&rFalseIfx,left,size,7);
4158                     if(ifx) ifx->generated = 1;
4159                     return;
4160                 }
4161
4162                 if(lit <0x100) {
4163                     DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4164
4165                     //rFalseIfx.condition ^= 1;
4166                     //genSkipCond(&rFalseIfx,left,size,7);
4167                     //rFalseIfx.condition ^= 1;
4168
4169                     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4170                     if(rFalseIfx.condition)
4171                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4172                     else
4173                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4174
4175                     emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4176                     emitpcode(POC_ADDFW, popGet(AOP(left),0));
4177                     emitpcode(POC_MOVFW, popGet(AOP(left),1));
4178
4179                     while(size > 1)
4180                         emitpcode(POC_IORFW, popGet(AOP(left),size--));
4181
4182                     if(rFalseIfx.condition) {
4183                         emitSKPZ;
4184                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4185
4186                     } else {
4187                         emitSKPNZ;
4188                     }
4189
4190                     genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4191                     emitpLabel(truelbl->key);
4192                     if(ifx) ifx->generated = 1;
4193                     return;
4194
4195                 }
4196
4197                 if(size == 1) {
4198
4199                     if( (lit & 0xff) == 0) {
4200                         /* lower byte is zero */
4201                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4202                         i = ((lit >> 8) & 0xff) ^0x80;
4203                         emitpcode(POC_MOVFW, popGet(AOP(left),size));
4204                         emitpcode(POC_ADDLW, popGetLit( 0x80));
4205                         emitpcode(POC_ADDLW, popGetLit(0x100-i));
4206                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4207
4208
4209                         if(ifx) ifx->generated = 1;
4210                         return;
4211
4212                     }
4213                 } else {
4214                     /* Special cases for signed longs */
4215                     if( (lit & 0xffffff) == 0) {
4216                         /* lower byte is zero */
4217                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4218                         i = ((lit >> 8*3) & 0xff) ^0x80;
4219                         emitpcode(POC_MOVFW, popGet(AOP(left),size));
4220                         emitpcode(POC_ADDLW, popGetLit( 0x80));
4221                         emitpcode(POC_ADDLW, popGetLit(0x100-i));
4222                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4223
4224
4225                         if(ifx) ifx->generated = 1;
4226                         return;
4227
4228                     }
4229
4230                 }
4231
4232
4233                 if(lit & (0x80 << (size*8))) {
4234                     /* lit is negative */
4235                     DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4236
4237                     //genSkipCond(&rFalseIfx,left,size,7);
4238
4239                     emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4240
4241                     if(rFalseIfx.condition)
4242                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4243                     else
4244                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4245
4246
4247                 } else {
4248                     /* lit is positive */
4249                     DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4250                     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4251                     if(rFalseIfx.condition)
4252                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4253                     else
4254                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4255
4256                 }
4257
4258                 /* There are no more special cases, so perform a general compare */
4259
4260                 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4261                 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4262
4263                 while(size--) {
4264
4265                     emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4266                     emitSKPNZ;
4267                     emitpcode(POC_SUBFW, popGet(AOP(left),size));
4268                 }
4269                 //rFalseIfx.condition ^= 1;
4270                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4271
4272                 emitpLabel(truelbl->key);
4273
4274                 if(ifx) ifx->generated = 1;
4275                 return;
4276
4277
4278             }
4279
4280
4281             /* sign is out of the way. So now do an unsigned compare */
4282             DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4283
4284
4285             /* General case - compare to an unsigned literal on the right.*/
4286
4287             i = (lit >> (size*8)) & 0xff;
4288             emitpcode(POC_MOVLW, popGetLit(i));
4289             emitpcode(POC_SUBFW, popGet(AOP(left),size));
4290             while(size--) {
4291                 i = (lit >> (size*8)) & 0xff;
4292
4293                 if(i) {
4294                     emitpcode(POC_MOVLW, popGetLit(i));
4295                     emitSKPNZ;
4296                     emitpcode(POC_SUBFW, popGet(AOP(left),size));
4297                 } else {
4298                 /* this byte of the lit is zero,
4299                     *if it's not the last then OR in the variable */
4300                     if(size)
4301                         emitpcode(POC_IORFW, popGet(AOP(left),size));
4302                 }
4303             }
4304
4305
4306         emitpLabel(lbl->key);
4307         //if(emitFinalCheck)
4308         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4309         if(sign)
4310             emitpLabel(truelbl->key);
4311
4312         if(ifx) ifx->generated = 1;
4313         return;
4314
4315
4316         }
4317 #endif  // _swapp
4318
4319         if(AOP_TYPE(left) == AOP_LIT) {
4320             //symbol *lbl = newiTempLabel(NULL);
4321
4322             //EXPERIMENTAL lit = ulFromVal(AOP(left)->aopu.aop_lit);
4323
4324
4325             DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4326
4327             /* Special cases */
4328             if((lit == 0) && (sign == 0)){
4329
4330                 size--;
4331                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4332                 while(size)
4333                     emitpcode(POC_IORFW, popGet(AOP(right),--size));
4334
4335                 genSkipz2(&rFalseIfx,0);
4336                 if(ifx) ifx->generated = 1;
4337                 return;
4338             }
4339
4340             if(size==1) {
4341                 /* Special cases */
4342                 lit &= 0xff;
4343                 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4344                     /* degenerate compare can never be true */
4345                     if(rFalseIfx.condition == 0)
4346                         emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4347
4348                     if(ifx) ifx->generated = 1;
4349                     return;
4350                 }
4351
4352                 if(sign) {
4353                     /* signed comparisons to a literal byte */
4354
4355                     int lp1 = (lit+1) & 0xff;
4356
4357                     DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4358                     switch (lp1) {
4359                     case 0:
4360                         rFalseIfx.condition ^= 1;
4361                         genSkipCond(&rFalseIfx,right,0,7);
4362                         break;
4363                     case 0x7f:
4364                         emitpcode(POC_MOVFW, popGet(AOP(right),0));
4365                         emitpcode(POC_XORLW, popGetLit(0x7f));
4366                         genSkipz2(&rFalseIfx,1);
4367                         break;
4368                     default:
4369                         emitpcode(POC_MOVFW, popGet(AOP(right),0));
4370                         emitpcode(POC_ADDLW, popGetLit(0x80));
4371                         emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4372                         rFalseIfx.condition ^= 1;
4373                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4374                         break;
4375                     }
4376                     if(ifx) ifx->generated = 1;
4377                 } else {
4378                     /* unsigned comparisons to a literal byte */
4379
4380                     switch(lit & 0xff ) {
4381                     case 0:
4382                         emitpcode(POC_MOVFW, popGet(AOP(right),0));
4383                         genSkipz2(&rFalseIfx,0);
4384                         if(ifx) ifx->generated = 1;
4385                         break;
4386                     case 0x7f:
4387                         genSkipCond(&rFalseIfx,right,0,7);
4388                         if(ifx) ifx->generated = 1;
4389                         break;
4390
4391                     default:
4392                         emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4393                         emitpcode(POC_SUBFW, popGet(AOP(right),0));
4394                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4395                         rFalseIfx.condition ^= 1;
4396                         if (AOP_TYPE(result) == AOP_CRY) {
4397                             genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4398                             if(ifx) ifx->generated = 1;
4399                         } else {
4400                             DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4401                             emitpcode(POC_CLRF, popGet(AOP(result),0));
4402                             emitpcode(POC_RLF, popGet(AOP(result),0));
4403                             emitpcode(POC_MOVLW, popGetLit(0x01));
4404                             emitpcode(POC_XORWF, popGet(AOP(result),0));
4405                         }
4406                         break;
4407                     }
4408                 }
4409
4410                 //goto check_carry;
4411                 return;
4412
4413             } else {
4414
4415                 /* Size is greater than 1 */
4416
4417                 if(sign) {
4418                     int lp1 = lit+1;
4419
4420                     size--;
4421
4422                     if(lp1 == 0) {
4423                         /* this means lit = 0xffffffff, or -1 */
4424
4425
4426                         DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4427                         rFalseIfx.condition ^= 1;
4428                         genSkipCond(&rFalseIfx,right,size,7);
4429                         if(ifx) ifx->generated = 1;
4430                         return;
4431                     }
4432
4433                     if(lit == 0) {
4434                         int s = size;
4435
4436                         if(rFalseIfx.condition) {
4437                             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4438                             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4439                         }
4440
4441                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4442                         while(size--)
4443                             emitpcode(POC_IORFW, popGet(AOP(right),size));
4444
4445
4446                         emitSKPZ;
4447                         if(rFalseIfx.condition) {
4448                             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4449                             emitpLabel(truelbl->key);
4450                         }else {
4451                             rFalseIfx.condition ^= 1;
4452                             genSkipCond(&rFalseIfx,right,s,7);
4453                         }
4454
4455                         if(ifx) ifx->generated = 1;
4456                         return;
4457                     }
4458
4459                     if((size == 1) &&  (0 == (lp1&0xff))) {
4460                         /* lower byte of signed word is zero */
4461                         DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4462                         i = ((lp1 >> 8) & 0xff) ^0x80;
4463                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4464                         emitpcode(POC_ADDLW, popGetLit( 0x80));
4465                         emitpcode(POC_ADDLW, popGetLit(0x100-i));
4466                         rFalseIfx.condition ^= 1;
4467                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4468
4469
4470                         if(ifx) ifx->generated = 1;
4471                         return;
4472                     }
4473
4474                     if(lit & (0x80 << (size*8))) {
4475                         /* Lit is less than zero */
4476                         DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4477                         //rFalseIfx.condition ^= 1;
4478                         //genSkipCond(&rFalseIfx,left,size,7);
4479                         //rFalseIfx.condition ^= 1;
4480                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4481                         //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4482
4483                         if(rFalseIfx.condition)
4484                             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4485                         else
4486                             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4487
4488
4489                     } else {
4490                         /* Lit is greater than or equal to zero */
4491                         DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4492                         //rFalseIfx.condition ^= 1;
4493                         //genSkipCond(&rFalseIfx,right,size,7);
4494                         //rFalseIfx.condition ^= 1;
4495
4496                         //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4497                         //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4498
4499                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4500                         if(rFalseIfx.condition)
4501                             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4502                         else
4503                             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4504
4505                     }
4506
4507
4508                     emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4509                     emitpcode(POC_SUBFW, popGet(AOP(right),size));
4510
4511                     while(size--) {
4512
4513                         emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4514                         emitSKPNZ;
4515                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4516                     }
4517                     rFalseIfx.condition ^= 1;
4518                     //rFalseIfx.condition = 1;
4519                     genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4520
4521                     emitpLabel(truelbl->key);
4522
4523                     if(ifx) ifx->generated = 1;
4524                     return;
4525                     // end of if (sign)
4526                 } else {
4527
4528                     /* compare word or long to an unsigned literal on the right.*/
4529
4530
4531                     size--;
4532                     if(lit < 0xff) {
4533                         DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4534                         switch (lit) {
4535                         case 0:
4536                             break; /* handled above */
4537                         /*
4538                         case 0xff:
4539                             emitpcode(POC_MOVFW, popGet(AOP(right),size));
4540                             while(size--)
4541                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4542                             genSkipz2(&rFalseIfx,0);
4543                             break;
4544                         */
4545                         default:
4546                             emitpcode(POC_MOVFW, popGet(AOP(right),size));
4547                             while(--size)
4548                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4549
4550                             emitSKPZ;
4551                             if(rFalseIfx.condition)
4552                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4553                             else
4554                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4555
4556
4557                             emitpcode(POC_MOVLW, popGetLit(lit+1));
4558                             emitpcode(POC_SUBFW, popGet(AOP(right),0));
4559
4560                             rFalseIfx.condition ^= 1;
4561                             genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4562                         }
4563
4564                         emitpLabel(truelbl->key);
4565
4566                         if(ifx) ifx->generated = 1;
4567                         return;
4568                     }
4569
4570
4571                     lit++;
4572                     DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4573                     i = (lit >> (size*8)) & 0xff;
4574
4575                     emitpcode(POC_MOVLW, popGetLit(i));
4576                     emitpcode(POC_SUBFW, popGet(AOP(right),size));
4577
4578                     while(size--) {
4579                         i = (lit >> (size*8)) & 0xff;
4580
4581                         if(i) {
4582                             emitpcode(POC_MOVLW, popGetLit(i));
4583                             emitSKPNZ;
4584                             emitpcode(POC_SUBFW, popGet(AOP(right),size));
4585                         } else {
4586                         /* this byte of the lit is zero,
4587                             *if it's not the last then OR in the variable */
4588                             if(size)
4589                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4590                         }
4591                     }
4592
4593
4594                     emitpLabel(lbl->key);
4595
4596                     rFalseIfx.condition ^= 1;
4597                     genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4598                 }
4599
4600                 if(sign)
4601                     emitpLabel(truelbl->key);
4602                 if(ifx) ifx->generated = 1;
4603                 return;
4604             }
4605         }
4606         /* Compare two variables */
4607
4608         DEBUGpic14_emitcode(";sign","%d",sign);
4609
4610         size--;
4611         if(sign) {
4612             /* Sigh. thus sucks... */
4613             if(size) {
4614                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4615                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4616                 emitpcode(POC_MOVLW, popGetLit(0x80));
4617                 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4618                 emitpcode(POC_XORFW, popGet(AOP(right),size));
4619                 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4620             } else {
4621                 /* Signed char comparison */
4622                 /* Special thanks to Nikolai Golovchenko for this snippet */
4623                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4624                 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4625                 emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4626                 emitpcode(POC_XORFW, popGet(AOP(left),0));
4627                 emitpcode(POC_XORFW, popGet(AOP(right),0));
4628                 emitpcode(POC_ADDLW, popGetLit(0x80));
4629
4630                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4631                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4632
4633                 if(ifx) ifx->generated = 1;
4634                 return;
4635             }
4636
4637         } else {
4638
4639             emitpcode(POC_MOVFW, popGet(AOP(right),size));
4640             emitpcode(POC_SUBFW, popGet(AOP(left),size));
4641         }
4642
4643
4644         /* The rest of the bytes of a multi-byte compare */
4645         while (size) {
4646
4647             emitSKPZ;
4648             emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4649             size--;
4650
4651             emitpcode(POC_MOVFW, popGet(AOP(right),size));
4652             emitpcode(POC_SUBFW, popGet(AOP(left),size));
4653
4654
4655         }
4656
4657         emitpLabel(lbl->key);
4658
4659         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4660         if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
4661             (AOP_TYPE(result) == AOP_REG)) {
4662             emitpcode(POC_CLRF, popGet(AOP(result),0));
4663             emitpcode(POC_RLF, popGet(AOP(result),0));
4664         } else {
4665             genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4666         }
4667         //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4668         if(ifx) ifx->generated = 1;
4669
4670         return;
4671
4672     }
4673
4674     // check_carry:
4675     if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4676         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4677         pic14_outBitC(result);
4678     } else {
4679         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4680         /* if the result is used in the next
4681         ifx conditional branch then generate
4682         code a little differently */
4683         if (ifx )
4684             genIfxJump (ifx,"c");
4685         else
4686             pic14_outBitC(result);
4687         /* leave the result in acc */
4688     }
4689
4690 }
4691 #endif
4692
4693 /*-----------------------------------------------------------------*/
4694 /* genCmpGt :- greater than comparison                             */
4695 /*-----------------------------------------------------------------*/
4696 static void genCmpGt (iCode *ic, iCode *ifx)
4697 {
4698     operand *left, *right, *result;
4699     sym_link *letype , *retype;
4700     int sign ;
4701
4702     FENTRY;
4703     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4704     left = IC_LEFT(ic);
4705     right= IC_RIGHT(ic);
4706     result = IC_RESULT(ic);
4707
4708     letype = getSpec(operandType(left));
4709     retype =getSpec(operandType(right));
4710     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4711     /* assign the amsops */
4712     aopOp (left,ic,FALSE);
4713     aopOp (right,ic,FALSE);
4714     aopOp (result,ic,TRUE);
4715
4716     genCmp(right, left, result, ifx, sign);
4717
4718     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4719     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4720     freeAsmop(result,NULL,ic,TRUE);
4721 }
4722
4723 /*-----------------------------------------------------------------*/
4724 /* genCmpLt - less than comparisons                                */
4725 /*-----------------------------------------------------------------*/
4726 static void genCmpLt (iCode *ic, iCode *ifx)
4727 {
4728     operand *left, *right, *result;
4729     sym_link *letype , *retype;
4730     int sign ;
4731
4732     FENTRY;
4733     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4734     left = IC_LEFT(ic);
4735     right= IC_RIGHT(ic);
4736     result = IC_RESULT(ic);
4737
4738     letype = getSpec(operandType(left));
4739     retype =getSpec(operandType(right));
4740     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4741
4742     /* assign the amsops */
4743     aopOp (left,ic,FALSE);
4744     aopOp (right,ic,FALSE);
4745     aopOp (result,ic,TRUE);
4746
4747     genCmp(left, right, result, ifx, sign);
4748
4749     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4750     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4751     freeAsmop(result,NULL,ic,TRUE);
4752 }
4753
4754 #if 0
4755 /*-----------------------------------------------------------------*/
4756 /* genc16bit2lit - compare a 16 bit value to a literal             */
4757 /*-----------------------------------------------------------------*/
4758 static void genc16bit2lit(operand *op, int lit, int offset)
4759 {
4760     int i;
4761
4762     FENTRY;
4763     DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4764     if( (lit&0xff) == 0)
4765         i=1;
4766     else
4767         i=0;
4768
4769     switch( BYTEofLONG(lit,i)) {
4770     case 0:
4771         emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4772         break;
4773     case 1:
4774         emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4775         break;
4776     case 0xff:
4777         emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4778         break;
4779     default:
4780         emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4781         emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4782     }
4783
4784     i ^= 1;
4785
4786     switch( BYTEofLONG(lit,i)) {
4787     case 0:
4788         emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4789         break;
4790     case 1:
4791         emitSKPNZ;
4792         emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4793         break;
4794     case 0xff:
4795         emitSKPNZ;
4796         emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4797         break;
4798     default:
4799         emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4800         emitSKPNZ;
4801         emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4802
4803     }
4804
4805 }
4806 #endif
4807
4808 #if 0
4809 /*-----------------------------------------------------------------*/
4810 /* gencjneshort - compare and jump if not equal                    */
4811 /*-----------------------------------------------------------------*/
4812 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4813 {
4814     int size = min(AOP_SIZE(left),AOP_SIZE(right));
4815     int offset = 0;
4816     //resolvedIfx rIfx;
4817     symbol *lbl;
4818
4819     //unsigned long lit = 0L;
4820     FENTRY;
4821     if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4822       emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4823       return;
4824     }
4825     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4826     DEBUGpic14_AopType(__LINE__,left,right,result);
4827
4828     assert (!pic14_sameRegs (AOP(left), AOP(result)));
4829     assert (!pic14_sameRegs (AOP(right), AOP(result)));
4830     if (AOP_SIZE(result)) {
4831       for (offset = 0; offset < AOP_SIZE(result); offset++)
4832         emitpcode (POC_CLRF, popGet (AOP(result), offset));
4833     }
4834
4835     assert (AOP_SIZE(left) == AOP_SIZE(right));
4836     //resolveIfx(&rIfx,ifx);
4837     lbl = newiTempLabel (NULL);
4838     while (size--)
4839     {
4840       mov2w (AOP(right),size);
4841       emitpcode (POC_XORFW, popGet (AOP(left), size));
4842       if (size)
4843       {
4844         emitSKPZ;
4845         emitpcode (POC_GOTO, popGetLabel (lbl->key));
4846       }
4847     } // while
4848     emitpLabel (lbl->key);
4849     if (AOP_SIZE(result)) {
4850       emitSKPNZ;
4851       emitpcode (POC_INCF, popGet (AOP(result), 0));
4852     } else {
4853       assert (ifx);
4854       genSkipz (ifx, NULL != IC_TRUE(ifx));
4855       ifx->generated = 1;
4856     }
4857     return;
4858 #if 0
4859     if(result)
4860     {
4861         DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4862         assert (!pic14_sameRegs (AOP(result), AOP(left)));
4863         assert (!pic14_sameRegs (AOP(result), AOP(right)));
4864         for (offset=0; offset < AOP_SIZE(result); offset++)
4865         {
4866             emitpcode (POC_CLRF, popGet (AOP(result), offset));
4867         } // for offset
4868     }
4869
4870
4871     /* if the left side is a literal or
4872     if the right is in a pointer register and left
4873     is not */
4874     if ((AOP_TYPE(left) == AOP_LIT) ||
4875         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4876         operand *t = right;
4877         right = left;
4878         left = t;
4879     }
4880     if(AOP_TYPE(right) == AOP_LIT)
4881         lit = ulFromVal(AOP(right)->aopu.aop_lit);
4882
4883     /* if the right side is a literal then anything goes */
4884     if (AOP_TYPE(right) == AOP_LIT &&
4885         AOP_TYPE(left) != AOP_DIR ) {
4886         switch(size) {
4887         case 2:
4888             genc16bit2lit(left, lit, 0);
4889             emitSKPNZ;
4890             emitpcode(POC_GOTO,popGetLabel(lbl->key));
4891             break;
4892         default:
4893             offset = 0;
4894             while (size--) {
4895                 if(lit & 0xff) {
4896                     emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4897                     emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4898                 } else {
4899                     emitpcode(POC_MOVF,popGet(AOP(left),offset));
4900                 }
4901
4902                 emitSKPNZ;
4903                 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4904                 offset++;
4905                 lit >>= 8;
4906             }
4907             break;
4908         }
4909     }
4910
4911     /* if the right side is in a register or in direct space or
4912     if the left is a pointer register & right is not */
4913     else if (AOP_TYPE(right) == AOP_REG ||
4914         AOP_TYPE(right) == AOP_DIR ||
4915         (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4916         (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4917         //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4918         int lbl_key = lbl->key;
4919
4920         if(!result) {
4921             DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4922             fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4923                 __FUNCTION__,__LINE__);
4924             return;
4925         }
4926
4927         /*     switch(size) { */
4928         /*     case 2: */
4929         /*       genc16bit2lit(left, lit, 0); */
4930         /*       emitSKPNZ; */
4931         /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4932         /*       break; */
4933         /*     default: */
4934         offset = 0;
4935         while (size--) {
4936             int emit_skip=1;
4937             if((AOP_TYPE(left) == AOP_DIR) &&
4938                 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4939
4940                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4941                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
4942
4943             } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4944
4945                 switch (lit & 0xff) {
4946                 case 0:
4947                     emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4948                     break;
4949                 case 1:
4950                     emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4951                     //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4952                     emitpcode(POC_GOTO,popGetLabel(lbl->key));
4953                     emit_skip=0;
4954                     break;
4955                 case 0xff:
4956                     emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4957                     //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4958                     //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4959                     emitpcode(POC_GOTO,popGetLabel(lbl_key));
4960                     emit_skip=0;
4961                     break;
4962                 default:
4963                     emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4964                     emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4965                 }
4966                 lit >>= 8;
4967
4968             } else {
4969                 emitpcode(POC_MOVF,popGet(AOP(left),offset));
4970             }
4971             if(emit_skip) {
4972                 if(AOP_TYPE(result) == AOP_CRY) {
4973                     pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4974                     if(rIfx.condition)
4975                         emitSKPNZ;
4976                     else
4977                         emitSKPZ;
4978                     emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4979                 } else {
4980                     /* fix me. probably need to check result size too */
4981                     //emitpcode(POC_CLRF,popGet(AOP(result),0));
4982                     if(rIfx.condition)
4983                         emitSKPZ;
4984                     else
4985                         emitSKPNZ;
4986                     emitpcode(POC_GOTO,popGetLabel(lbl_key));
4987                 }
4988                 if(ifx)
4989                     ifx->generated=1;
4990             }
4991             emit_skip++;
4992             offset++;
4993         }
4994         /*       break; */
4995         /*     } */
4996     } else if(AOP_TYPE(right) == AOP_REG &&
4997         AOP_TYPE(left) != AOP_DIR){
4998
4999         offset = 0;
5000         while(size--) {
5001             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5002             emitpcode(POC_XORFW,popGet(AOP(right),offset));
5003             pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5004             if(rIfx.condition)
5005                 emitSKPNZ;
5006             else
5007                 emitSKPZ;
5008             emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5009             offset++;
5010         }
5011
5012     }else{
5013         /* right is a pointer reg need both a & b */
5014         offset = 0;
5015         while(size--) {
5016             char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5017             if(strcmp(l,"b"))
5018                 pic14_emitcode("mov","b,%s",l);
5019             MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5020             pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5021             offset++;
5022         }
5023     }
5024
5025     emitpcode(POC_INCF,popGet(AOP(result),0));
5026     if(!rIfx.condition)
5027         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5028
5029     emitpLabel(lbl->key);
5030
5031     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5032
5033     if(ifx)
5034         ifx->generated = 1;
5035 #endif
5036 }
5037 #endif
5038
5039 #if 0
5040 /*-----------------------------------------------------------------*/
5041 /* gencjne - compare and jump if not equal                         */
5042 /*-----------------------------------------------------------------*/
5043 static void gencjne(operand *left, operand *right, iCode *ifx)
5044 {
5045     symbol *tlbl  = newiTempLabel(NULL);
5046
5047     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5048     gencjneshort(left, right, lbl);
5049
5050     pic14_emitcode("mov","a,%s",one);
5051     pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5052     pic14_emitcode("","%05d_DS_:",lbl->key+100);
5053     pic14_emitcode("clr","a");
5054     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5055
5056     emitpLabel(lbl->key);
5057     emitpLabel(tlbl->key);
5058
5059 }
5060 #endif
5061
5062 /*-----------------------------------------------------------------*/
5063 /* genCmpEq - generates code for equal to                          */
5064 /*-----------------------------------------------------------------*/
5065 static void genCmpEq (iCode *ic, iCode *ifx)
5066 {
5067   operand *left, *right, *result;
5068   int size;
5069   symbol *false_label;
5070
5071   FENTRY;
5072   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5073
5074   if(ifx)
5075     DEBUGpic14_emitcode ("; ifx is non-null","");
5076   else
5077     DEBUGpic14_emitcode ("; ifx is null","");
5078
5079   aopOp((left=IC_LEFT(ic)),ic,FALSE);
5080   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5081   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5082
5083   DEBUGpic14_AopType(__LINE__,left,right,result);
5084
5085   /* if literal, move literal to right */
5086   if (op_isLitLike (IC_LEFT(ic))) {
5087     operand *tmp = right ;
5088     right = left;
5089     left = tmp;
5090   }
5091
5092   false_label = NULL;
5093   if (ifx && !IC_TRUE(ifx))
5094   {
5095     assert (IC_FALSE(ifx));
5096     false_label = IC_FALSE(ifx);
5097   }
5098
5099   size = min(AOP_SIZE(left),AOP_SIZE(right));
5100   assert(!pic14_sameRegs(AOP(result),AOP(left)));
5101   assert(!pic14_sameRegs(AOP(result),AOP(right)));
5102
5103   /* assume left != right */
5104   {
5105     int i;
5106     for (i=0; i < AOP_SIZE(result); i++)
5107     {
5108       emitpcode(POC_CLRF, popGet(AOP(result),i));
5109     }
5110   }
5111
5112   if (AOP_TYPE(right) == AOP_LIT)
5113   {
5114     unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
5115     int i;
5116     size = AOP_SIZE(left);
5117     assert(!op_isLitLike(left));
5118
5119     switch (lit)
5120     {
5121       case 0:
5122         mov2w(AOP(left), 0);
5123     for (i=1; i < size; i++)
5124       emitpcode(POC_IORFW,popGet(AOP(left),i));
5125     /* now Z is set iff `left == right' */
5126     emitSKPZ;
5127     if (!false_label) false_label = newiTempLabel(NULL);
5128     emitpcode(POC_GOTO, popGetLabel(false_label->key));
5129     break;
5130
5131       default:
5132     for (i=0; i < size; i++)
5133     {
5134       mov2w(AOP(left),i);
5135       emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5136       /* now Z is cleared if `left != right' */
5137       emitSKPZ;
5138       if (!false_label) false_label = newiTempLabel(NULL);
5139       emitpcode(POC_GOTO, popGetLabel(false_label->key));
5140     } // for i
5141     break;
5142     } // switch (lit)
5143   }
5144   else
5145   {
5146     /* right is no literal */
5147     int i;
5148
5149     for (i=0; i < size; i++)
5150     {
5151       mov2w(AOP(right),i);
5152       emitpcode(POC_XORFW,popGet(AOP(left),i));
5153       /* now Z is cleared if `left != right' */
5154       emitSKPZ;
5155       if (!false_label) false_label = newiTempLabel(NULL);
5156       emitpcode(POC_GOTO, popGetLabel(false_label->key));
5157     } // for i
5158   }
5159
5160   /* if we reach here, left == right */
5161
5162   if (AOP_SIZE(result) > 0)
5163   {
5164     emitpcode(POC_INCF, popGet(AOP(result),0));
5165   }
5166
5167   if (ifx && IC_TRUE(ifx))
5168   {
5169     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5170   }
5171
5172   if (false_label && (!ifx || IC_TRUE(ifx)))
5173     emitpLabel(false_label->key);
5174
5175   if (ifx) ifx->generated = 1;
5176
5177   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5178   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5179   freeAsmop(result,NULL,ic,TRUE);
5180 }
5181
5182 /*-----------------------------------------------------------------*/
5183 /* ifxForOp - returns the icode containing the ifx for operand     */
5184 /*-----------------------------------------------------------------*/
5185 static iCode *ifxForOp ( operand *op, iCode *ic )
5186 {
5187     FENTRY;
5188     /* if true symbol then needs to be assigned */
5189     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5190     if (IS_TRUE_SYMOP(op))
5191         return NULL ;
5192
5193     /* if this has register type condition and
5194     the next instruction is ifx with the same operand
5195     and live to of the operand is upto the ifx only then */
5196     if (ic->next &&
5197         ic->next->op == IFX &&
5198         IC_COND(ic->next)->key == op->key &&
5199         OP_SYMBOL(op)->liveTo <= ic->next->seq )
5200         return ic->next;
5201
5202     if (ic->next &&
5203         ic->next->op == IFX &&
5204         IC_COND(ic->next)->key == op->key) {
5205         DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5206         return ic->next;
5207     }
5208
5209     DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5210     if (ic->next &&
5211         ic->next->op == IFX)
5212         DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5213
5214     if (ic->next &&
5215         ic->next->op == IFX &&
5216         IC_COND(ic->next)->key == op->key) {
5217         DEBUGpic14_emitcode ("; "," key is okay");
5218         DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5219             OP_SYMBOL(op)->liveTo,
5220             ic->next->seq);
5221     }
5222
5223
5224     return NULL;
5225 }
5226 /*-----------------------------------------------------------------*/
5227 /* genAndOp - for && operation                                     */
5228 /*-----------------------------------------------------------------*/
5229 static void genAndOp (iCode *ic)
5230 {
5231     operand *left,*right, *result;
5232     /*     symbol *tlbl; */
5233
5234     FENTRY;
5235     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5236     /* note here that && operations that are in an
5237     if statement are taken away by backPatchLabels
5238     only those used in arthmetic operations remain */
5239     aopOp((left=IC_LEFT(ic)),ic,FALSE);
5240     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5241     aopOp((result=IC_RESULT(ic)),ic,FALSE);
5242
5243     DEBUGpic14_AopType(__LINE__,left,right,result);
5244
5245     emitpcode(POC_MOVFW,popGet(AOP(left),0));
5246     emitpcode(POC_ANDFW,popGet(AOP(right),0));
5247     emitpcode(POC_MOVWF,popGet(AOP(result),0));
5248
5249     /* if both are bit variables */
5250     /*     if (AOP_TYPE(left) == AOP_CRY && */
5251     /*         AOP_TYPE(right) == AOP_CRY ) { */
5252     /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5253     /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5254     /*         pic14_outBitC(result); */
5255     /*     } else { */
5256     /*         tlbl = newiTempLabel(NULL); */
5257     /*         pic14_toBoolean(left);     */
5258     /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5259     /*         pic14_toBoolean(right); */
5260     /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5261     /*         pic14_outBitAcc(result); */
5262     /*     } */
5263
5264     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5265     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5266     freeAsmop(result,NULL,ic,TRUE);
5267 }
5268
5269
5270 /*-----------------------------------------------------------------*/
5271 /* genOrOp - for || operation                                      */
5272 /*-----------------------------------------------------------------*/
5273 /*
5274 tsd pic port -
5275 modified this code, but it doesn't appear to ever get called
5276 */
5277
5278 static void genOrOp (iCode *ic)
5279 {
5280     operand *left,*right, *result;
5281     symbol *tlbl;
5282     int i;
5283
5284     /* note here that || operations that are in an
5285     if statement are taken away by backPatchLabels
5286     only those used in arthmetic operations remain */
5287     FENTRY;
5288     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5289     aopOp((left=IC_LEFT(ic)),ic,FALSE);
5290     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5291     aopOp((result=IC_RESULT(ic)),ic,FALSE);
5292
5293     DEBUGpic14_AopType(__LINE__,left,right,result);
5294
5295     for (i=0; i < AOP_SIZE(result); i++)
5296     {
5297         emitpcode(POC_CLRF, popGet(AOP(result), i));
5298     } // for i
5299
5300     tlbl = newiTempLabel(NULL);
5301     pic14_toBoolean(left);
5302     emitSKPZ;
5303     emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5304     pic14_toBoolean(right);
5305     emitpLabel(tlbl->key);
5306     /* here Z is clear IFF `left || right' */
5307     emitSKPZ;
5308     emitpcode(POC_INCF, popGet(AOP(result), 0));
5309
5310     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5311     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5312     freeAsmop(result,NULL,ic,TRUE);
5313 }
5314
5315 /*-----------------------------------------------------------------*/
5316 /* isLiteralBit - test if lit == 2^n                               */
5317 /*-----------------------------------------------------------------*/
5318 static int isLiteralBit(unsigned long lit)
5319 {
5320     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5321         0x100L,0x200L,0x400L,0x800L,
5322         0x1000L,0x2000L,0x4000L,0x8000L,
5323         0x10000L,0x20000L,0x40000L,0x80000L,
5324         0x100000L,0x200000L,0x400000L,0x800000L,
5325         0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5326         0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5327     int idx;
5328
5329     FENTRY;
5330     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5331     for(idx = 0; idx < 32; idx++)
5332         if(lit == pw[idx])
5333             return idx+1;
5334         return 0;
5335 }
5336
5337 /*-----------------------------------------------------------------*/
5338 /* continueIfTrue -                                                */
5339 /*-----------------------------------------------------------------*/
5340 static void continueIfTrue (iCode *ic)
5341 {
5342     FENTRY;
5343     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5344     if(IC_TRUE(ic))
5345     {
5346         // Why +100?!?
5347         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5348         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5349     }
5350     ic->generated = 1;
5351 }
5352
5353 /*-----------------------------------------------------------------*/
5354 /* jmpIfTrue -                                                     */
5355 /*-----------------------------------------------------------------*/
5356 static void jumpIfTrue (iCode *ic)
5357 {
5358     FENTRY;
5359     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5360     if(!IC_TRUE(ic))
5361     {
5362         // Why +100?!?
5363         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5364         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5365     }
5366     ic->generated = 1;
5367 }
5368
5369 /*-----------------------------------------------------------------*/
5370 /* jmpTrueOrFalse -                                                */
5371 /*-----------------------------------------------------------------*/
5372 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5373 {
5374     FENTRY;
5375     // ugly but optimized by peephole
5376     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5377     if(IC_TRUE(ic)){
5378         symbol *nlbl = newiTempLabel(NULL);
5379         pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5380         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5381         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5382         pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5383     }
5384     else{
5385         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5386         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5387     }
5388     ic->generated = 1;
5389 }
5390
5391 /*-----------------------------------------------------------------*/
5392 /* genAnd  - code for and                                          */
5393 /*-----------------------------------------------------------------*/
5394 static void genAnd (iCode *ic, iCode *ifx)
5395 {
5396     operand *left, *right, *result;
5397     int size, offset=0;
5398     unsigned long lit = 0L;
5399     int bytelit = 0;
5400     resolvedIfx rIfx;
5401
5402     FENTRY;
5403     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5404     aopOp((left = IC_LEFT(ic)),ic,FALSE);
5405     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5406     aopOp((result=IC_RESULT(ic)),ic,TRUE);
5407
5408     resolveIfx(&rIfx,ifx);
5409
5410     /* if left is a literal & right is not then exchange them */
5411     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5412         AOP_NEEDSACC(left)) {
5413         operand *tmp = right ;
5414         right = left;
5415         left = tmp;
5416     }
5417
5418     /* if result = right then exchange them */
5419     if(pic14_sameRegs(AOP(result),AOP(right))){
5420         operand *tmp = right ;
5421         right = left;
5422         left = tmp;
5423     }
5424
5425     /* if right is bit then exchange them */
5426     if (AOP_TYPE(right) == AOP_CRY &&
5427         AOP_TYPE(left) != AOP_CRY){
5428         operand *tmp = right ;
5429         right = left;
5430         left = tmp;
5431     }
5432     if(AOP_TYPE(right) == AOP_LIT)
5433         lit = ulFromVal (AOP(right)->aopu.aop_lit);
5434
5435     size = AOP_SIZE(result);
5436
5437     DEBUGpic14_AopType(__LINE__,left,right,result);
5438
5439     // if(bit & yy)
5440     // result = bit & yy;
5441     if (AOP_TYPE(left) == AOP_CRY){
5442         // c = bit & literal;
5443         if(AOP_TYPE(right) == AOP_LIT){
5444             if(lit & 1) {
5445                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5446                     // no change
5447                     goto release;
5448                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5449             } else {
5450                 // bit(result) = 0;
5451                 if(size && (AOP_TYPE(result) == AOP_CRY)){
5452                     pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5453                     goto release;
5454                 }
5455                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5456                     jumpIfTrue(ifx);
5457                     goto release;
5458                 }
5459                 pic14_emitcode("clr","c");
5460             }
5461         } else {
5462             if (AOP_TYPE(right) == AOP_CRY){
5463                 // c = bit & bit;
5464                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5465                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5466             } else {
5467                 // c = bit & val;
5468                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5469                 // c = lsb
5470                 pic14_emitcode("rrc","a");
5471                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5472             }
5473         }
5474         // bit = c
5475         // val = c
5476         if(size)
5477             pic14_outBitC(result);
5478         // if(bit & ...)
5479         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5480             genIfxJump(ifx, "c");
5481         goto release ;
5482     }
5483
5484     // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5485     // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5486     if((AOP_TYPE(right) == AOP_LIT) &&
5487         (AOP_TYPE(result) == AOP_CRY) &&
5488         (AOP_TYPE(left) != AOP_CRY)){
5489         int posbit = isLiteralBit(lit);
5490         /* left &  2^n */
5491         if(posbit){
5492             posbit--;
5493             //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5494             // bit = left & 2^n
5495             if(size)
5496                 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5497             // if(left &  2^n)
5498             else{
5499                 if(ifx){
5500                     int offset = 0;
5501                     while (posbit > 7) {
5502                         posbit -= 8;
5503                         offset++;
5504                     }
5505                     emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5506                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5507                     emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5508
5509                     ifx->generated = 1;
5510                 }
5511                 goto release;
5512             }
5513         } else {
5514             symbol *tlbl = newiTempLabel(NULL);
5515             int sizel = AOP_SIZE(left);
5516             if(size)
5517                 pic14_emitcode("setb","c");
5518             while(sizel--){
5519                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5520                     mov2w( AOP(left), offset);
5521                     // byte ==  2^n ?
5522                     if((posbit = isLiteralBit(bytelit)) != 0) {
5523                         emitpcode(rIfx.condition ? POC_BTFSC : POC_BTFSS, // XXX: or the other way round?
5524                             newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit - 1, 0));
5525                         pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5526                     }
5527                     else{
5528                         emitpcode(POC_ANDLW, newpCodeOpLit(bytelit & 0x0ff));
5529                         if (rIfx.condition) emitSKPZ;
5530                         else emitSKPNZ;
5531
5532                         if(bytelit != 0x0FFL)
5533                         {
5534                             pic14_emitcode("anl","a,%s",
5535                             aopGet(AOP(right),offset,FALSE,TRUE));
5536                         }
5537                         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5538                     }
5539
5540                     emitpcode(POC_GOTO, popGetLabel(rIfx.lbl->key));
5541                     ifx->generated = 1;
5542
5543                 }
5544                 offset++;
5545             }
5546             // bit = left & literal
5547             if(size){
5548                 pic14_emitcode("clr","c");
5549                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5550             }
5551             // if(left & literal)
5552             else{
5553                 if(ifx)
5554                     jmpTrueOrFalse(ifx, tlbl);
5555                 goto release ;
5556             }
5557         }
5558         pic14_outBitC(result);
5559         goto release ;
5560     }
5561
5562     /* if left is same as result */
5563     if(pic14_sameRegs(AOP(result),AOP(left))){
5564         int know_W = -1;
5565         for(;size--; offset++,lit>>=8) {
5566             if(AOP_TYPE(right) == AOP_LIT){
5567                 switch(lit & 0xff) {
5568                 case 0x00:
5569                     /*  and'ing with 0 has clears the result */
5570                     emitpcode(POC_CLRF,popGet(AOP(result),offset));
5571                     break;
5572                 case 0xff:
5573                     /* and'ing with 0xff is a nop when the result and left are the same */
5574                     break;
5575
5576                 default:
5577                     {
5578                         int p = my_powof2( (~lit) & 0xff );
5579                         if(p>=0) {
5580                             /* only one bit is set in the literal, so use a bcf instruction */
5581                             emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5582
5583                         } else {
5584                             if(know_W != (int)(lit&0xff))
5585                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5586                             know_W = lit &0xff;
5587                             emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5588                         }
5589                     }
5590                 }
5591             } else {
5592                 if (AOP_TYPE(left) == AOP_ACC) {
5593                     emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5594                 } else {
5595                     emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5596                     emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5597
5598                 }
5599             }
5600         }
5601
5602     } else {
5603         // left & result in different registers
5604         if(AOP_TYPE(result) == AOP_CRY){
5605             // result = bit
5606             // if(size), result in bit
5607             // if(!size && ifx), conditional oper: if(left & right)
5608             symbol *tlbl = newiTempLabel(NULL);
5609             int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5610             if(size)
5611                 pic14_emitcode("setb","c");
5612             while(sizer--){
5613                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5614                 pic14_emitcode("anl","a,%s",
5615                     aopGet(AOP(left),offset,FALSE,FALSE));
5616                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5617                 offset++;
5618             }
5619             if(size){
5620                 CLRC;
5621                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5622                 pic14_outBitC(result);
5623             } else if(ifx)
5624                 jmpTrueOrFalse(ifx, tlbl);
5625         } else {
5626             for(;(size--);offset++) {
5627                 // normal case
5628                 // result = left & right
5629                 if(AOP_TYPE(right) == AOP_LIT){
5630                     int t = (lit >> (offset*8)) & 0x0FFL;
5631                     switch(t) {
5632                     case 0x00:
5633                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
5634                         break;
5635                     case 0xff:
5636                         if(AOP_TYPE(left) != AOP_ACC) {
5637                             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5638                         }
5639                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5640                         break;
5641                     default:
5642                         if(AOP_TYPE(left) == AOP_ACC) {
5643                             emitpcode(POC_ANDLW, popGetLit(t));
5644                         } else {
5645                             emitpcode(POC_MOVLW, popGetLit(t));
5646                             emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5647                         }
5648                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5649                     }
5650                     continue;
5651                 }
5652
5653                 if (AOP_TYPE(left) == AOP_ACC) {
5654                     emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5655                 } else {
5656                     emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5657                     emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5658                 }
5659                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5660             }
5661         }
5662     }
5663
5664 release :
5665     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5666     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5667     freeAsmop(result,NULL,ic,TRUE);
5668 }
5669
5670 /*-----------------------------------------------------------------*/
5671 /* genOr  - code for or                                            */
5672 /*-----------------------------------------------------------------*/
5673 static void genOr (iCode *ic, iCode *ifx)
5674 {
5675     operand *left, *right, *result;
5676     int size, offset=0;
5677     unsigned long lit = 0L;
5678
5679     FENTRY;
5680     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5681
5682     aopOp((left = IC_LEFT(ic)),ic,FALSE);
5683     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5684     aopOp((result=IC_RESULT(ic)),ic,TRUE);
5685
5686     DEBUGpic14_AopType(__LINE__,left,right,result);
5687
5688     /* if left is a literal & right is not then exchange them */
5689     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5690         AOP_NEEDSACC(left)) {
5691         operand *tmp = right ;
5692         right = left;
5693         left = tmp;
5694     }
5695
5696     /* if result = right then exchange them */
5697     if(pic14_sameRegs(AOP(result),AOP(right))){
5698         operand *tmp = right ;
5699         right = left;
5700         left = tmp;
5701     }
5702
5703     /* if right is bit then exchange them */
5704     if (AOP_TYPE(right) == AOP_CRY &&
5705         AOP_TYPE(left) != AOP_CRY){
5706         operand *tmp = right ;
5707         right = left;
5708         left = tmp;
5709     }
5710
5711     DEBUGpic14_AopType(__LINE__,left,right,result);
5712
5713     if(AOP_TYPE(right) == AOP_LIT)
5714         lit = ulFromVal (AOP(right)->aopu.aop_lit);
5715
5716     size = AOP_SIZE(result);
5717
5718     // if(bit | yy)
5719     // xx = bit | yy;
5720     if (AOP_TYPE(left) == AOP_CRY){
5721         if(AOP_TYPE(right) == AOP_LIT){
5722             // c = bit & literal;
5723             if(lit){
5724                 // lit != 0 => result = 1
5725                 if(AOP_TYPE(result) == AOP_CRY){
5726                     if(size)
5727                         emitpcode(POC_BSF, popGet(AOP(result),0));
5728                     //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5729                     //   AOP(result)->aopu.aop_dir,
5730                     //   AOP(result)->aopu.aop_dir);
5731                     else if(ifx)
5732                         continueIfTrue(ifx);
5733                     goto release;
5734                 }
5735             } else {
5736                 // lit == 0 => result = left
5737                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5738                     goto release;
5739                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5740             }
5741         } else {
5742             if (AOP_TYPE(right) == AOP_CRY){
5743                 if(pic14_sameRegs(AOP(result),AOP(left))){
5744                     // c = bit | bit;
5745                     emitpcode(POC_BCF,   popGet(AOP(result),0));
5746                     emitpcode(POC_BTFSC, popGet(AOP(right),0));
5747                     emitpcode(POC_BSF,   popGet(AOP(result),0));
5748
5749                     pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5750                         AOP(result)->aopu.aop_dir,
5751                         AOP(result)->aopu.aop_dir);
5752                     pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5753                         AOP(right)->aopu.aop_dir,
5754                         AOP(right)->aopu.aop_dir);
5755                     pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5756                         AOP(result)->aopu.aop_dir,
5757                         AOP(result)->aopu.aop_dir);
5758                 } else {
5759                     if( AOP_TYPE(result) == AOP_ACC) {
5760                         emitpcode(POC_MOVLW, popGetLit(0));
5761                         emitpcode(POC_BTFSS, popGet(AOP(right),0));
5762                         emitpcode(POC_BTFSC, popGet(AOP(left),0));
5763                         emitpcode(POC_MOVLW, popGetLit(1));
5764
5765                     } else {
5766
5767                         emitpcode(POC_BCF,   popGet(AOP(result),0));
5768                         emitpcode(POC_BTFSS, popGet(AOP(right),0));
5769                         emitpcode(POC_BTFSC, popGet(AOP(left),0));
5770                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5771
5772                         pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5773                             AOP(result)->aopu.aop_dir,
5774                             AOP(result)->aopu.aop_dir);
5775                         pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5776                             AOP(right)->aopu.aop_dir,
5777                             AOP(right)->aopu.aop_dir);
5778                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5779                             AOP(left)->aopu.aop_dir,
5780                             AOP(left)->aopu.aop_dir);
5781                         pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5782                             AOP(result)->aopu.aop_dir,
5783                             AOP(result)->aopu.aop_dir);
5784                     }
5785                 }
5786             } else {
5787                 // c = bit | val;
5788                 symbol *tlbl = newiTempLabel(NULL);
5789                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5790
5791
5792                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5793                 if( AOP_TYPE(right) == AOP_ACC) {
5794                     emitpcode(POC_IORLW, popGetLit(0));
5795                     emitSKPNZ;
5796                     emitpcode(POC_BTFSC, popGet(AOP(left),0));
5797                     emitpcode(POC_BSF,   popGet(AOP(result),0));
5798                 }
5799
5800
5801
5802                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5803                     pic14_emitcode(";XXX setb","c");
5804                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5805                     AOP(left)->aopu.aop_dir,tlbl->key+100);
5806                 pic14_toBoolean(right);
5807                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5808                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5809                     jmpTrueOrFalse(ifx, tlbl);
5810                     goto release;
5811                 } else {
5812                     CLRC;
5813                     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5814                 }
5815             }
5816         }
5817         // bit = c
5818         // val = c
5819         if(size)
5820             pic14_outBitC(result);
5821         // if(bit | ...)
5822         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5823             genIfxJump(ifx, "c");
5824         goto release ;
5825     }
5826
5827     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5828     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5829     if((AOP_TYPE(right) == AOP_LIT) &&
5830       (AOP_TYPE(result) == AOP_CRY) &&
5831       (AOP_TYPE(left) != AOP_CRY)){
5832         if(lit){
5833             pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5834             // result = 1
5835             if(size)
5836                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5837             else
5838                 continueIfTrue(ifx);
5839             goto release;
5840         } else {
5841             pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5842             // lit = 0, result = boolean(left)
5843             if(size)
5844                 pic14_emitcode(";XXX setb","c");
5845             pic14_toBoolean(right);
5846             if(size){
5847                 symbol *tlbl = newiTempLabel(NULL);
5848                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5849                 CLRC;
5850                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5851             } else {
5852                 genIfxJump (ifx,"a");
5853                 goto release;
5854             }
5855         }
5856         pic14_outBitC(result);
5857         goto release ;
5858     }
5859
5860     /* if left is same as result */
5861     if(pic14_sameRegs(AOP(result),AOP(left))){
5862         int know_W = -1;
5863         for(;size--; offset++,lit>>=8) {
5864             if(AOP_TYPE(right) == AOP_LIT){
5865                 if((lit & 0xff) == 0)
5866                     /*  or'ing with 0 has no effect */
5867                     continue;
5868                 else {
5869                     int p = my_powof2(lit & 0xff);
5870                     if(p>=0) {
5871                         /* only one bit is set in the literal, so use a bsf instruction */
5872                         emitpcode(POC_BSF,
5873                             newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5874                     } else {
5875                         if(know_W != (int)(lit & 0xff))
5876                             emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5877                         know_W = lit & 0xff;
5878                         emitpcode(POC_IORWF, popGet(AOP(left),offset));
5879                     }
5880
5881                 }
5882             } else {
5883                 if (AOP_TYPE(left) == AOP_ACC) {
5884                     emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5885                     pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5886                 } else {
5887                     emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5888                     emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5889
5890                     pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5891                     pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5892
5893                 }
5894             }
5895         }
5896     } else {
5897         // left & result in different registers
5898         if(AOP_TYPE(result) == AOP_CRY){
5899             // result = bit
5900             // if(size), result in bit
5901             // if(!size && ifx), conditional oper: if(left | right)
5902             symbol *tlbl = newiTempLabel(NULL);
5903             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5904             pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5905
5906
5907             if(size)
5908                 pic14_emitcode(";XXX setb","c");
5909             while(sizer--){
5910                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5911                 pic14_emitcode(";XXX orl","a,%s",
5912                     aopGet(AOP(left),offset,FALSE,FALSE));
5913                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5914                 offset++;
5915             }
5916             if(size){
5917                 CLRC;
5918                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5919                 pic14_outBitC(result);
5920             } else if(ifx)
5921                 jmpTrueOrFalse(ifx, tlbl);
5922         } else for(;(size--);offset++){
5923             // normal case
5924             // result = left | right
5925             if(AOP_TYPE(right) == AOP_LIT){
5926                 int t = (lit >> (offset*8)) & 0x0FFL;
5927                 switch(t) {
5928                 case 0x00:
5929                     if (AOP_TYPE(left) != AOP_ACC) {
5930                         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
5931                     }
5932                     emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5933
5934                     break;
5935                 default:
5936                     if (AOP_TYPE(left) == AOP_ACC) {
5937                         emitpcode(POC_IORLW,  popGetLit(t));
5938                     } else {
5939                         emitpcode(POC_MOVLW,  popGetLit(t));
5940                         emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5941                     }
5942                     emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5943                 }
5944                 continue;
5945             }
5946
5947             // faster than result <- left, anl result,right
5948             // and better if result is SFR
5949             if (AOP_TYPE(left) == AOP_ACC) {
5950                 emitpcode(POC_IORFW,popGet(AOP(right),offset));
5951             } else {
5952                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5953                 emitpcode(POC_IORFW,popGet(AOP(left),offset));
5954             }
5955             emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5956         }
5957     }
5958
5959 release :
5960     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5961     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5962     freeAsmop(result,NULL,ic,TRUE);
5963 }
5964
5965 /*-----------------------------------------------------------------*/
5966 /* genXor - code for xclusive or                                   */
5967 /*-----------------------------------------------------------------*/
5968 static void genXor (iCode *ic, iCode *ifx)
5969 {
5970     operand *left, *right, *result;
5971     int size, offset=0;
5972     unsigned long lit = 0L;
5973
5974     FENTRY;
5975     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5976
5977     aopOp((left = IC_LEFT(ic)),ic,FALSE);
5978     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5979     aopOp((result=IC_RESULT(ic)),ic,TRUE);
5980
5981     /* if left is a literal & right is not ||
5982     if left needs acc & right does not */
5983     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5984         (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5985         operand *tmp = right ;
5986         right = left;
5987         left = tmp;
5988     }
5989
5990     /* if result = right then exchange them */
5991     if(pic14_sameRegs(AOP(result),AOP(right))){
5992         operand *tmp = right ;
5993         right = left;
5994         left = tmp;
5995     }
5996
5997     /* if right is bit then exchange them */
5998     if (AOP_TYPE(right) == AOP_CRY &&
5999         AOP_TYPE(left) != AOP_CRY){
6000         operand *tmp = right ;
6001         right = left;
6002         left = tmp;
6003     }
6004     if(AOP_TYPE(right) == AOP_LIT)
6005         lit = ulFromVal (AOP(right)->aopu.aop_lit);
6006
6007     size = AOP_SIZE(result);
6008
6009     // if(bit ^ yy)
6010     // xx = bit ^ yy;
6011     if (AOP_TYPE(left) == AOP_CRY){
6012         if(AOP_TYPE(right) == AOP_LIT){
6013             // c = bit & literal;
6014             if(lit>>1){
6015                 // lit>>1  != 0 => result = 1
6016                 if(AOP_TYPE(result) == AOP_CRY){
6017                     if(size)
6018                     {emitpcode(POC_BSF,  popGet(AOP(result),offset));
6019                     pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6020                     else if(ifx)
6021                         continueIfTrue(ifx);
6022                     goto release;
6023                 }
6024                 pic14_emitcode("setb","c");
6025             } else{
6026                 // lit == (0 or 1)
6027                 if(lit == 0){
6028                     // lit == 0, result = left
6029                     if(size && pic14_sameRegs(AOP(result),AOP(left)))
6030                         goto release;
6031                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6032                 } else{
6033                     // lit == 1, result = not(left)
6034                     if(size && pic14_sameRegs(AOP(result),AOP(left))){
6035                         emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
6036                         emitpcode(POC_XORWF,  popGet(AOP(result),offset));
6037                         pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6038                         goto release;
6039                     } else {
6040                         assert ( !"incomplete genXor" );
6041                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6042                         pic14_emitcode("cpl","c");
6043                     }
6044                 }
6045             }
6046
6047         } else {
6048             // right != literal
6049             symbol *tlbl = newiTempLabel(NULL);
6050             if (AOP_TYPE(right) == AOP_CRY){
6051                 // c = bit ^ bit;
6052                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6053             }
6054             else{
6055                 int sizer = AOP_SIZE(right);
6056                 // c = bit ^ val
6057                 // if val>>1 != 0, result = 1
6058                 pic14_emitcode("setb","c");
6059                 while(sizer){
6060                     MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6061                     if(sizer == 1)
6062                         // test the msb of the lsb
6063                         pic14_emitcode("anl","a,#0xfe");
6064                     pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6065                     sizer--;
6066                 }
6067                 // val = (0,1)
6068                 pic14_emitcode("rrc","a");
6069             }
6070             pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6071             pic14_emitcode("cpl","c");
6072             pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6073         }
6074         // bit = c
6075         // val = c
6076         if(size)
6077             pic14_outBitC(result);
6078         // if(bit | ...)
6079         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6080             genIfxJump(ifx, "c");
6081         goto release ;
6082     }
6083
6084     if(pic14_sameRegs(AOP(result),AOP(left))){
6085         /* if left is same as result */
6086         for(;size--; offset++) {
6087             if(AOP_TYPE(right) == AOP_LIT){
6088                 int t  = (lit >> (offset*8)) & 0x0FFL;
6089                 if(t == 0x00L)
6090                     continue;
6091                 else
6092                     if (IS_AOP_PREG(left)) {
6093                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6094                         pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6095                         aopPut(AOP(result),"a",offset);
6096                     } else {
6097                         emitpcode(POC_MOVLW, popGetLit(t));
6098                         emitpcode(POC_XORWF,popGet(AOP(left),offset));
6099                         pic14_emitcode("xrl","%s,%s",
6100                             aopGet(AOP(left),offset,FALSE,TRUE),
6101                             aopGet(AOP(right),offset,FALSE,FALSE));
6102                     }
6103             } else {
6104                 if (AOP_TYPE(left) == AOP_ACC)
6105                     pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6106                 else {
6107                     emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6108                     emitpcode(POC_XORWF,popGet(AOP(left),offset));
6109                     /*
6110                     if (IS_AOP_PREG(left)) {
6111                     pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6112                     aopPut(AOP(result),"a",offset);
6113                     } else
6114                     pic14_emitcode("xrl","%s,a",
6115                     aopGet(AOP(left),offset,FALSE,TRUE));
6116                     */
6117                 }
6118             }
6119         }
6120     } else {
6121         // left & result in different registers
6122         if(AOP_TYPE(result) == AOP_CRY){
6123             // result = bit
6124             // if(size), result in bit
6125             // if(!size && ifx), conditional oper: if(left ^ right)
6126             symbol *tlbl = newiTempLabel(NULL);
6127             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6128             if(size)
6129                 pic14_emitcode("setb","c");
6130             while(sizer--){
6131                 if((AOP_TYPE(right) == AOP_LIT) &&
6132                     (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6133                     MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6134                 } else {
6135                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6136                     pic14_emitcode("xrl","a,%s",
6137                         aopGet(AOP(left),offset,FALSE,FALSE));
6138                 }
6139                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6140                 offset++;
6141             }
6142             if(size){
6143                 CLRC;
6144                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6145                 pic14_outBitC(result);
6146             } else if(ifx)
6147                 jmpTrueOrFalse(ifx, tlbl);
6148         } else for(;(size--);offset++){
6149             // normal case
6150             // result = left & right
6151             if(AOP_TYPE(right) == AOP_LIT){
6152                 int t = (lit >> (offset*8)) & 0x0FFL;
6153                 switch(t) {
6154                 case 0x00:
6155                     if (AOP_TYPE(left) != AOP_ACC) {
6156                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6157                     }
6158                     emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6159                     pic14_emitcode("movf","%s,w",
6160                         aopGet(AOP(left),offset,FALSE,FALSE));
6161                     pic14_emitcode("movwf","%s",
6162                         aopGet(AOP(result),offset,FALSE,FALSE));
6163                     break;
6164                 case 0xff:
6165                     if (AOP_TYPE(left) == AOP_ACC) {
6166                         emitpcode(POC_XORLW, popGetLit(t));
6167                     } else {
6168                         emitpcode(POC_COMFW,popGet(AOP(left),offset));
6169                     }
6170                     emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6171                     break;
6172                 default:
6173                     if (AOP_TYPE(left) == AOP_ACC) {
6174                         emitpcode(POC_XORLW, popGetLit(t));
6175                     } else {
6176                         emitpcode(POC_MOVLW, popGetLit(t));
6177                         emitpcode(POC_XORFW,popGet(AOP(left),offset));
6178                     }
6179                     emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6180                     pic14_emitcode("movlw","0x%x",t);
6181                     pic14_emitcode("xorwf","%s,w",
6182                         aopGet(AOP(left),offset,FALSE,FALSE));
6183                     pic14_emitcode("movwf","%s",
6184                         aopGet(AOP(result),offset,FALSE,FALSE));
6185
6186                 }
6187                 continue;
6188             }
6189
6190             // faster than result <- left, anl result,right
6191             // and better if result is SFR
6192             if (AOP_TYPE(left) == AOP_ACC) {
6193                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6194             } else {
6195                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6196                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6197             }
6198             if ( AOP_TYPE(result) != AOP_ACC){
6199                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6200             }
6201         }
6202     }
6203
6204 release :
6205     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6206     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6207     freeAsmop(result,NULL,ic,TRUE);
6208 }
6209
6210 /*-----------------------------------------------------------------*/
6211 /* genInline - write the inline code out                           */
6212 /*-----------------------------------------------------------------*/
6213 static void genInline (iCode *ic)
6214 {
6215   char *buffer, *bp, *bp1;
6216   bool inComment = FALSE;
6217
6218   FENTRY;
6219   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6220
6221   _G.inLine += (!options.asmpeep);
6222
6223   buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
6224
6225   while (*bp)
6226     {
6227       switch (*bp)
6228         {
6229         case ';':
6230           inComment = TRUE;
6231           ++bp;
6232           break;
6233
6234         case '\n':
6235           inComment = FALSE;
6236           *bp++ = '\0';
6237           if (*bp1)
6238             addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6239           bp1 = bp;
6240           break;
6241
6242         default:
6243           /* Add \n for labels, not dirs such as c:\mydir */
6244           if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
6245             {
6246               ++bp;
6247               *bp = '\0';
6248               ++bp;
6249               /* print label, use this special format with NULL directive
6250                * to denote that the argument should not be indented with tab */
6251               addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6252               bp1 = bp;
6253             }
6254           else
6255             ++bp;
6256           break;
6257         }
6258     }
6259   if ((bp1 != bp) && *bp1)
6260     addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6261
6262   Safe_free (buffer);
6263
6264   _G.inLine -= (!options.asmpeep);
6265 }
6266
6267 /*-----------------------------------------------------------------*/
6268 /* genRRC - rotate right with carry                                */
6269 /*-----------------------------------------------------------------*/
6270 static void genRRC (iCode *ic)
6271 {
6272     operand *left , *result ;
6273     int size, offset = 0, same;
6274
6275     FENTRY;
6276     /* rotate right with carry */
6277     left = IC_LEFT(ic);
6278     result=IC_RESULT(ic);
6279     aopOp (left,ic,FALSE);
6280     aopOp (result,ic,FALSE);
6281
6282     DEBUGpic14_AopType(__LINE__,left,NULL,result);
6283
6284     same = pic14_sameRegs(AOP(result),AOP(left));
6285
6286     size = AOP_SIZE(result);
6287
6288     /* get the lsb and put it into the carry */
6289     emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6290
6291     offset = 0 ;
6292
6293     while(size--) {
6294
6295         if(same) {
6296             emitpcode(POC_RRF, popGet(AOP(left),offset));
6297         } else {
6298             emitpcode(POC_RRFW, popGet(AOP(left),offset));
6299             emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6300         }
6301
6302         offset++;
6303     }
6304
6305     freeAsmop(left,NULL,ic,TRUE);
6306     freeAsmop(result,NULL,ic,TRUE);
6307 }
6308
6309 /*-----------------------------------------------------------------*/
6310 /* genRLC - generate code for rotate left with carry               */
6311 /*-----------------------------------------------------------------*/
6312 static void genRLC (iCode *ic)
6313 {
6314     operand *left , *result ;
6315     int size, offset = 0;
6316     int same;
6317
6318     FENTRY;
6319     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6320     /* rotate right with carry */
6321     left = IC_LEFT(ic);
6322     result=IC_RESULT(ic);
6323     aopOp (left,ic,FALSE);
6324     aopOp (result,ic,FALSE);
6325
6326     DEBUGpic14_AopType(__LINE__,left,NULL,result);
6327
6328     same = pic14_sameRegs(AOP(result),AOP(left));
6329
6330     /* move it to the result */
6331     size = AOP_SIZE(result);
6332
6333     /* get the msb and put it into the carry */
6334     emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6335
6336     offset = 0 ;
6337
6338     while(size--) {
6339
6340         if(same) {
6341             emitpcode(POC_RLF, popGet(AOP(left),offset));
6342         } else {
6343             emitpcode(POC_RLFW, popGet(AOP(left),offset));
6344             emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6345         }
6346
6347         offset++;
6348     }
6349
6350
6351     freeAsmop(left,NULL,ic,TRUE);
6352     freeAsmop(result,NULL,ic,TRUE);
6353 }
6354
6355 /*-----------------------------------------------------------------*/
6356 /* genGetHbit - generates code get highest order bit               */
6357 /*-----------------------------------------------------------------*/
6358 static void genGetHbit (iCode *ic)
6359 {
6360     operand *left, *result;
6361     left = IC_LEFT(ic);
6362     result=IC_RESULT(ic);
6363     aopOp (left,ic,FALSE);
6364     aopOp (result,ic,FALSE);
6365
6366     FENTRY;
6367     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6368     /* get the highest order byte into a */
6369     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6370     if(AOP_TYPE(result) == AOP_CRY){
6371         pic14_emitcode("rlc","a");
6372         pic14_outBitC(result);
6373     }
6374     else{
6375         pic14_emitcode("rl","a");
6376         pic14_emitcode("anl","a,#0x01");
6377         pic14_outAcc(result);
6378     }
6379
6380
6381     freeAsmop(left,NULL,ic,TRUE);
6382     freeAsmop(result,NULL,ic,TRUE);
6383 }
6384
6385 /*-----------------------------------------------------------------*/
6386 /* AccLsh - shift left accumulator by known count                  */
6387 /* MARK: pic14 always rotates through CARRY!                       */
6388 /*-----------------------------------------------------------------*/
6389 static void AccLsh (pCodeOp *pcop,int shCount)
6390 {
6391     FENTRY;
6392     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6393     shCount &= 0x0007;              // shCount : 0..7
6394     switch(shCount){
6395     case 0 :
6396         return;
6397         break;
6398     case 1 :
6399         emitCLRC;
6400         emitpcode(POC_RLF,pcop);
6401         return;
6402         break;
6403     case 2 :
6404         emitpcode(POC_RLF,pcop);
6405         emitpcode(POC_RLF,pcop);
6406         break;
6407     case 3 :
6408         emitpcode(POC_RLF,pcop);
6409         emitpcode(POC_RLF,pcop);
6410         emitpcode(POC_RLF,pcop);
6411         break;
6412     case 4 :
6413         emitpcode(POC_SWAPF,pcop);
6414         break;
6415     case 5 :
6416         emitpcode(POC_SWAPF,pcop);
6417         emitpcode(POC_RLF,pcop);
6418         break;
6419     case 6 :
6420         emitpcode(POC_SWAPF,pcop);
6421         emitpcode(POC_RLF,pcop);
6422         emitpcode(POC_RLF,pcop);
6423         break;
6424     case 7 :
6425         emitpcode(POC_RRFW,pcop);
6426         emitpcode(POC_RRF,pcop);
6427         break;
6428     }
6429     /* clear invalid bits */
6430     emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6431     emitpcode(POC_ANDWF, pcop);
6432 }
6433
6434 /*-----------------------------------------------------------------*/
6435 /* AccRsh - shift right accumulator by known count                 */
6436 /* MARK: pic14 always rotates through CARRY!                       */
6437 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6438 /*            1: mask out invalid bits (zero-extend)               */
6439 /*            2: sign-extend result (pretty slow)                  */
6440 /*-----------------------------------------------------------------*/
6441 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6442 {
6443     FENTRY;
6444     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6445     shCount &= 0x0007;              // shCount : 0..7
6446     switch(shCount){
6447     case 0 :
6448         return;
6449         break;
6450     case 1 :
6451         /* load sign if needed */
6452         if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6453         else if (mask_mode == 1) emitCLRC;
6454         emitpcode(POC_RRF,pcop);
6455         return;
6456         break;
6457     case 2 :
6458         /* load sign if needed */
6459         if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6460         emitpcode(POC_RRF,pcop);
6461         /* load sign if needed */
6462         if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6463         emitpcode(POC_RRF,pcop);
6464         if (mask_mode == 2) return;
6465         break;
6466     case 3 :
6467         /* load sign if needed */
6468         if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6469         emitpcode(POC_RRF,pcop);
6470         /* load sign if needed */
6471         if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6472         emitpcode(POC_RRF,pcop);
6473         /* load sign if needed */
6474         if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6475         emitpcode(POC_RRF,pcop);
6476         if (mask_mode == 2) return;
6477         break;
6478     case 4 :
6479         emitpcode(POC_SWAPF,pcop);
6480         break;
6481     case 5 :
6482         emitpcode(POC_SWAPF,pcop);
6483         emitpcode(POC_RRF,pcop);
6484         break;
6485     case 6 :
6486         emitpcode(POC_SWAPF,pcop);
6487         emitpcode(POC_RRF,pcop);
6488         emitpcode(POC_RRF,pcop);
6489         break;
6490     case 7 :
6491         if (mask_mode == 2)
6492         {
6493             /* load sign */
6494             emitpcode(POC_RLFW,pcop);
6495             emitpcode(POC_CLRF,pcop);
6496             emitSKPNC;
6497             emitpcode(POC_COMF,pcop);
6498             return;
6499         } else {
6500             emitpcode(POC_RLFW,pcop);
6501             emitpcode(POC_RLF,pcop);
6502         }
6503         break;
6504     }
6505
6506     if (mask_mode == 0)
6507     {
6508         /* leave invalid bits undefined */
6509         return;
6510     }
6511
6512     /* clear invalid bits -- zero-extend */
6513     emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6514     emitpcode(POC_ANDWF, pcop);
6515
6516     if (mask_mode == 2) {
6517       /* sign-extend */
6518       emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6519       emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6520       emitpcode(POC_IORWF, pcop);
6521     }
6522 }
6523
6524 #if 0
6525 /*-----------------------------------------------------------------*/
6526 /* AccSRsh - signed right shift accumulator by known count                 */
6527 /*-----------------------------------------------------------------*/
6528 static void AccSRsh (int shCount)
6529 {
6530     symbol *tlbl ;
6531     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6532     if(shCount != 0){
6533         if(shCount == 1){
6534             pic14_emitcode("mov","c,acc.7");
6535             pic14_emitcode("rrc","a");
6536         } else if(shCount == 2){
6537             pic14_emitcode("mov","c,acc.7");
6538             pic14_emitcode("rrc","a");
6539             pic14_emitcode("mov","c,acc.7");
6540             pic14_emitcode("rrc","a");
6541         } else {
6542             tlbl = newiTempLabel(NULL);
6543             /* rotate right accumulator */
6544             AccRol(8 - shCount);
6545             /* and kill the higher order bits */
6546             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6547             pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6548             pic14_emitcode("orl","a,#0x%02x",
6549                 (unsigned char)~SRMask[shCount]);
6550             pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6551         }
6552     }
6553 }
6554
6555 /*-----------------------------------------------------------------*/
6556 /* shiftR1Left2Result - shift right one byte from left to result   */
6557 /*-----------------------------------------------------------------*/
6558 static void shiftR1Left2ResultSigned (operand *left, int offl,
6559                                       operand *result, int offr,
6560                                       int shCount)
6561 {
6562     int same;
6563
6564     FENTRY;
6565     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6566
6567     same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6568
6569     switch(shCount) {
6570     case 1:
6571         emitpcode(POC_RLFW, popGet(AOP(left),offl));
6572         if(same)
6573             emitpcode(POC_RRF, popGet(AOP(result),offr));
6574         else {
6575             emitpcode(POC_RRFW, popGet(AOP(left),offl));
6576             emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6577         }
6578
6579         break;
6580     case 2:
6581
6582         emitpcode(POC_RLFW, popGet(AOP(left),offl));
6583         if(same)
6584             emitpcode(POC_RRF, popGet(AOP(result),offr));
6585         else {
6586             emitpcode(POC_RRFW, popGet(AOP(left),offl));
6587             emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6588         }
6589         emitpcode(POC_RLFW, popGet(AOP(result),offr));
6590         emitpcode(POC_RRF,  popGet(AOP(result),offr));
6591
6592         break;
6593
6594     case 3:
6595         if(same)
6596             emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6597         else {
6598             emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6599             emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6600         }
6601
6602         emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6603         emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6604         emitpcode(POC_ANDLW, popGetLit(0x1f));
6605
6606         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6607         emitpcode(POC_IORLW, popGetLit(0xe0));
6608
6609         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6610         break;
6611
6612     case 4:
6613         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6614         emitpcode(POC_ANDLW,  popGetLit(0x0f));
6615         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6616         emitpcode(POC_IORLW,  popGetLit(0xf0));
6617         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6618         break;
6619     case 5:
6620         if(same) {
6621             emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6622         } else {
6623             emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6624             emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6625         }
6626         emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6627         emitpcode(POC_ANDLW,  popGetLit(0x07));
6628         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6629         emitpcode(POC_IORLW,  popGetLit(0xf8));
6630         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6631         break;
6632
6633     case 6:
6634         if(same) {
6635             emitpcode(POC_MOVLW, popGetLit(0x00));
6636             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6637             emitpcode(POC_MOVLW, popGetLit(0xfe));
6638             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6639             emitpcode(POC_IORLW, popGetLit(0x01));
6640             emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6641         } else {
6642             emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6643             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6644             emitpcode(POC_DECF,  popGet(AOP(result),offr));
6645             emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6646             emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6647         }
6648         break;
6649
6650     case 7:
6651         if(same) {
6652             emitpcode(POC_MOVLW, popGetLit(0x00));
6653             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6654             emitpcode(POC_MOVLW, popGetLit(0xff));
6655             emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6656         } else {
6657             emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6658             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6659             emitpcode(POC_DECF,  popGet(AOP(result),offr));
6660         }
6661
6662     default:
6663         break;
6664     }
6665 }
6666
6667 /*-----------------------------------------------------------------*/
6668 /* shiftR1Left2Result - shift right one byte from left to result   */
6669 /*-----------------------------------------------------------------*/
6670 static void shiftR1Left2Result (operand *left, int offl,
6671                                 operand *result, int offr,
6672                                 int shCount, int sign)
6673 {
6674     int same;
6675
6676     FENTRY;
6677     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6678
6679     same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6680
6681     /* Copy the msb into the carry if signed. */
6682     if(sign) {
6683         shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6684         return;
6685     }
6686
6687
6688
6689     switch(shCount) {
6690     case 1:
6691         emitCLRC;
6692         if(same)
6693             emitpcode(POC_RRF, popGet(AOP(result),offr));
6694         else {
6695             emitpcode(POC_RRFW, popGet(AOP(left),offl));
6696             emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6697         }
6698         break;
6699     case 2:
6700         emitCLRC;
6701         if(same) {
6702             emitpcode(POC_RRF, popGet(AOP(result),offr));
6703         } else {
6704             emitpcode(POC_RRFW, popGet(AOP(left),offl));
6705             emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6706         }
6707         emitCLRC;
6708         emitpcode(POC_RRF, popGet(AOP(result),offr));
6709
6710         break;
6711     case 3:
6712         if(same)
6713             emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6714         else {
6715             emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6716             emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6717         }
6718
6719         emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6720         emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6721         emitpcode(POC_ANDLW, popGetLit(0x1f));
6722         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6723         break;
6724
6725     case 4:
6726         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6727         emitpcode(POC_ANDLW, popGetLit(0x0f));
6728         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6729         break;
6730
6731     case 5:
6732         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6733         emitpcode(POC_ANDLW, popGetLit(0x0f));
6734         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6735         emitCLRC;
6736         emitpcode(POC_RRF, popGet(AOP(result),offr));
6737
6738         break;
6739     case 6:
6740
6741         emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6742         emitpcode(POC_ANDLW, popGetLit(0x80));
6743         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6744         emitpcode(POC_RLF,   popGet(AOP(result),offr));
6745         emitpcode(POC_RLF,   popGet(AOP(result),offr));
6746         break;
6747
6748     case 7:
6749
6750         emitpcode(POC_RLFW, popGet(AOP(left),offl));
6751         emitpcode(POC_CLRF, popGet(AOP(result),offr));
6752         emitpcode(POC_RLF,  popGet(AOP(result),offr));
6753
6754         break;
6755
6756     default:
6757         break;
6758     }
6759 }
6760
6761 /*-----------------------------------------------------------------*/
6762 /* shiftL1Left2Result - shift left one byte from left to result    */
6763 /*-----------------------------------------------------------------*/
6764 static void shiftL1Left2Result (operand *left, int offl,
6765                                 operand *result, int offr, int shCount)
6766 {
6767     int same;
6768
6769     //    char *l;
6770     FENTRY;
6771     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6772
6773     same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6774     DEBUGpic14_emitcode ("; ***","same =  %d",same);
6775     //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6776     //    MOVA(l);
6777     /* shift left accumulator */
6778     //AccLsh(shCount); // don't comment out just yet...
6779     //    aopPut(AOP(result),"a",offr);
6780
6781     switch(shCount) {
6782     case 1:
6783         /* Shift left 1 bit position */
6784         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6785         if(same) {
6786             emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6787         } else {
6788             emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6789             emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6790         }
6791         break;
6792     case 2:
6793         emitpcode(POC_RLFW, popGet(AOP(left),offl));
6794         emitpcode(POC_ANDLW,popGetLit(0x7e));
6795         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6796         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6797         break;
6798     case 3:
6799         emitpcode(POC_RLFW, popGet(AOP(left),offl));
6800         emitpcode(POC_ANDLW,popGetLit(0x3e));
6801         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6802         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6803         emitpcode(POC_RLF,  popGet(AOP(result),offr));
6804         break;
6805     case 4:
6806         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6807         emitpcode(POC_ANDLW, popGetLit(0xf0));
6808         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6809         break;
6810     case 5:
6811         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6812         emitpcode(POC_ANDLW, popGetLit(0xf0));
6813         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6814         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6815         break;
6816     case 6:
6817         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6818         emitpcode(POC_ANDLW, popGetLit(0x30));
6819         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6820         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6821         emitpcode(POC_RLF,  popGet(AOP(result),offr));
6822         break;
6823     case 7:
6824         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6825         emitpcode(POC_CLRF, popGet(AOP(result),offr));
6826         emitpcode(POC_RRF,  popGet(AOP(result),offr));
6827         break;
6828
6829     default:
6830         DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6831     }
6832
6833 }
6834 #endif
6835
6836 /*-----------------------------------------------------------------*/
6837 /* movLeft2Result - move byte from left to result                  */
6838 /*-----------------------------------------------------------------*/
6839 static void movLeft2Result (operand *left, int offl,
6840                             operand *result, int offr)
6841 {
6842     char *l;
6843     FENTRY;
6844     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6845     if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6846         l = aopGet(AOP(left),offl,FALSE,FALSE);
6847
6848         if (*l == '@' && (IS_AOP_PREG(result))) {
6849             pic14_emitcode("mov","a,%s",l);
6850             aopPut(AOP(result),"a",offr);
6851         } else {
6852             emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6853             emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6854         }
6855     }
6856 }
6857
6858 /*-----------------------------------------------------------------*/
6859 /* shiftLeft_Left2ResultLit - shift left by known count            */
6860 /*-----------------------------------------------------------------*/
6861
6862 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6863 {
6864     int size, same, offr, i;
6865
6866     size = AOP_SIZE(left);
6867     if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6868
6869     same = pic14_sameRegs (AOP(left), AOP(result));
6870
6871     offr = shCount / 8;
6872     shCount = shCount & 0x07;
6873
6874     size -= offr;
6875
6876     switch (shCount)
6877     {
6878     case 0: /* takes 0 or 2N cycles (for offr==0) */
6879         if (!same || offr) {
6880             for (i=size-1; i >= 0; i--)
6881                 movLeft2Result (left, i, result, offr + i);
6882         } // if
6883         break;
6884
6885     case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6886         if (same && offr) {
6887             shiftLeft_Left2ResultLit (left, result, 8 * offr);
6888             shiftLeft_Left2ResultLit (result, result, shCount);
6889             return; /* prevent clearing result again */
6890         } else {
6891             emitCLRC;
6892             for (i=0; i < size; i++) {
6893                 if (same && !offr) {
6894                     emitpcode (POC_RLF, popGet (AOP(left), i));
6895                 } else {
6896                     emitpcode (POC_RLFW, popGet (AOP(left), i));
6897                     emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6898                 } // if
6899             } // for
6900         } // if (offr)
6901         break;
6902
6903     case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6904         /* works in-place/with offr as well */
6905         emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6906         emitpcode (POC_ANDLW, popGetLit (0xF0));
6907         emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6908
6909         for (i = size - 2; i >= 0; i--)
6910         {
6911             emitpcode (POC_SWAPFW, popGet (AOP(left), i));
6912             emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6913             emitpcode (POC_ANDLW, popGetLit (0x0F));
6914             emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
6915             emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
6916         } // for i
6917         break;
6918
6919     case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
6920         /* works in-place/with offr as well */
6921         emitpcode (POC_RRFW, popGet (AOP(left), size-1));
6922         for (i = size-2; i >= 0; i--) {
6923             emitpcode (POC_RRFW, popGet (AOP(left), i));
6924             emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
6925         } // for i
6926         emitpcode (POC_CLRF, popGet (AOP(result), offr));
6927         emitpcode (POC_RRF, popGet (AOP(result), offr));
6928         break;
6929
6930     default:
6931         shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
6932         shiftLeft_Left2ResultLit (result, result, 1);
6933         return; /* prevent clearing result again */
6934         break;
6935     } // switch
6936
6937     while (0 < offr--)
6938     {
6939         emitpcode (POC_CLRF, popGet (AOP(result), offr));
6940     } // while
6941 }
6942
6943 /*-----------------------------------------------------------------*/
6944 /* shiftRight_Left2ResultLit - shift right by known count          */
6945 /*-----------------------------------------------------------------*/
6946
6947 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
6948 {
6949     int size, same, offr, i;
6950
6951     size = AOP_SIZE(left);
6952     if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6953
6954     same = pic14_sameRegs (AOP(left), AOP(result));
6955
6956     offr = shCount / 8;
6957     shCount = shCount & 0x07;
6958
6959     size -= offr;
6960
6961     if (size)
6962     {
6963         switch (shCount)
6964         {
6965         case 0: /* takes 0 or 2N cycles (for offr==0) */
6966             if (!same || offr) {
6967                 for (i=0; i < size; i++)
6968                     movLeft2Result (left, i + offr, result, i);
6969             } // if
6970             break;
6971
6972         case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
6973             emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
6974             if (same && offr) {
6975                 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
6976                 shiftRight_Left2ResultLit (result, result, shCount, sign);
6977                 return; /* prevent sign-extending result again */
6978             } else {
6979                 emitCLRC;
6980                 if (sign) {
6981                     emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
6982                     emitSETC;
6983                 }
6984                 for (i = size-1; i >= 0; i--) {
6985                     if (same && !offr) {
6986                         emitpcode (POC_RRF, popGet (AOP(left), i));
6987                     } else {
6988                         emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
6989                         emitpcode (POC_MOVWF, popGet (AOP(result), i));
6990                     }
6991                 } // for i
6992             } // if (offr)
6993             break;
6994
6995         case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
6996             /* works in-place/with offr as well */
6997             emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
6998             emitpcode (POC_ANDLW, popGetLit (0x0F));
6999             emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7000
7001             for (i = 1; i < size; i++)
7002             {
7003                 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7004                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7005                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7006                 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7007                 emitpcode (POC_XORWF, popGet (AOP(result), i));
7008             } // for i
7009
7010             if (sign)
7011             {
7012                 emitpcode (POC_MOVLW, popGetLit (0xF0));
7013                 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7014                 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7015             } // if
7016             break;
7017
7018         case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7019             /* works in-place/with offr as well */
7020             emitpcode (POC_RLFW, popGet (AOP(left), offr));
7021             for (i = 0; i < size-1; i++) {
7022                 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7023                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7024             } // for i
7025             emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7026             if (!sign) {
7027                 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7028             } else {
7029                 emitSKPNC;
7030                 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7031             }
7032             break;
7033
7034         default:
7035             shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7036             shiftRight_Left2ResultLit (result, result, 1, sign);
7037             return; /* prevent sign extending result again */
7038             break;
7039         } // switch
7040     } // if
7041
7042     addSign (result, size, sign);
7043 }
7044
7045 #if 0
7046 /*-----------------------------------------------------------------*/
7047 /* shiftL2Left2Result - shift left two bytes from left to result   */
7048 /*-----------------------------------------------------------------*/
7049 static void shiftL2Left2Result (operand *left, int offl,
7050                                 operand *result, int offr, int shCount)
7051 {
7052     FENTRY;
7053
7054     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7055
7056     if(pic14_sameRegs(AOP(result), AOP(left))) {
7057         switch(shCount) {
7058         case 0:
7059             break;
7060         case 1:
7061         case 2:
7062         case 3:
7063
7064             emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7065             emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7066             emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7067
7068             while(--shCount) {
7069                 emitCLRC;
7070                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7071                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7072             }
7073
7074             break;
7075         case 4:
7076         case 5:
7077             emitpcode(POC_MOVLW, popGetLit(0x0f));
7078             emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7079             emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7080             emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7081             emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7082             emitpcode(POC_XORWF, popGet(AOP(result),offr));
7083             emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7084             if(shCount >=5) {
7085                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7086                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7087             }
7088             break;
7089         case 6:
7090             emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7091             emitpcode(POC_RRF,  popGet(AOP(result),offr));
7092             emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7093             emitpcode(POC_RRF,  popGet(AOP(result),offr));
7094             emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7095             emitpcode(POC_ANDLW,popGetLit(0xc0));
7096             emitpcode(POC_XORFW,popGet(AOP(result),offr));
7097             emitpcode(POC_XORWF,popGet(AOP(result),offr));
7098             emitpcode(POC_XORFW,popGet(AOP(result),offr));
7099             emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7100             break;
7101         case 7:
7102             emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7103             emitpcode(POC_RRFW, popGet(AOP(result),offr));
7104             emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7105             emitpcode(POC_CLRF, popGet(AOP(result),offr));
7106             emitpcode(POC_RRF,  popGet(AOP(result),offr));
7107         }
7108
7109     } else {
7110         switch(shCount) {
7111         case 0:
7112             break;
7113         case 1:
7114         case 2:
7115         case 3:
7116         /* note, use a mov/add for the shift since the mov has a
7117             chance of getting optimized out */
7118             emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7119             emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7120             emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7121             emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
7122             emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7123
7124             while(--shCount) {
7125                 emitCLRC;
7126                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7127                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7128             }
7129             break;
7130
7131         case 4:
7132         case 5:
7133             emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7134             emitpcode(POC_ANDLW, popGetLit(0xF0));
7135             emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7136             emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7137             emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7138             emitpcode(POC_ANDLW, popGetLit(0xF0));
7139             emitpcode(POC_XORWF, popGet(AOP(result),offr));
7140             emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7141
7142
7143             if(shCount == 5) {
7144                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7145                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7146             }
7147             break;
7148         case 6:
7149             emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7150             emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7151             emitpcode(POC_RRFW, popGet(AOP(result),offl));
7152             emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
7153
7154             emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7155             emitpcode(POC_RRF,  popGet(AOP(result),offr));
7156             emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7157             emitpcode(POC_ANDLW,popGetLit(0xc0));
7158             emitpcode(POC_XORFW,popGet(AOP(result),offr));
7159             emitpcode(POC_XORWF,popGet(AOP(result),offr));
7160             emitpcode(POC_XORFW,popGet(AOP(result),offr));
7161             emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7162             break;
7163         case 7:
7164             emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7165             emitpcode(POC_RRFW, popGet(AOP(left),offl));
7166             emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7167             emitpcode(POC_CLRF, popGet(AOP(result),offr));
7168             emitpcode(POC_RRF,  popGet(AOP(result),offr));
7169         }
7170     }
7171
7172 }
7173
7174 /*-----------------------------------------------------------------*/
7175 /* shiftR2Left2Result - shift right two bytes from left to result  */
7176 /*-----------------------------------------------------------------*/
7177 static void shiftR2Left2Result (operand *left, int offl,
7178                                 operand *result, int offr,
7179                                 int shCount, int sign)
7180 {
7181     int same=0;
7182
7183     FENTRY;
7184     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7185     same = pic14_sameRegs(AOP(result), AOP(left));
7186
7187     if(same && ((offl + MSB16) == offr)){
7188         same=1;
7189         /* don't crash result[offr] */
7190         MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7191         pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7192     }
7193     /* else {
7194     movLeft2Result(left,offl, result, offr);
7195     MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7196     }
7197     */
7198     /* a:x >> shCount (x = lsb(result))*/
7199     /*
7200     if(sign)
7201     AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7202     else {
7203     AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7204     */
7205     switch(shCount) {
7206     case 0:
7207         break;
7208     case 1:
7209     case 2:
7210     case 3:
7211         if(sign)
7212             emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7213         else
7214             emitCLRC;
7215
7216         if(same) {
7217             emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7218             emitpcode(POC_RRF,popGet(AOP(result),offr));
7219         } else {
7220             emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7221             emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7222             emitpcode(POC_RRFW, popGet(AOP(left),offl));
7223             emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7224         }
7225
7226         while(--shCount) {
7227             if(sign)
7228                 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7229             else
7230                 emitCLRC;
7231             emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7232             emitpcode(POC_RRF,popGet(AOP(result),offr));
7233         }
7234         break;
7235     case 4:
7236     case 5:
7237         if(same) {
7238
7239             emitpcode(POC_MOVLW, popGetLit(0xf0));
7240             emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7241             emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7242
7243             emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7244             emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7245             emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7246             emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7247         } else {
7248             emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7249             emitpcode(POC_ANDLW, popGetLit(0x0f));
7250             emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7251
7252             emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7253             emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7254             emitpcode(POC_ANDLW, popGetLit(0xf0));
7255             emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7256             emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7257         }
7258
7259         if(shCount >=5) {
7260             emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7261             emitpcode(POC_RRF, popGet(AOP(result),offr));
7262         }
7263
7264         if(sign) {
7265             emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7266             emitpcode(POC_BTFSC,
7267                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7268             emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7269         }
7270
7271         break;
7272
7273     case 6:
7274         if(same) {
7275
7276             emitpcode(POC_RLF,  popGet(AOP(result),offr));
7277             emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7278
7279             emitpcode(POC_RLF,  popGet(AOP(result),offr));
7280             emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7281             emitpcode(POC_RLFW, popGet(AOP(result),offr));
7282             emitpcode(POC_ANDLW,popGetLit(0x03));
7283             if(sign) {
7284                 emitpcode(POC_BTFSC,
7285                     newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7286                 emitpcode(POC_IORLW,popGetLit(0xfc));
7287             }
7288             emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7289             emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7290             emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7291             emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7292         } else {
7293             emitpcode(POC_RLFW, popGet(AOP(left),offl));
7294             emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7295             emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7296             emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7297             emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7298             emitpcode(POC_RLF,  popGet(AOP(result),offr));
7299             emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7300             emitpcode(POC_ANDLW,popGetLit(0x03));
7301             if(sign) {
7302                 emitpcode(POC_BTFSC,
7303                     newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7304                 emitpcode(POC_IORLW,popGetLit(0xfc));
7305             }
7306             emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7307             //emitpcode(POC_RLF,  popGet(AOP(result),offr));
7308
7309
7310         }
7311
7312         break;
7313     case 7:
7314         emitpcode(POC_RLFW, popGet(AOP(left),offl));
7315         emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7316         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7317         emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7318         if(sign) {
7319             emitSKPNC;
7320             emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7321         } else
7322             emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7323   }
7324 }
7325
7326 /*-----------------------------------------------------------------*/
7327 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7328 /*-----------------------------------------------------------------*/
7329 static void shiftLLeftOrResult (operand *left, int offl,
7330                                 operand *result, int offr, int shCount)
7331 {
7332     FENTRY;
7333     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7334
7335     /* shift left accumulator */
7336     AccLsh(left,offl,shCount);
7337     /* or with result */
7338     emitpcode (POC_IORWF, popGet (AOP(result), offr));
7339     assert ( !"broken (modifies left, fails for left==result))" );
7340 }
7341
7342 /*-----------------------------------------------------------------*/
7343 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7344 /*-----------------------------------------------------------------*/
7345 static void shiftRLeftOrResult (operand *left, int offl,
7346                                 operand *result, int offr, int shCount)
7347 {
7348     FENTRY;
7349     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7350
7351     /* shift right accumulator */
7352     AccRsh(left,offl,shCount);
7353     /* or with result */
7354     emitpcode (POC_IORWF, popGet (AOP(result), offr));
7355     assert ( !"broken (modifies left, fails for left==result))" );
7356 }
7357
7358 /*-----------------------------------------------------------------*/
7359 /* genlshOne - left shift a one byte quantity by known count       */
7360 /*-----------------------------------------------------------------*/
7361 static void genlshOne (operand *result, operand *left, int shCount)
7362 {
7363     FENTRY;
7364     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7365     shiftL1Left2Result(left, LSB, result, LSB, shCount);
7366 }
7367
7368 /*-----------------------------------------------------------------*/
7369 /* genlshTwo - left shift two bytes by known amount != 0           */
7370 /*-----------------------------------------------------------------*/
7371 static void genlshTwo (operand *result,operand *left, int shCount)
7372 {
7373     int size;
7374
7375     FENTRY;
7376     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7377     size = pic14_getDataSize(result);
7378
7379     /* if shCount >= 8 */
7380     if (shCount >= 8) {
7381         shCount -= 8 ;
7382
7383         if (size > 1){
7384             if (shCount)
7385                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7386             else
7387                 movLeft2Result(left, LSB, result, MSB16);
7388         }
7389         emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7390     }
7391
7392     /*  1 <= shCount <= 7 */
7393     else {
7394         if(size == 1)
7395             shiftL1Left2Result(left, LSB, result, LSB, shCount);
7396         else
7397             shiftL2Left2Result(left, LSB, result, LSB, shCount);
7398     }
7399 }
7400
7401 /*-----------------------------------------------------------------*/
7402 /* shiftLLong - shift left one long from left to result            */
7403 /* offl = LSB or MSB16                                             */
7404 /*-----------------------------------------------------------------*/
7405 static void shiftLLong (operand *left, operand *result, int offr )
7406 {
7407     char *l;
7408     int size = AOP_SIZE(result);
7409
7410     FENTRY;
7411     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7412     if(size >= LSB+offr){
7413         l = aopGet(AOP(left),LSB,FALSE,FALSE);
7414         MOVA(l);
7415         pic14_emitcode("add","a,acc");
7416         if (pic14_sameRegs(AOP(left),AOP(result)) &&
7417             size >= MSB16+offr && offr != LSB )
7418             pic14_emitcode("xch","a,%s",
7419             aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7420         else
7421             aopPut(AOP(result),"a",LSB+offr);
7422     }
7423
7424     if(size >= MSB16+offr){
7425         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7426             l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7427             MOVA(l);
7428         }
7429         pic14_emitcode("rlc","a");
7430         if (pic14_sameRegs(AOP(left),AOP(result)) &&
7431             size >= MSB24+offr && offr != LSB)
7432             pic14_emitcode("xch","a,%s",
7433             aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7434         else
7435             aopPut(AOP(result),"a",MSB16+offr);
7436     }
7437
7438     if(size >= MSB24+offr){
7439         if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7440             l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7441             MOVA(l);
7442         }
7443         pic14_emitcode("rlc","a");
7444         if (pic14_sameRegs(AOP(left),AOP(result)) &&
7445             size >= MSB32+offr && offr != LSB )
7446             pic14_emitcode("xch","a,%s",
7447             aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7448         else
7449             aopPut(AOP(result),"a",MSB24+offr);
7450     }
7451
7452     if(size > MSB32+offr){
7453         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7454             l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7455             MOVA(l);
7456         }
7457         pic14_emitcode("rlc","a");
7458         aopPut(AOP(result),"a",MSB32+offr);
7459     }
7460     if(offr != LSB)
7461         aopPut(AOP(result),zero,LSB);
7462 }
7463
7464 /*-----------------------------------------------------------------*/
7465 /* genlshFour - shift four byte by a known amount != 0             */
7466 /*-----------------------------------------------------------------*/
7467 static void genlshFour (operand *result, operand *left, int shCount)
7468 {
7469     int size;
7470
7471     FENTRY;
7472     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7473     size = AOP_SIZE(result);
7474
7475     /* if shifting more that 3 bytes */
7476     if (shCount >= 24 ) {
7477         shCount -= 24;
7478         if (shCount)
7479         /* lowest order of left goes to the highest
7480         order of the destination */
7481         shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7482         else
7483             movLeft2Result(left, LSB, result, MSB32);
7484         aopPut(AOP(result),zero,LSB);
7485         aopPut(AOP(result),zero,MSB16);
7486         aopPut(AOP(result),zero,MSB32);
7487         return;
7488     }
7489
7490     /* more than two bytes */
7491     else if ( shCount >= 16 ) {
7492         /* lower order two bytes goes to higher order two bytes */
7493         shCount -= 16;
7494         /* if some more remaining */
7495         if (shCount)
7496             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7497         else {
7498             movLeft2Result(left, MSB16, result, MSB32);
7499             movLeft2Result(left, LSB, result, MSB24);
7500         }
7501         aopPut(AOP(result),zero,MSB16);
7502         aopPut(AOP(result),zero,LSB);
7503         return;
7504     }
7505
7506     /* if more than 1 byte */
7507     else if ( shCount >= 8 ) {
7508         /* lower order three bytes goes to higher order  three bytes */
7509         shCount -= 8;
7510         if(size == 2){
7511             if(shCount)
7512                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7513             else
7514                 movLeft2Result(left, LSB, result, MSB16);
7515         }
7516         else{   /* size = 4 */
7517             if(shCount == 0){
7518                 movLeft2Result(left, MSB24, result, MSB32);
7519                 movLeft2Result(left, MSB16, result, MSB24);
7520                 movLeft2Result(left, LSB, result, MSB16);
7521                 aopPut(AOP(result),zero,LSB);
7522             }
7523             else if(shCount == 1)
7524                 shiftLLong(left, result, MSB16);
7525             else{
7526                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7527                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7528                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7529                 aopPut(AOP(result),zero,LSB);
7530             }
7531         }
7532     }
7533
7534     /* 1 <= shCount <= 7 */
7535     else if(shCount <= 2){
7536         shiftLLong(left, result, LSB);
7537         if(shCount == 2)
7538             shiftLLong(result, result, LSB);
7539     }
7540     /* 3 <= shCount <= 7, optimize */
7541     else{
7542         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7543         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7544         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7545     }
7546 }
7547 #endif
7548
7549 #if 0
7550 /*-----------------------------------------------------------------*/
7551 /* genLeftShiftLiteral - left shifting by known count              */
7552 /*-----------------------------------------------------------------*/
7553 static void genLeftShiftLiteral (operand *left,
7554                                  operand *right,
7555                                  operand *result,
7556                                  iCode *ic)
7557 {
7558     int shCount = (int) ulFromVal (AOP(right)->aopu.aop_lit);
7559     //int size;
7560
7561     FENTRY;
7562     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7563     freeAsmop(right,NULL,ic,TRUE);
7564
7565     aopOp(left,ic,FALSE);
7566     aopOp(result,ic,FALSE);
7567
7568     size = getSize(operandType(result));
7569
7570 #if VIEW_SIZE
7571     pic14_emitcode("; shift left ","result %d, left %d",size,
7572         AOP_SIZE(left));
7573 #endif
7574
7575     /* I suppose that the left size >= result size */
7576     if(shCount == 0){
7577         while(size--){
7578             movLeft2Result(left, size, result, size);
7579         }
7580     }
7581
7582     else if(shCount >= (size * 8))
7583         while(size--)
7584             aopPut(AOP(result),zero,size);
7585         else{
7586             switch (size) {
7587             case 1:
7588                 genlshOne (result,left,shCount);
7589                 break;
7590
7591             case 2:
7592             case 3:
7593                 genlshTwo (result,left,shCount);
7594                 break;
7595
7596             case 4:
7597                 genlshFour (result,left,shCount);
7598                 break;
7599             }
7600         }
7601         freeAsmop(left,NULL,ic,TRUE);
7602         freeAsmop(result,NULL,ic,TRUE);
7603 }
7604 #endif
7605
7606 /*-----------------------------------------------------------------*
7607 * genMultiAsm - repeat assembly instruction for size of register.
7608 * if endian == 1, then the high byte (i.e base address + size of
7609 * register) is used first else the low byte is used first;
7610 *-----------------------------------------------------------------*/
7611 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7612 {
7613
7614     int offset = 0;
7615
7616     FENTRY;
7617     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7618
7619     if(!reg)
7620         return;
7621
7622     if(!endian) {
7623         endian = 1;
7624     } else {
7625         endian = -1;
7626         offset = size-1;
7627     }
7628
7629     while(size--) {
7630         emitpcode(poc,    popGet(AOP(reg),offset));
7631         offset += endian;
7632     }
7633
7634 }
7635
7636 #if 0
7637 /*-----------------------------------------------------------------*/
7638 /* genLeftShift - generates code for left shifting                 */
7639 /*-----------------------------------------------------------------*/
7640 static void genLeftShift (iCode *ic)
7641 {
7642     operand *left,*right, *result;
7643     int size, offset;
7644     unsigned long lit = 0L;
7645     char *l;
7646     symbol *tlbl , *tlbl1;
7647     pCodeOp *pctemp;
7648
7649     FENTRY;
7650     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7651
7652     right = IC_RIGHT(ic);
7653     left  = IC_LEFT(ic);
7654     result = IC_RESULT(ic);
7655
7656     aopOp(right,ic,FALSE);
7657     aopOp(left,ic,FALSE);
7658     aopOp(result,ic,FALSE);
7659
7660
7661     /* if the shift count is known then do it
7662     as efficiently as possible */
7663     if (AOP_TYPE(right) == AOP_LIT) {
7664         shiftLeft_Left2ResultLit (left, result, (int) ulFromVal (AOP(right)->aopu.aop_lit));
7665         return ;
7666     }
7667
7668     /* shift count is unknown then we have to form
7669     a loop get the loop count in B : Note: we take
7670     only the lower order byte since shifting
7671     more that 32 bits make no sense anyway, ( the
7672     largest size of an object can be only 32 bits ) */
7673
7674     /* this code fails for RIGHT == RESULT */
7675     assert (!pic14_sameRegs (AOP(right), AOP(result)));
7676
7677     /* now move the left to the result if they are not the
7678     same */
7679     if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7680         AOP_SIZE(result) > 1) {
7681
7682         size = AOP_SIZE(result);
7683         offset=0;
7684         while (size--) {
7685             l = aopGet(AOP(left),offset,FALSE,TRUE);
7686             if (*l == '@' && (IS_AOP_PREG(result))) {
7687
7688                 pic14_emitcode("mov","a,%s",l);
7689                 aopPut(AOP(result),"a",offset);
7690             } else {
7691                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7692                 emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7693                 //aopPut(AOP(result),l,offset);
7694             }
7695             offset++;
7696         }
7697     }
7698
7699     if(AOP_TYPE(left) == AOP_LIT)
7700         lit = ulFromVal (AOP(left)->aopu.aop_lit);
7701
7702     size = AOP_SIZE(result);
7703
7704     /* if it is only one byte then */
7705     if (size == 1) {
7706         if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7707             emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7708             emitpcode(POC_ANDLW,  popGetLit(0xf0));
7709             emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7710             emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7711             emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7712             emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7713             emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7714             emitpcode(POC_RLFW,   popGet(AOP(result),0));
7715             emitpcode(POC_ANDLW,  popGetLit(0xfe));
7716             emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7717             emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7718             emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7719         } else {
7720
7721             tlbl = newiTempLabel(NULL);
7722             if (!pic14_sameRegs(AOP(left),AOP(result))) {
7723                 mov2w (AOP(left), 0);
7724                 emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7725             }
7726
7727             emitpcode(POC_COMFW,  popGet(AOP(right),0));
7728             emitpcode(POC_RRF,    popGet(AOP(result),0));
7729             emitpLabel(tlbl->key);
7730             emitpcode(POC_RLF,    popGet(AOP(result),0));
7731             emitpcode(POC_ADDLW,  popGetLit(1));
7732             emitSKPC;
7733             emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7734         }
7735         goto release ;
7736     }
7737
7738     if (pic14_sameRegs(AOP(left),AOP(result))) {
7739
7740         tlbl = newiTempLabel(NULL);
7741         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7742         genMultiAsm(POC_RRF, result, size,1);
7743         emitpLabel(tlbl->key);
7744         genMultiAsm(POC_RLF, result, size,0);
7745         emitpcode(POC_ADDLW,  popGetLit(1));
7746         emitSKPC;
7747         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7748         goto release;
7749     }
7750
7751     //tlbl = newiTempLabel(NULL);
7752     //offset = 0 ;
7753     //tlbl1 = newiTempLabel(NULL);
7754
7755     //reAdjustPreg(AOP(result));
7756
7757     //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7758     //pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7759     //l = aopGet(AOP(result),offset,FALSE,FALSE);
7760     //MOVA(l);
7761     //pic14_emitcode("add","a,acc");
7762     //aopPut(AOP(result),"a",offset++);
7763     //while (--size) {
7764     //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7765     //  MOVA(l);
7766     //  pic14_emitcode("rlc","a");
7767     //  aopPut(AOP(result),"a",offset++);
7768     //}
7769     //reAdjustPreg(AOP(result));
7770
7771     //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7772     //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7773
7774
7775     tlbl = newiTempLabel(NULL);
7776     tlbl1= newiTempLabel(NULL);
7777
7778     size = AOP_SIZE(result);
7779     offset = 1;
7780
7781     pctemp = popGetTempReg();  /* grab a temporary working register. */
7782
7783     emitpcode(POC_MOVFW, popGet(AOP(right),0));
7784
7785     /* offset should be 0, 1 or 3 */
7786     emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7787     emitSKPNZ;
7788     emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7789
7790     emitpcode(POC_MOVWF, pctemp);
7791
7792
7793     emitpLabel(tlbl->key);
7794
7795     emitCLRC;
7796     emitpcode(POC_RLF,  popGet(AOP(result),0));
7797     while(--size)
7798         emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7799
7800     emitpcode(POC_DECFSZ,  pctemp);
7801     emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7802     emitpLabel(tlbl1->key);
7803
7804     popReleaseTempReg(pctemp);
7805
7806
7807 release:
7808     freeAsmop (right,NULL,ic,TRUE);
7809     freeAsmop(left,NULL,ic,TRUE);
7810     freeAsmop(result,NULL,ic,TRUE);
7811 }
7812 #endif
7813
7814 #if 0
7815 /*-----------------------------------------------------------------*/
7816 /* genrshOne - right shift a one byte quantity by known count      */
7817 /*-----------------------------------------------------------------*/
7818 static void genrshOne (operand *result, operand *left,
7819                        int shCount, int sign)
7820 {
7821     FENTRY;
7822     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7823     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7824 }
7825
7826 /*-----------------------------------------------------------------*/
7827 /* genrshTwo - right shift two bytes by known amount != 0          */
7828 /*-----------------------------------------------------------------*/
7829 static void genrshTwo (operand *result,operand *left,
7830                        int shCount, int sign)
7831 {
7832     FENTRY;
7833     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7834     /* if shCount >= 8 */
7835     if (shCount >= 8) {
7836         shCount -= 8 ;
7837         if (shCount)
7838             shiftR1Left2Result(left, MSB16, result, LSB,
7839             shCount, sign);
7840         else
7841             movLeft2Result(left, MSB16, result, LSB);
7842
7843         emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7844
7845         if(sign) {
7846             emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7847             emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7848         }
7849     }
7850
7851     /*  1 <= shCount <= 7 */
7852     else
7853         shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7854 }
7855
7856 /*-----------------------------------------------------------------*/
7857 /* shiftRLong - shift right one long from left to result           */
7858 /* offl = LSB or MSB16                                             */
7859 /*-----------------------------------------------------------------*/
7860 static void shiftRLong (operand *left, int offl,
7861                         operand *result, int sign)
7862 {
7863     int size, same;
7864
7865     FENTRY;
7866     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7867
7868     size = AOP_SIZE(left);
7869     if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7870
7871     if (sign)
7872         emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7873     else
7874         emitCLRC;
7875
7876     assert (offl >= 0 && offl < size);
7877
7878     same = pic14_sameRegs (AOP(left), AOP(result));
7879
7880     /* perform the shift */
7881     while (size--)
7882     {
7883         if (same && !offl) {
7884             emitpcode (POC_RRF, popGet (AOP(result), size));
7885         } else {
7886             emitpcode (POC_RRFW, popGet (AOP(left), size));
7887             emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7888         }
7889     } // while
7890
7891     addSign (result, AOP_SIZE(left) - offl, sign);
7892 }
7893
7894 /*-----------------------------------------------------------------*/
7895 /* genrshFour - shift four byte by a known amount != 0             */
7896 /*-----------------------------------------------------------------*/
7897 static void genrshFour (operand *result, operand *left,
7898                         int shCount, int sign)
7899 {
7900     FENTRY;
7901     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7902     /* if shifting more that 3 bytes */
7903     if(shCount >= 24 ) {
7904         shCount -= 24;
7905         if(shCount)
7906             shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7907         else
7908             movLeft2Result(left, MSB32, result, LSB);
7909
7910         addSign(result, MSB16, sign);
7911     }
7912     else if(shCount >= 16){
7913         shCount -= 16;
7914         if(shCount)
7915             shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7916         else{
7917             movLeft2Result(left, MSB24, result, LSB);
7918             movLeft2Result(left, MSB32, result, MSB16);
7919         }
7920         addSign(result, MSB24, sign);
7921     }
7922     else if(shCount >= 8){
7923         shCount -= 8;
7924         if(shCount == 1)
7925             shiftRLong(left, MSB16, result, sign);
7926         else if(shCount == 0){
7927             movLeft2Result(left, MSB16, result, LSB);
7928             movLeft2Result(left, MSB24, result, MSB16);
7929             movLeft2Result(left, MSB32, result, MSB24);
7930             addSign(result, MSB32, sign);
7931         }
7932         else{
7933             shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7934             shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7935             /* the last shift is signed */
7936             shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7937             addSign(result, MSB32, sign);
7938         }
7939     }
7940     else{   /* 1 <= shCount <= 7 */
7941         if(shCount <= 2){
7942             shiftRLong(left, LSB, result, sign);
7943             if(shCount == 2)
7944                 shiftRLong(result, LSB, result, sign);
7945         }
7946         else{
7947             shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7948             shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7949             shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7950         }
7951     }
7952 }
7953
7954 /*-----------------------------------------------------------------*/
7955 /* genRightShiftLiteral - right shifting by known count            */
7956 /*-----------------------------------------------------------------*/
7957 static void genRightShiftLiteral (operand *left,
7958                                   operand *right,
7959                                   operand *result,
7960                                   iCode *ic,
7961                                   int sign)
7962 {
7963     int shCount = (int) ulFromVal (AOP(right)->aopu.aop_lit);
7964     int lsize,res_size;
7965
7966     FENTRY;
7967     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7968     freeAsmop(right,NULL,ic,TRUE);
7969
7970     aopOp(left,ic,FALSE);
7971     aopOp(result,ic,FALSE);
7972
7973 #if VIEW_SIZE
7974     pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7975         AOP_SIZE(left));
7976 #endif
7977
7978     lsize = pic14_getDataSize(left);
7979     res_size = pic14_getDataSize(result);
7980     /* test the LEFT size !!! */
7981
7982     /* I suppose that the left size >= result size */
7983     if(shCount == 0){
7984         while(res_size--)
7985             movLeft2Result(left, res_size, result, res_size);
7986     }
7987
7988     else if(shCount >= (lsize * 8)){
7989
7990         if(res_size == 1) {
7991             emitpcode(POC_CLRF, popGet(AOP(result),LSB));
7992             if(sign) {
7993                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7994                 emitpcode(POC_DECF, popGet(AOP(result),LSB));
7995             }
7996         } else {
7997
7998             if(sign) {
7999                 emitpcode(POC_MOVLW, popGetLit(0));
8000                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8001                 emitpcode(POC_MOVLW, popGetLit(0xff));
8002                 while(res_size--)
8003                     emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8004
8005             } else {
8006
8007                 while(res_size--)
8008                     emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8009             }
8010         }
8011     } else {
8012
8013         switch (res_size) {
8014         case 1:
8015             genrshOne (result,left,shCount,sign);
8016             break;
8017
8018         case 2:
8019             genrshTwo (result,left,shCount,sign);
8020             break;
8021
8022         case 4:
8023             genrshFour (result,left,shCount,sign);
8024             break;
8025         default :
8026             break;
8027         }
8028
8029     }
8030
8031     freeAsmop(left,NULL,ic,TRUE);
8032     freeAsmop(result,NULL,ic,TRUE);
8033 }
8034 #endif
8035
8036 #if 0
8037 /*-----------------------------------------------------------------*/
8038 /* genSignedRightShift - right shift of signed number              */
8039 /*-----------------------------------------------------------------*/
8040 static void genSignedRightShift (iCode *ic)
8041 {
8042     operand *right, *left, *result;
8043     int size, offset;
8044     //  char *l;
8045     symbol *tlbl, *tlbl1 ;
8046     pCodeOp *pctemp;
8047
8048     //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8049
8050     /* we do it the hard way put the shift count in b
8051     and loop thru preserving the sign */
8052     FENTRY;
8053     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8054
8055     right = IC_RIGHT(ic);
8056     left  = IC_LEFT(ic);
8057     result = IC_RESULT(ic);
8058
8059     aopOp(right,ic,FALSE);
8060     aopOp(left,ic,FALSE);
8061     aopOp(result,ic,FALSE);
8062
8063
8064     if ( AOP_TYPE(right) == AOP_LIT) {
8065         shiftRight_Left2ResultLit (left, result, (int) ulFromVal (AOP(right)->aopu.aop_lit), 1);
8066         //genRightShiftLiteral (left,right,result,ic,1);
8067         return ;
8068     }
8069     /* shift count is unknown then we have to form
8070     a loop get the loop count in B : Note: we take
8071     only the lower order byte since shifting
8072     more that 32 bits make no sense anyway, ( the
8073     largest size of an object can be only 32 bits ) */
8074
8075     //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8076     //pic14_emitcode("inc","b");
8077     //freeAsmop (right,NULL,ic,TRUE);
8078     //aopOp(left,ic,FALSE);
8079     //aopOp(result,ic,FALSE);
8080
8081     /* now move the left to the result if they are not the
8082     same */
8083     if (!pic14_sameRegs(AOP(left),AOP(result)) &&
8084         AOP_SIZE(result) > 1) {
8085
8086         size = AOP_SIZE(result);
8087         offset=0;
8088         while (size--) {
8089             /*
8090             l = aopGet(AOP(left),offset,FALSE,TRUE);
8091             if (*l == '@' && IS_AOP_PREG(result)) {
8092                 pic14_emitcode("mov","a,%s",l);
8093                 aopPut(AOP(result),"a",offset);
8094             } else
8095             aopPut(AOP(result),l,offset);
8096             */
8097             emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
8098             emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
8099
8100             offset++;
8101         }
8102     }
8103
8104     /* mov the highest order bit to OVR */
8105     tlbl = newiTempLabel(NULL);
8106     tlbl1= newiTempLabel(NULL);
8107
8108     size = AOP_SIZE(result);
8109     offset = size - 1;
8110
8111     pctemp = popGetTempReg();  /* grab a temporary working register. */
8112
8113     emitpcode(POC_MOVFW, popGet(AOP(right),0));
8114
8115     /* offset should be 0, 1 or 3 */
8116     emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8117     emitSKPNZ;
8118     emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
8119
8120     emitpcode(POC_MOVWF, pctemp);
8121
8122
8123     emitpLabel(tlbl->key);
8124
8125     emitpcode(POC_RLFW,  popGet(AOP(result),offset));
8126     emitpcode(POC_RRF,   popGet(AOP(result),offset));
8127
8128     while(--size) {
8129         emitpcode(POC_RRF,   popGet(AOP(result),--offset));
8130     }
8131
8132     emitpcode(POC_DECFSZ,  pctemp);
8133     emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8134     emitpLabel(tlbl1->key);
8135
8136     popReleaseTempReg(pctemp);
8137 #if 0
8138     size = AOP_SIZE(result);
8139     offset = size - 1;
8140     pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8141     pic14_emitcode("rlc","a");
8142     pic14_emitcode("mov","ov,c");
8143     /* if it is only one byte then */
8144     if (size == 1) {
8145         l = aopGet(AOP(left),0,FALSE,FALSE);
8146         MOVA(l);
8147         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8148         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8149         pic14_emitcode("mov","c,ov");
8150         pic14_emitcode("rrc","a");
8151         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8152         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8153         aopPut(AOP(result),"a",0);
8154         goto release ;
8155     }
8156
8157     reAdjustPreg(AOP(result));
8158     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8159     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8160     pic14_emitcode("mov","c,ov");
8161     while (size--) {
8162         l = aopGet(AOP(result),offset,FALSE,FALSE);
8163         MOVA(l);
8164         pic14_emitcode("rrc","a");
8165         aopPut(AOP(result),"a",offset--);
8166     }
8167     reAdjustPreg(AOP(result));
8168     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8169     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8170
8171 release:
8172 #endif
8173
8174     freeAsmop(left,NULL,ic,TRUE);
8175     freeAsmop(result,NULL,ic,TRUE);
8176     freeAsmop(right,NULL,ic,TRUE);
8177 }
8178 #endif
8179
8180 /*-----------------------------------------------------------------*/
8181 /* loadSignToC - load the operand's sign bit into CARRY            */
8182 /*-----------------------------------------------------------------*/
8183
8184 static void loadSignToC (operand *op)
8185 {
8186     FENTRY;
8187     assert (op && AOP(op) && AOP_SIZE(op));
8188
8189     emitCLRC;
8190     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8191     emitSETC;
8192 }
8193
8194 /*-----------------------------------------------------------------*/
8195 /* genRightShift - generate code for right shifting                */
8196 /*-----------------------------------------------------------------*/
8197 static void genGenericShift (iCode *ic, int shiftRight)
8198 {
8199     operand *right, *left, *result;
8200     sym_link *retype ;
8201     int size;
8202     symbol *tlbl, *tlbl1, *inverselbl;
8203
8204     FENTRY;
8205     /* if signed then we do it the hard way preserve the
8206     sign bit moving it inwards */
8207     retype = getSpec(operandType(IC_RESULT(ic)));
8208     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8209
8210     /* signed & unsigned types are treated the same : i.e. the
8211     signed is NOT propagated inwards : quoting from the
8212     ANSI - standard : "for E1 >> E2, is equivalent to division
8213     by 2**E2 if unsigned or if it has a non-negative value,
8214     otherwise the result is implementation defined ", MY definition
8215     is that the sign does not get propagated */
8216
8217     right = IC_RIGHT(ic);
8218     left  = IC_LEFT(ic);
8219     result = IC_RESULT(ic);
8220
8221     aopOp(right,ic,FALSE);
8222     aopOp(left,ic,FALSE);
8223     aopOp(result,ic,FALSE);
8224
8225     /* if the shift count is known then do it
8226     as efficiently as possible */
8227     if (AOP_TYPE(right) == AOP_LIT) {
8228         int lit = (int) ulFromVal (AOP(right)->aopu.aop_lit);
8229         if (lit < 0)
8230         {
8231             lit = -lit;
8232             shiftRight = !shiftRight;
8233         }
8234
8235         if (shiftRight)
8236             shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8237         else
8238             shiftLeft_Left2ResultLit (left, result, lit);
8239         //genRightShiftLiteral (left,right,result,ic, 0);
8240         return ;
8241     }
8242
8243     /* shift count is unknown then we have to form
8244     a loop get the loop count in B : Note: we take
8245     only the lower order byte since shifting
8246     more that 32 bits make no sense anyway, ( the
8247     largest size of an object can be only 32 bits ) */
8248
8249     /* we must not overwrite the shift counter */
8250     assert (!pic14_sameRegs(AOP(right),AOP(result)));
8251
8252     /* now move the left to the result if they are not the
8253     same */
8254     if (!pic14_sameRegs(AOP(left),AOP(result)))
8255     {
8256         size = min(AOP_SIZE(result), AOP_SIZE(left));
8257         while (size--) {
8258             mov2w(AOP(left), size);
8259             movwf(AOP(result), size);
8260         }
8261         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8262     }
8263
8264     tlbl = newiTempLabel(NULL);
8265     tlbl1= newiTempLabel(NULL);
8266     inverselbl = NULL;
8267     size = AOP_SIZE(result);
8268
8269     mov2w(AOP(right),0);
8270     if (!SPEC_USIGN(operandType(right)))
8271     {
8272         inverselbl = newiTempLabel(NULL);
8273         /* signed shift count -- invert shift direction for c<0 */
8274         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8275         emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8276     } // if
8277     emitpcode(POC_SUBLW, popGetLit(0)); /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8278     /* check for `a = b >> c' with `-c == 0' */
8279     emitSKPNZ;
8280     emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8281     emitpLabel(tlbl->key);
8282     /* propagate the sign bit inwards for SIGNED result */
8283     if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8284     genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8285     emitpcode(POC_ADDLW,  popGetLit(1));    /* clears CARRY (unless W==0 afterwards) */
8286     emitSKPC;
8287     emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8288
8289     if (!SPEC_USIGN(operandType(right)))
8290     {
8291         symbol *inv_loop = newiTempLabel(NULL);
8292
8293         shiftRight = !shiftRight;   /* invert shift direction */
8294
8295         /* we came here from the code above -- we are done */
8296         emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8297
8298         /* emit code for shifting N<0 steps, count is already in W */
8299         emitpLabel(inverselbl->key);
8300         if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8301         emitpLabel(inv_loop->key);
8302         /* propagate the sign bit inwards for SIGNED result */
8303         if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8304         genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8305         emitpcode(POC_ADDLW, popGetLit(1));
8306         emitSKPC;
8307         emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8308     } // if
8309
8310     emitpLabel(tlbl1->key);
8311
8312     freeAsmop(left,NULL,ic,TRUE);
8313     freeAsmop (right,NULL,ic,TRUE);
8314     freeAsmop(result,NULL,ic,TRUE);
8315 }
8316
8317 static void genRightShift (iCode *ic)
8318 {
8319     genGenericShift(ic, 1);
8320 }
8321
8322 static void genLeftShift (iCode *ic)
8323 {
8324     genGenericShift(ic, 0);
8325 }
8326
8327 /*-----------------------------------------------------------------*/
8328 /* SetIrp - Set IRP bit                                            */
8329 /*-----------------------------------------------------------------*/
8330 void SetIrp(operand *result) {
8331     FENTRY;
8332     if (AOP_TYPE(result) == AOP_LIT) {
8333         unsigned lit = (unsigned) double2ul (operandLitValue(result));
8334         if (lit&0x100)
8335             emitSETIRP;
8336         else
8337             emitCLRIRP;
8338     } else {
8339         if (PCOP(AOP(result))->type == PO_LITERAL) {
8340             int addrs = PCOL(AOP(result))->lit;
8341             if (addrs & 0x100)
8342                 emitSETIRP;
8343             else
8344                 emitCLRIRP;
8345         } else {
8346             emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8347             if(AOP_SIZE(result) > 1) {
8348                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8349                 emitSETIRP;
8350             }
8351         }
8352     }
8353 }
8354
8355 static void
8356 setup_fsr (operand *ptr)
8357 {
8358   mov2w_op(ptr, 0);
8359   emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8360
8361   /* also setup-up IRP */
8362   SetIrp (ptr);
8363 }
8364
8365 /*-----------------------------------------------------------------*/
8366 /* emitPtrByteGet - emits code to get a byte into WREG from an     */
8367 /*                  arbitrary pointer (__code, __data, generic)    */
8368 /*-----------------------------------------------------------------*/
8369 static void
8370 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8371 {
8372     FENTRY;
8373     switch (p_type)
8374     {
8375     case POINTER:
8376     case FPOINTER:
8377       if (!alreadyAddressed) setup_fsr (src);
8378       emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8379       break;
8380
8381     case CPOINTER:
8382       assert( AOP_SIZE(src) == 2 );
8383       mov2w_op(src, 0);
8384       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8385       mov2w_op(src, 1);
8386       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8387       emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE));   /* GPOINTER tag for __code space */
8388       call_libraryfunc ("__gptrget1");
8389       break;
8390
8391     case GPOINTER:
8392       assert( AOP_SIZE(src) == 3 );
8393       mov2w_op(src, 0);
8394       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8395       mov2w_op(src, 1);
8396       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8397       mov2w_op(src, 2);
8398       call_libraryfunc ("__gptrget1");
8399       break;
8400
8401     default:
8402       assert( !"unhandled pointer type" );
8403       break;
8404     }
8405 }
8406
8407 /*-----------------------------------------------------------------*/
8408 /* emitPtrByteSet - emits code to set a byte from src through a    */
8409 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR).       */
8410 /*-----------------------------------------------------------------*/
8411 static void
8412 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8413 {
8414     FENTRY;
8415     switch (p_type)
8416     {
8417     case POINTER:
8418     case FPOINTER:
8419       if (!alreadyAddressed) setup_fsr (dst);
8420       emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8421       break;
8422
8423     case CPOINTER:
8424       assert( !"trying to assign to __code pointer" );
8425       break;
8426
8427     case GPOINTER:
8428       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8429       mov2w_op(dst, 0);
8430       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8431       mov2w_op(dst, 1);
8432       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8433       mov2w_op(dst, 2);
8434       call_libraryfunc ("__gptrput1");
8435       break;
8436
8437     default:
8438       assert( !"unhandled pointer type" );
8439       break;
8440     }
8441 }
8442
8443 /*-----------------------------------------------------------------*/
8444 /* genUnpackBits - generates code for unpacking bits               */
8445 /*-----------------------------------------------------------------*/
8446 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8447 {
8448   int rsize;            /* result size */
8449   sym_link *etype;      /* bitfield type information */
8450   int blen;             /* bitfield length */
8451   int bstr;             /* bitfield starting bit within byte */
8452
8453   FENTRY;
8454   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8455   etype = getSpec(operandType(result));
8456   rsize = getSize (operandType (result));
8457   blen = SPEC_BLEN (etype);
8458   bstr = SPEC_BSTR (etype);
8459
8460   /* single bit field case */
8461   if (blen == 1) {
8462     if (ifx) { /* that is for an if statement */
8463       pCodeOp *pcop;
8464       resolvedIfx rIfx;
8465       resolveIfx(&rIfx,ifx);
8466       if (ptype == -1) /* direct */
8467     pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8468       else
8469     pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8470       emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8471       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8472       ifx->generated=1;
8473     } else {
8474       int i;
8475       assert (!pic14_sameRegs (AOP(result), AOP(left)));
8476       for (i=0; i < AOP_SIZE(result); i++)
8477     emitpcode (POC_CLRF, popGet (AOP(result), i));
8478
8479       switch (ptype)
8480       {
8481       case -1:
8482         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8483     /* adjust result below */
8484         break;
8485
8486       case POINTER:
8487       case FPOINTER:
8488       case GPOINTER:
8489       case CPOINTER:
8490         emitPtrByteGet (left, ptype, FALSE);
8491     emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8492     emitSKPZ;
8493     /* adjust result below */
8494         break;
8495
8496       default:
8497         assert( !"unhandled pointer type" );
8498       } // switch
8499
8500       /* move sign-/zero extended bit to result */
8501       if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8502     emitpcode (POC_INCF, popGet (AOP(result), 0));
8503       } else {
8504     emitpcode (POC_DECF, popGet (AOP(result), 0));
8505       }
8506       addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8507     }
8508     return;
8509   }
8510   else if (blen <= 8 && ((blen + bstr) <= 8))
8511   {
8512     /* blen > 1 */
8513     int i;
8514
8515     for (i=0; i < AOP_SIZE(result); i++)
8516       emitpcode (POC_CLRF, popGet (AOP(result), i));
8517
8518     switch (ptype)
8519     {
8520     case -1:
8521       mov2w(AOP(left), 0);
8522       break;
8523
8524     case POINTER:
8525     case FPOINTER:
8526     case GPOINTER:
8527     case CPOINTER:
8528       emitPtrByteGet (left, ptype, FALSE);
8529       break;
8530
8531     default:
8532       assert( !"unhandled pointer type" );
8533     } // switch
8534
8535     if (blen < 8)
8536       emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8537     movwf(AOP(result), 0);
8538     AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8539
8540     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8541     {
8542       /* signed bitfield */
8543       assert (bstr + blen > 0);
8544       emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8545       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8546       emitpcode(POC_IORWF, popGet(AOP(result),0));
8547     }
8548     addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8549     return;
8550   }
8551
8552   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8553 }
8554
8555 #if 1
8556 /*-----------------------------------------------------------------*/
8557 /* genDataPointerGet - generates code when ptr offset is known     */
8558 /*-----------------------------------------------------------------*/
8559 static void genDataPointerGet (operand *left,
8560     operand *result,
8561     iCode *ic)
8562 {
8563     int size , offset = 0;
8564
8565     FENTRY;
8566     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8567
8568
8569     /* optimization - most of the time, left and result are the same
8570     * address, but different types. for the pic code, we could omit
8571     * the following
8572     */
8573     aopOp(result,ic,TRUE);
8574
8575     if (pic14_sameRegs (AOP(left), AOP(result)))
8576         return;
8577
8578     DEBUGpic14_AopType(__LINE__,left,NULL,result);
8579
8580     //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8581
8582     size = AOP_SIZE(result);
8583     if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8584
8585     offset = 0;
8586     while (size--) {
8587         emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8588         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8589         offset++;
8590     }
8591
8592     freeAsmop(left,NULL,ic,TRUE);
8593     freeAsmop(result,NULL,ic,TRUE);
8594 }
8595 #endif
8596
8597 /*-----------------------------------------------------------------*/
8598 /* genNearPointerGet - pic14_emitcode for near pointer fetch       */
8599 /*-----------------------------------------------------------------*/
8600 static void genNearPointerGet (operand *left,
8601                                operand *result,
8602                                iCode *ic)
8603 {
8604     asmop *aop = NULL;
8605     sym_link *ltype = operandType(left);
8606     sym_link *rtype = operandType(result);
8607     sym_link *retype= getSpec(rtype);      /* bitfield type information */
8608     int direct = 0;
8609
8610     FENTRY;
8611     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8612
8613
8614     aopOp(left,ic,FALSE);
8615
8616     /* if left is rematerialisable and
8617     result is not bit variable type and
8618     the left is pointer to data space i.e
8619     lower 128 bytes of space */
8620     if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8621         !IS_BITVAR(retype)         &&
8622         PIC_IS_DATA_PTR(ltype)) {
8623         genDataPointerGet (left,result,ic);
8624         return ;
8625     }
8626
8627     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8628     aopOp (result,ic,FALSE);
8629
8630     /* Check if can access directly instead of via a pointer */
8631     if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8632         && AOP_SIZE(result) == 1)
8633     {
8634         direct = 1;
8635     }
8636
8637     if (IS_BITFIELD(getSpec(operandType(result))))
8638     {
8639         genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8640         goto release;
8641     }
8642
8643     /* If the pointer value is not in a the FSR then need to put it in */
8644     /* Must set/reset IRP bit for use with FSR. */
8645     if (!direct)
8646       setup_fsr (left);
8647
8648 //  sym_link *etype;
8649     /* if bitfield then unpack the bits */
8650     {
8651         /* we have can just get the values */
8652         int size = AOP_SIZE(result);
8653         int offset = 0 ;
8654
8655         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8656
8657         while(size--) {
8658             if (direct)
8659                 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8660             else
8661                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8662             if (AOP_TYPE(result) == AOP_LIT) {
8663                 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8664             } else {
8665                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8666             }
8667             if (size && !direct)
8668                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8669             offset++;
8670         }
8671     }
8672
8673     /* now some housekeeping stuff */
8674     if (aop) {
8675         /* we had to allocate for this iCode */
8676         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8677         freeAsmop(NULL,aop,ic,TRUE);
8678     } else {
8679         /* we did not allocate which means left
8680         already in a pointer register, then
8681         if size > 0 && this could be used again
8682         we have to point it back to where it
8683         belongs */
8684         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8685         if (AOP_SIZE(result) > 1 &&
8686             !OP_SYMBOL(left)->remat &&
8687             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8688             ic->depth )) {
8689             int size = AOP_SIZE(result) - 1;
8690             while (size--)
8691                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8692         }
8693     }
8694
8695 release:
8696     /* done */
8697     freeAsmop(left,NULL,ic,TRUE);
8698     freeAsmop(result,NULL,ic,TRUE);
8699
8700 }
8701
8702 #if 0
8703 /*-----------------------------------------------------------------*/
8704 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8705 /*-----------------------------------------------------------------*/
8706 static void genPagedPointerGet (operand *left,
8707                                 operand *result,
8708                                 iCode *ic)
8709 {
8710     asmop *aop = NULL;
8711     regs *preg = NULL ;
8712     char *rname ;
8713     sym_link *rtype, *retype;
8714
8715     FENTRY;
8716     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8717
8718     rtype = operandType(result);
8719     retype= getSpec(rtype);
8720
8721     aopOp(left,ic,FALSE);
8722
8723     /* if the value is already in a pointer register
8724     then don't need anything more */
8725     if (!AOP_INPREG(AOP(left))) {
8726         /* otherwise get a free pointer register */
8727         aop = newAsmop(0);
8728         preg = getFreePtr(ic,&aop,FALSE);
8729         pic14_emitcode("mov","%s,%s",
8730             preg->name,
8731             aopGet(AOP(left),0,FALSE,TRUE));
8732         rname = preg->name ;
8733     } else
8734         rname = aopGet(AOP(left),0,FALSE,FALSE);
8735
8736     freeAsmop(left,NULL,ic,TRUE);
8737     aopOp (result,ic,FALSE);
8738
8739     /* if bitfield then unpack the bits */
8740     if (IS_BITFIELD(retype))
8741         genUnpackBits (result,left,rname,PPOINTER,0);
8742     else {
8743         /* we have can just get the values */
8744         int size = AOP_SIZE(result);
8745         int offset = 0 ;
8746
8747         while (size--) {
8748
8749             pic14_emitcode("movx","a,@%s",rname);
8750             aopPut(AOP(result),"a",offset);
8751
8752             offset++ ;
8753
8754             if (size)
8755                 pic14_emitcode("inc","%s",rname);
8756         }
8757     }
8758
8759     /* now some housekeeping stuff */
8760     if (aop) {
8761         /* we had to allocate for this iCode */
8762         freeAsmop(NULL,aop,ic,TRUE);
8763     } else {
8764     /* we did not allocate which means left
8765     already in a pointer register, then
8766     if size > 0 && this could be used again
8767     we have to point it back to where it
8768         belongs */
8769         if (AOP_SIZE(result) > 1 &&
8770             !OP_SYMBOL(left)->remat &&
8771             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8772             ic->depth )) {
8773             int size = AOP_SIZE(result) - 1;
8774             while (size--)
8775                 pic14_emitcode("dec","%s",rname);
8776         }
8777     }
8778
8779     /* done */
8780     freeAsmop(result,NULL,ic,TRUE);
8781
8782
8783 }
8784
8785 /*-----------------------------------------------------------------*/
8786 /* genFarPointerGet - gget value from far space                    */
8787 /*-----------------------------------------------------------------*/
8788 static void genFarPointerGet (operand *left,
8789                               operand *result, iCode *ic)
8790 {
8791     int size, offset ;
8792     sym_link *retype = getSpec(operandType(result));
8793
8794     FENTRY;
8795     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8796
8797     aopOp(left,ic,FALSE);
8798
8799     /* if the operand is already in dptr
8800     then we do nothing else we move the value to dptr */
8801     if (AOP_TYPE(left) != AOP_STR) {
8802         /* if this is remateriazable */
8803         if (AOP_TYPE(left) == AOP_IMMD)
8804             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8805         else { /* we need to get it byte by byte */
8806             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8807             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8808             if (options.model == MODEL_FLAT24)
8809             {
8810                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8811             }
8812         }
8813     }
8814     /* so dptr know contains the address */
8815     freeAsmop(left,NULL,ic,TRUE);
8816     aopOp(result,ic,FALSE);
8817
8818     /* if bit then unpack */
8819     if (IS_BITFIELD(retype))
8820         genUnpackBits(result,left,"dptr",FPOINTER,0);
8821     else {
8822         size = AOP_SIZE(result);
8823         offset = 0 ;
8824
8825         while (size--) {
8826             pic14_emitcode("movx","a,@dptr");
8827             aopPut(AOP(result),"a",offset++);
8828             if (size)
8829                 pic14_emitcode("inc","dptr");
8830         }
8831     }
8832
8833     freeAsmop(result,NULL,ic,TRUE);
8834 }
8835 #endif
8836
8837 #if 0
8838 /*-----------------------------------------------------------------*/
8839 /* genCodePointerGet - get value from code space                  */
8840 /*-----------------------------------------------------------------*/
8841 static void genCodePointerGet (operand *left,
8842                                operand *result, iCode *ic)
8843 {
8844     int size, offset ;
8845     sym_link *retype = getSpec(operandType(result));
8846
8847     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8848
8849     aopOp(left,ic,FALSE);
8850
8851     /* if the operand is already in dptr
8852     then we do nothing else we move the value to dptr */
8853     if (AOP_TYPE(left) != AOP_STR) {
8854         /* if this is remateriazable */
8855         if (AOP_TYPE(left) == AOP_IMMD)
8856             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8857         else { /* we need to get it byte by byte */
8858             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8859             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8860             if (options.model == MODEL_FLAT24)
8861             {
8862                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8863             }
8864         }
8865     }
8866     /* so dptr know contains the address */
8867     freeAsmop(left,NULL,ic,TRUE);
8868     aopOp(result,ic,FALSE);
8869
8870     /* if bit then unpack */
8871     if (IS_BITFIELD(retype))
8872         genUnpackBits(result,left,"dptr",CPOINTER,0);
8873     else {
8874         size = AOP_SIZE(result);
8875         offset = 0 ;
8876
8877         while (size--) {
8878             pic14_emitcode("clr","a");
8879             pic14_emitcode("movc","a,@a+dptr");
8880             aopPut(AOP(result),"a",offset++);
8881             if (size)
8882                 pic14_emitcode("inc","dptr");
8883         }
8884     }
8885
8886     freeAsmop(result,NULL,ic,TRUE);
8887 }
8888 #endif
8889 /*-----------------------------------------------------------------*/
8890 /* genGenPointerGet - gget value from generic pointer space        */
8891 /*-----------------------------------------------------------------*/
8892 static void genGenPointerGet (operand *left,
8893                               operand *result, iCode *ic)
8894 {
8895     FENTRY;
8896     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8897     aopOp(left,ic,FALSE);
8898     aopOp(result,ic,FALSE);
8899
8900
8901     DEBUGpic14_AopType(__LINE__,left,NULL,result);
8902
8903     if (IS_BITFIELD(getSpec(operandType(result))))
8904     {
8905       genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
8906       return;
8907     }
8908
8909     {
8910       /* emit call to __gptrget */
8911       char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
8912       int size = AOP_SIZE(result);
8913       int idx = 0;
8914
8915       assert (size > 0 && size <= 4);
8916
8917       /* pass arguments */
8918       assert (AOP_SIZE(left) == 3);
8919       mov2w(AOP(left), 0);
8920       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8921       mov2w(AOP(left), 1);
8922       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8923       mov2w(AOP(left), 2);
8924       call_libraryfunc (func[size]);
8925
8926       /* save result */
8927       movwf (AOP(result), --size);
8928       while (size--) {
8929         emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
8930         movwf (AOP(result), size);
8931       } // while
8932     }
8933
8934     freeAsmop(left,NULL,ic,TRUE);
8935     freeAsmop(result,NULL,ic,TRUE);
8936
8937 }
8938
8939 /*-----------------------------------------------------------------*/
8940 /* genConstPointerGet - get value from const generic pointer space */
8941 /*-----------------------------------------------------------------*/
8942 static void genConstPointerGet (operand *left,
8943                                 operand *result, iCode *ic)
8944 {
8945     //sym_link *retype = getSpec(operandType(result));
8946     #if 0
8947     symbol *albl, *blbl;//, *clbl;
8948     pCodeOp *pcop;
8949     #endif
8950     PIC_OPCODE poc;
8951     int i, size, lit;
8952
8953     FENTRY;
8954     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8955     aopOp(left,ic,FALSE);
8956     aopOp(result,ic,FALSE);
8957
8958     size = AOP_SIZE(result);
8959
8960     DEBUGpic14_AopType(__LINE__,left,NULL,result);
8961
8962     DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8963
8964     lit = op_isLitLike (left);
8965     poc = lit ? POC_MOVLW : POC_MOVFW;
8966
8967     if (IS_BITFIELD(getSpec(operandType(result))))
8968     {
8969         genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
8970         goto release;
8971     }
8972
8973     {
8974         char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
8975         int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
8976         assert (size > 0 && size <= 4);
8977
8978         mov2w_op(left, 0);
8979         emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8980         mov2w_op(left, 1);
8981         emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8982         emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
8983         call_libraryfunc (func[size]);
8984
8985         movwf(AOP(result),size-1);
8986         for (i = 1; i < size; i++)
8987         {
8988             emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
8989             movwf(AOP(result),size - 1 - i);
8990         } // for
8991     }
8992
8993 release:
8994     freeAsmop(left,NULL,ic,TRUE);
8995     freeAsmop(result,NULL,ic,TRUE);
8996
8997 }
8998 /*-----------------------------------------------------------------*/
8999 /* genPointerGet - generate code for pointer get                   */
9000 /*-----------------------------------------------------------------*/
9001 static void genPointerGet (iCode *ic)
9002 {
9003     operand *left, *result ;
9004     sym_link *type, *etype;
9005     int p_type = -1;
9006
9007     FENTRY;
9008     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9009
9010     left = IC_LEFT(ic);
9011     result = IC_RESULT(ic) ;
9012
9013     /* depending on the type of pointer we need to
9014     move it to the correct pointer register */
9015     type = operandType(left);
9016     etype = getSpec(type);
9017
9018     if (IS_PTR_CONST(type))
9019         DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9020
9021     /* if left is of type of pointer then it is simple */
9022     if (IS_PTR(type) && !IS_FUNC(type->next))
9023         p_type = DCL_TYPE(type);
9024     else {
9025         /* we have to go by the storage class */
9026         p_type = PTR_TYPE(SPEC_OCLS(etype));
9027
9028         DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9029
9030         if (SPEC_OCLS(etype)->codesp ) {
9031             DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9032             //p_type = CPOINTER ;
9033         }
9034         else
9035             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9036                 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9037             /*p_type = FPOINTER ;*/
9038             else
9039                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9040                     DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9041                 /*        p_type = PPOINTER; */
9042                 else
9043                     if (SPEC_OCLS(etype) == idata )
9044                         DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9045                     /*      p_type = IPOINTER; */
9046                     else
9047                         DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9048                     /*      p_type = POINTER ; */
9049     }
9050
9051     /* now that we have the pointer type we assign
9052     the pointer values */
9053     switch (p_type) {
9054
9055     case POINTER:
9056     case FPOINTER:
9057     //case IPOINTER:
9058         genNearPointerGet (left,result,ic);
9059         break;
9060 /*
9061     case PPOINTER:
9062         genPagedPointerGet(left,result,ic);
9063         break;
9064
9065     case FPOINTER:
9066         genFarPointerGet (left,result,ic);
9067         break;
9068 */
9069     case CPOINTER:
9070         genConstPointerGet (left,result,ic);
9071         break;
9072
9073     case GPOINTER:
9074         genGenPointerGet (left,result,ic);
9075         break;
9076     default:
9077         assert ( !"unhandled pointer type" );
9078         break;
9079     }
9080
9081 }
9082
9083 /*-----------------------------------------------------------------*/
9084 /* genPackBits - generates code for packed bit storage             */
9085 /*-----------------------------------------------------------------*/
9086 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9087 {
9088   int blen;             /* bitfield length */
9089   int bstr;             /* bitfield starting bit within byte */
9090   int litval;           /* source literal value (if AOP_LIT) */
9091   unsigned char mask;   /* bitmask within current byte */
9092
9093   FENTRY;
9094   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9095
9096   blen = SPEC_BLEN (etype);
9097   bstr = SPEC_BSTR (etype);
9098
9099   /* If the bitfield length is less than a byte and does not cross byte boundaries */
9100   if ((blen <= 8) && ((bstr + blen) <= 8))
9101   {
9102     mask = ((unsigned char) (0xFF << (blen + bstr)) |
9103         (unsigned char) (0xFF >> (8 - bstr)));
9104
9105     if (AOP_TYPE (right) == AOP_LIT)
9106     {
9107       /* Case with a bitfield length <8 and literal source */
9108       int lit = (int) ulFromVal (AOP (right)->aopu.aop_lit);
9109       if (blen == 1) {
9110         pCodeOp *pcop;
9111
9112     switch (p_type)
9113     {
9114     case -1:
9115       if (AOP(result)->type == AOP_PCODE)
9116         pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9117       else
9118         pcop = popGet(AOP(result),0);
9119       emitpcode(lit?POC_BSF:POC_BCF,pcop);
9120       break;
9121
9122     case POINTER:
9123     case FPOINTER:
9124       setup_fsr (result);
9125       emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9126       break;
9127
9128     case CPOINTER:
9129       assert( !"trying to assign to bitfield via pointer to __code space" );
9130       break;
9131
9132     case GPOINTER:
9133       emitPtrByteGet(result, p_type, FALSE);
9134       if (lit) {
9135         emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9136       } else {
9137         emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9138       }
9139       emitPtrByteSet(result, p_type, TRUE);
9140       break;
9141
9142     default:
9143       assert( !"unhandled pointer type" );
9144       break;
9145     } // switch (p_type)
9146       } else {
9147         /* blen > 1 */
9148     litval = lit << bstr;
9149     litval &= (~mask) & 0x00ff;
9150
9151     switch (p_type)
9152     {
9153     case -1:
9154       mov2w (AOP(result), 0);
9155       if ((litval|mask) != 0x00ff)
9156         emitpcode(POC_ANDLW, popGetLit (mask));
9157       if (litval != 0x00)
9158         emitpcode(POC_IORLW, popGetLit (litval));
9159       movwf (AOP(result), 0);
9160       break;
9161
9162     case POINTER:
9163     case FPOINTER:
9164     case GPOINTER:
9165       emitPtrByteGet(result, p_type, FALSE);
9166       if ((litval|mask) != 0x00ff)
9167         emitpcode(POC_ANDLW, popGetLit (mask));
9168       if (litval != 0x00)
9169         emitpcode(POC_IORLW, popGetLit (litval));
9170       emitPtrByteSet(result, p_type, TRUE);
9171       break;
9172
9173     case CPOINTER:
9174       assert( !"trying to assign to bitfield via pointer to __code space" );
9175       break;
9176
9177     default:
9178       assert( !"unhandled pointer type" );
9179       break;
9180     } // switch
9181       } // if (blen > 1)
9182     }
9183     else
9184     {
9185       /* right is no literal */
9186       if (blen==1) {
9187         switch (p_type)
9188     {
9189     case -1:
9190       /* Note more efficient code, of pre clearing bit then only setting it if required,
9191        * can only be done if it is known that the result is not a SFR */
9192       emitpcode(POC_RRFW,popGet(AOP(right),0));
9193       emitSKPC;
9194       emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9195       emitSKPNC;
9196       emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9197       break;
9198
9199     case POINTER:
9200     case FPOINTER:
9201     case GPOINTER:
9202       emitPtrByteGet (result, p_type, FALSE);
9203       emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9204       emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9205       emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9206       emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9207       emitPtrByteSet (result, p_type, TRUE);
9208       break;
9209
9210     case CPOINTER:
9211       assert( !"trying to assign to bitfield via pointer to __code space" );
9212       break;
9213
9214     default:
9215       assert( !"unhandled pointer type" );
9216       break;
9217     } // switch
9218     return;
9219       } else {
9220     /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9221     pCodeOp *temp = popGetTempReg ();
9222
9223     mov2w (AOP(right), 0);
9224     if (blen < 8) {
9225       emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9226     }
9227     emitpcode(POC_MOVWF, temp);
9228     if (bstr) {
9229       AccLsh (temp, bstr);
9230     }
9231
9232     switch (p_type)
9233     {
9234     case -1:
9235       mov2w (AOP(result), 0);
9236       emitpcode(POC_ANDLW, popGetLit (mask));
9237       emitpcode(POC_IORFW, temp);
9238       movwf (AOP(result), 0);
9239       break;
9240
9241     case POINTER:
9242     case FPOINTER:
9243     case GPOINTER:
9244       emitPtrByteGet (result, p_type, FALSE);
9245       emitpcode(POC_ANDLW, popGetLit (mask));
9246       emitpcode(POC_IORFW, temp);
9247       emitPtrByteSet (result, p_type, TRUE);
9248       break;
9249
9250     case CPOINTER:
9251       assert( !"trying to assign to bitfield via pointer to __code space" );
9252       break;
9253
9254     default:
9255       assert( !"unhandled pointer type" );
9256       break;
9257     } // switch
9258
9259     popReleaseTempReg (temp);
9260       } // if (blen > 1)
9261     } // if (AOP(right)->type != AOP_LIT)
9262     return;
9263   } // if (blen <= 8 && ((blen + bstr) <= 8))
9264
9265   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9266 }
9267
9268 /*-----------------------------------------------------------------*/
9269 /* genDataPointerSet - remat pointer to data space                 */
9270 /*-----------------------------------------------------------------*/
9271 static void genDataPointerSet(operand *right,
9272     operand *result,
9273     iCode *ic)
9274 {
9275     int size, offset = 0 ;
9276     int ressize;
9277
9278     FENTRY;
9279     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9280     aopOp(right,ic,FALSE);
9281     aopOp(result,ic,FALSE);
9282
9283     assert (IS_SYMOP(result));
9284     assert (IS_PTR(OP_SYM_TYPE(result)));
9285
9286     if (AOP_TYPE(right) == AOP_LIT)
9287       size = 4;
9288     else
9289       size = AOP_SIZE(right);
9290     ressize = getSize(OP_SYM_ETYPE(result));
9291     if (size > ressize) size = ressize;
9292     //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9293
9294     //assert( !"what's going on here?" );
9295
9296     /*
9297     if ( AOP_TYPE(result) == AOP_PCODE) {
9298     fprintf(stderr,"genDataPointerSet   %s, %d\n",
9299     AOP(result)->aopu.pcop->name,
9300     PCOI(AOP(result)->aopu.pcop)->offset);
9301     }
9302     */
9303
9304     // tsd, was l+1 - the underline `_' prefix was being stripped
9305     while (size--) {
9306         emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
9307
9308         if (AOP_TYPE(right) == AOP_LIT) {
9309             unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
9310             //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9311             if(lit&0xff) {
9312                 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9313                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9314             } else {
9315                 emitpcode(POC_CLRF, popGet(AOP(result), offset));
9316             }
9317         } else {
9318             //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9319             emitpcode(POC_MOVFW, popGet(AOP(right), offset));
9320             emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9321         }
9322
9323         offset++;
9324     }
9325
9326     freeAsmop(right,NULL,ic,TRUE);
9327     freeAsmop(result,NULL,ic,TRUE);
9328 }
9329
9330 /*-----------------------------------------------------------------*/
9331 /* genNearPointerSet - pic14_emitcode for near pointer put         */
9332 /*-----------------------------------------------------------------*/
9333 static void genNearPointerSet (operand *right,
9334                                operand *result,
9335                                iCode *ic)
9336 {
9337     asmop *aop = NULL;
9338     sym_link *ptype = operandType(result);
9339     sym_link *retype = getSpec(operandType(right));
9340     sym_link *letype = getSpec(ptype);
9341     int direct = 0;
9342
9343
9344     FENTRY;
9345     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9346     aopOp(result,ic,FALSE);
9347
9348 #if 1
9349     /* if the result is rematerializable &
9350     in data space & not a bit variable */
9351     //if (AOP_TYPE(result) == AOP_IMMD &&
9352     if (AOP_TYPE(result) == AOP_PCODE &&
9353         PIC_IS_DATA_PTR(ptype) &&
9354         !IS_BITVAR (retype) &&
9355         !IS_BITVAR (letype)) {
9356         genDataPointerSet (right,result,ic);
9357         freeAsmop(result,NULL,ic,TRUE);
9358         return;
9359     }
9360 #endif
9361
9362     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9363     aopOp(right,ic,FALSE);
9364     DEBUGpic14_AopType(__LINE__,NULL,right,result);
9365
9366     /* Check if can access directly instead of via a pointer */
9367     if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9368         direct = 1;
9369     }
9370
9371     if (IS_BITFIELD (letype))
9372     {
9373       genPackBits (letype, result, right, direct?-1:POINTER);
9374       return;
9375     }
9376
9377     /* If the pointer value is not in a the FSR then need to put it in */
9378     /* Must set/reset IRP bit for use with FSR. */
9379     /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9380     if (!direct)
9381         setup_fsr (result);
9382
9383     {
9384         /* we have can just get the values */
9385         int size = AOP_SIZE(right);
9386         int offset = 0 ;
9387
9388         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9389         while (size--) {
9390             char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9391             if (*l == '@' ) {
9392                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9393             } else {
9394                 if (AOP_TYPE(right) == AOP_LIT) {
9395                     emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9396                 } else {
9397                     emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9398                 }
9399                 if (direct)
9400                     emitpcode(POC_MOVWF,popGet(AOP(result),0));
9401                 else
9402                     emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9403             }
9404             if (size && !direct)
9405                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9406             offset++;
9407         }
9408     }
9409
9410     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9411     /* now some housekeeping stuff */
9412     if (aop) {
9413         /* we had to allocate for this iCode */
9414         freeAsmop(NULL,aop,ic,TRUE);
9415     } else {
9416         /* we did not allocate which means left
9417         already in a pointer register, then
9418         if size > 0 && this could be used again
9419         we have to point it back to where it
9420         belongs */
9421         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9422         if (AOP_SIZE(right) > 1 &&
9423             !OP_SYMBOL(result)->remat &&
9424             ( OP_SYMBOL(result)->liveTo > ic->seq ||
9425             ic->depth )) {
9426             int size = AOP_SIZE(right) - 1;
9427             while (size--)
9428                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9429         }
9430     }
9431
9432     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9433     /* done */
9434
9435     freeAsmop(right,NULL,ic,TRUE);
9436     freeAsmop(result,NULL,ic,TRUE);
9437 }
9438
9439 #if 0
9440 /*-----------------------------------------------------------------*/
9441 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
9442 /*-----------------------------------------------------------------*/
9443 static void genPagedPointerSet (operand *right,
9444                                 operand *result,
9445                                 iCode *ic)
9446 {
9447     asmop *aop = NULL;
9448     regs *preg = NULL ;
9449     char *rname , *l;
9450     sym_link *retype;
9451
9452     FENTRY;
9453     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9454
9455     retype= getSpec(operandType(right));
9456
9457     aopOp(result,ic,FALSE);
9458
9459     /* if the value is already in a pointer register
9460     then don't need anything more */
9461     if (!AOP_INPREG(AOP(result))) {
9462         /* otherwise get a free pointer register */
9463         aop = newAsmop(0);
9464         preg = getFreePtr(ic,&aop,FALSE);
9465         pic14_emitcode("mov","%s,%s",
9466             preg->name,
9467             aopGet(AOP(result),0,FALSE,TRUE));
9468         rname = preg->name ;
9469     } else
9470         rname = aopGet(AOP(result),0,FALSE,FALSE);
9471
9472     freeAsmop(result,NULL,ic,TRUE);
9473     aopOp (right,ic,FALSE);
9474
9475     /* if bitfield then unpack the bits */
9476     if (IS_BITFIELD(retype))
9477         genPackBits (retype,result,right,rname,PPOINTER);
9478     else {
9479         /* we have can just get the values */
9480         int size = AOP_SIZE(right);
9481         int offset = 0 ;
9482
9483         while (size--) {
9484             l = aopGet(AOP(right),offset,FALSE,TRUE);
9485
9486             MOVA(l);
9487             pic14_emitcode("movx","@%s,a",rname);
9488
9489             if (size)
9490                 pic14_emitcode("inc","%s",rname);
9491
9492             offset++;
9493         }
9494     }
9495
9496     /* now some housekeeping stuff */
9497     if (aop) {
9498         /* we had to allocate for this iCode */
9499         freeAsmop(NULL,aop,ic,TRUE);
9500     } else {
9501     /* we did not allocate which means left
9502     already in a pointer register, then
9503     if size > 0 && this could be used again
9504     we have to point it back to where it
9505         belongs */
9506         if (AOP_SIZE(right) > 1 &&
9507             !OP_SYMBOL(result)->remat &&
9508             ( OP_SYMBOL(result)->liveTo > ic->seq ||
9509             ic->depth )) {
9510             int size = AOP_SIZE(right) - 1;
9511             while (size--)
9512                 pic14_emitcode("dec","%s",rname);
9513         }
9514     }
9515
9516     /* done */
9517     freeAsmop(right,NULL,ic,TRUE);
9518
9519
9520 }
9521
9522 /*-----------------------------------------------------------------*/
9523 /* genFarPointerSet - set value from far space                     */
9524 /*-----------------------------------------------------------------*/
9525 static void genFarPointerSet (operand *right,
9526                               operand *result, iCode *ic)
9527 {
9528     int size, offset ;
9529     sym_link *retype = getSpec(operandType(right));
9530
9531     FENTRY;
9532     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9533     aopOp(result,ic,FALSE);
9534
9535     /* if the operand is already in dptr
9536     then we do nothing else we move the value to dptr */
9537     if (AOP_TYPE(result) != AOP_STR) {
9538         /* if this is remateriazable */
9539         if (AOP_TYPE(result) == AOP_IMMD)
9540             pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9541         else { /* we need to get it byte by byte */
9542             pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9543             pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9544             if (options.model == MODEL_FLAT24)
9545             {
9546                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9547             }
9548         }
9549     }
9550     /* so dptr know contains the address */
9551     freeAsmop(result,NULL,ic,TRUE);
9552     aopOp(right,ic,FALSE);
9553
9554     /* if bit then unpack */
9555     if (IS_BITFIELD(retype))
9556         genPackBits(retype,result,right,"dptr",FPOINTER);
9557     else {
9558         size = AOP_SIZE(right);
9559         offset = 0 ;
9560
9561         while (size--) {
9562             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9563             MOVA(l);
9564             pic14_emitcode("movx","@dptr,a");
9565             if (size)
9566                 pic14_emitcode("inc","dptr");
9567         }
9568     }
9569
9570     freeAsmop(right,NULL,ic,TRUE);
9571 }
9572 #endif
9573
9574 /*-----------------------------------------------------------------*/
9575 /* genGenPointerSet - set value from generic pointer space         */
9576 /*-----------------------------------------------------------------*/
9577 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9578 {
9579     sym_link *retype = getSpec(operandType(result));
9580
9581     FENTRY;
9582     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9583     aopOp(right,ic,FALSE);
9584     aopOp(result,ic,FALSE);
9585
9586
9587     DEBUGpic14_AopType(__LINE__,right,NULL,result);
9588
9589     if (IS_BITFIELD(retype))
9590     {
9591       genPackBits (retype, result, right, GPOINTER);
9592       return;
9593     }
9594
9595     {
9596       /* emit call to __gptrput */
9597       char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9598       int size = AOP_SIZE(right);
9599       int idx = 0;
9600
9601       /* The following assertion fails for
9602        *   struct foo { char a; char b; } bar;
9603        *   void demo(struct foo *dst, char c) { dst->b = c; }
9604        * as size will be 1 (sizeof(c)), whereas dst->b will be accessed
9605        * using (((char *)dst)+1), whose OP_SYM_ETYPE still is struct foo
9606        * of size 2.
9607        * The frontend seems to guarantee that IC_LEFT has the correct size,
9608        * it works fine both for larger and smaller types of `char c'.
9609        * */
9610       //assert (size == getSize(OP_SYM_ETYPE(result)));
9611       assert (size > 0 && size <= 4);
9612
9613       /* pass arguments */
9614       /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9615       {
9616         int off = size;
9617         idx = 2;
9618         while (off--)
9619         {
9620           mov2w_op (right, off);
9621           emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9622         }
9623         idx = 0;
9624       }
9625       /* - address */
9626       assert (AOP_SIZE(result) == 3);
9627       mov2w(AOP(result), 0);
9628       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9629       mov2w(AOP(result), 1);
9630       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9631       mov2w(AOP(result), 2);
9632       call_libraryfunc (func[size]);
9633     }
9634
9635     freeAsmop(right,NULL,ic,TRUE);
9636     freeAsmop(result,NULL,ic,TRUE);
9637 }
9638
9639 /*-----------------------------------------------------------------*/
9640 /* genPointerSet - stores the value into a pointer location        */
9641 /*-----------------------------------------------------------------*/
9642 static void genPointerSet (iCode *ic)
9643 {
9644     operand *right, *result ;
9645     sym_link *type, *etype;
9646     int p_type;
9647
9648     FENTRY;
9649     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9650
9651     right = IC_RIGHT(ic);
9652     result = IC_RESULT(ic) ;
9653
9654     /* depending on the type of pointer we need to
9655     move it to the correct pointer register */
9656     type = operandType(result);
9657     etype = getSpec(type);
9658     /* if left is of type of pointer then it is simple */
9659     if (IS_PTR(type) && !IS_FUNC(type->next)) {
9660         p_type = DCL_TYPE(type);
9661     }
9662     else {
9663         /* we have to go by the storage class */
9664         p_type = PTR_TYPE(SPEC_OCLS(etype));
9665
9666         /*  if (SPEC_OCLS(etype)->codesp ) { */
9667         /*      p_type = CPOINTER ;  */
9668         /*  } */
9669         /*  else */
9670         /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9671         /*    p_type = FPOINTER ; */
9672         /*      else */
9673         /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9674         /*        p_type = PPOINTER ; */
9675         /*    else */
9676         /*        if (SPEC_OCLS(etype) == idata ) */
9677         /*      p_type = IPOINTER ; */
9678         /*        else */
9679         /*      p_type = POINTER ; */
9680     }
9681
9682     /* now that we have the pointer type we assign
9683     the pointer values */
9684     switch (p_type) {
9685
9686     case POINTER:
9687     case FPOINTER:
9688     //case IPOINTER:
9689         genNearPointerSet (right,result,ic);
9690         break;
9691 /*
9692     case PPOINTER:
9693         genPagedPointerSet (right,result,ic);
9694         break;
9695
9696     case FPOINTER:
9697         genFarPointerSet (right,result,ic);
9698         break;
9699 */
9700     case GPOINTER:
9701         genGenPointerSet (right,result,ic);
9702         break;
9703
9704     default:
9705         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9706             "genPointerSet: illegal pointer type");
9707     }
9708 }
9709
9710 /*-----------------------------------------------------------------*/
9711 /* genIfx - generate code for Ifx statement                        */
9712 /*-----------------------------------------------------------------*/
9713 static void genIfx (iCode *ic, iCode *popIc)
9714 {
9715     operand *cond = IC_COND(ic);
9716     int isbit =0;
9717
9718     FENTRY;
9719     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9720
9721     aopOp(cond,ic,FALSE);
9722
9723     /* get the value into acc */
9724     if (AOP_TYPE(cond) != AOP_CRY)
9725         pic14_toBoolean(cond);
9726     else
9727         isbit = 1;
9728
9729     /* if there was something to be popped then do it */
9730     if (popIc)
9731         genIpop(popIc);
9732
9733     if (isbit)
9734     {
9735         /* This assumes that CARRY is set iff cond is true */
9736         if (IC_TRUE(ic))
9737         {
9738             assert (!IC_FALSE(ic));
9739             emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9740             //emitSKPNC;
9741             emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9742         } else {
9743             assert (IC_FALSE(ic));
9744             emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9745             //emitSKPC;
9746             emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9747         }
9748         if (0)
9749         {
9750             static int hasWarned = 0;
9751             if (!hasWarned)
9752             {
9753                 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9754                 hasWarned = 1;
9755             }
9756         }
9757     }
9758     else
9759     {
9760         /* now Z is set iff !cond */
9761         if (IC_TRUE(ic))
9762         {
9763             assert (!IC_FALSE(ic));
9764             emitSKPZ;
9765             emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9766         } else {
9767             emitSKPNZ;
9768             emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9769         }
9770     }
9771
9772     ic->generated = 1;
9773
9774     /* the result is now in the accumulator */
9775     freeAsmop(cond,NULL,ic,TRUE);
9776 }
9777
9778 /*-----------------------------------------------------------------*/
9779 /* genAddrOf - generates code for address of                       */
9780 /*-----------------------------------------------------------------*/
9781 static void genAddrOf (iCode *ic)
9782 {
9783     operand *right, *result, *left;
9784     int size, offset ;
9785
9786     FENTRY;
9787     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9788
9789
9790     //aopOp(IC_RESULT(ic),ic,FALSE);
9791
9792     aopOp((left=IC_LEFT(ic)),ic,FALSE);
9793     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9794     aopOp((result=IC_RESULT(ic)),ic,TRUE);
9795
9796     DEBUGpic14_AopType(__LINE__,left,right,result);
9797     assert (IS_SYMOP (left));
9798
9799     /* sanity check: generic pointers to code space are not yet supported,
9800      * pionters to codespace must not be assigned addresses of __data values. */
9801  #if 0
9802     fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9803     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)));
9804     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)));
9805     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)));
9806     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)));
9807 #endif
9808
9809     if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9810       fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9811         IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9812         OP_SYMBOL(left)->name);
9813     } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9814       fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9815         IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9816         OP_SYMBOL(left)->name);
9817     }
9818
9819     size = AOP_SIZE(IC_RESULT(ic));
9820     if (IS_GENPTR(OP_SYM_TYPE(result))) {
9821         /* strip tag */
9822         if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9823     }
9824     offset = 0;
9825
9826     while (size--) {
9827         /* fixing bug #863624, reported from (errolv) */
9828         emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9829         emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9830
9831 #if 0
9832         emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9833         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9834 #endif
9835         offset++;
9836     }
9837
9838     if (IS_GENPTR(OP_SYM_TYPE(result)))
9839     {
9840         /* provide correct tag */
9841         int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9842         emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9843         movwf (AOP(result), 2);
9844     }
9845
9846     freeAsmop(left,NULL,ic,FALSE);
9847     freeAsmop(result,NULL,ic,TRUE);
9848
9849 }
9850
9851 #if 0
9852 /*-----------------------------------------------------------------*/
9853 /* genFarFarAssign - assignment when both are in far space         */
9854 /*-----------------------------------------------------------------*/
9855 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9856 {
9857     int size = AOP_SIZE(right);
9858     int offset = 0;
9859     char *l ;
9860     /* first push the right side on to the stack */
9861     while (size--) {
9862         l = aopGet(AOP(right),offset++,FALSE,FALSE);
9863         MOVA(l);
9864         pic14_emitcode ("push","acc");
9865     }
9866
9867     freeAsmop(right,NULL,ic,FALSE);
9868     /* now assign DPTR to result */
9869     aopOp(result,ic,FALSE);
9870     size = AOP_SIZE(result);
9871     while (size--) {
9872         pic14_emitcode ("pop","acc");
9873         aopPut(AOP(result),"a",--offset);
9874     }
9875     freeAsmop(result,NULL,ic,FALSE);
9876
9877 }
9878 #endif
9879
9880 /*-----------------------------------------------------------------*/
9881 /* genAssign - generate code for assignment                        */
9882 /*-----------------------------------------------------------------*/
9883 static void genAssign (iCode *ic)
9884 {
9885     operand *result, *right;
9886     int size, offset,know_W;
9887     unsigned long lit = 0L;
9888
9889     result = IC_RESULT(ic);
9890     right  = IC_RIGHT(ic) ;
9891
9892     FENTRY;
9893     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9894
9895     /* if they are the same */
9896     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9897         return ;
9898
9899     aopOp(right,ic,FALSE);
9900     aopOp(result,ic,TRUE);
9901
9902     DEBUGpic14_AopType(__LINE__,NULL,right,result);
9903
9904     /* if they are the same registers */
9905     if (pic14_sameRegs(AOP(right),AOP(result)))
9906         goto release;
9907
9908     /* special case: assign from __code */
9909     if (!IS_ITEMP(right)                /* --> iTemps never reside in __code */
9910         && IS_SYMOP (right)         /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
9911         && !IS_FUNC(OP_SYM_TYPE(right))     /* --> we would want its address instead of the first instruction */
9912         && !IS_CODEPTR(OP_SYM_TYPE(right))  /* --> get symbols address instread */
9913         && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
9914     {
9915       emitpComment ("genAssign from CODESPACE");
9916       genConstPointerGet (right, result, ic);
9917       goto release;
9918     }
9919
9920     /* just for symmetry reasons... */
9921     if (!IS_ITEMP(result)
9922         && IS_SYMOP (result)
9923         && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
9924     {
9925       assert ( !"cannot write to CODESPACE" );
9926     }
9927
9928     /* if the result is a bit */
9929     if (AOP_TYPE(result) == AOP_CRY) {
9930
9931     /* if the right size is a literal then
9932         we know what the value is */
9933         if (AOP_TYPE(right) == AOP_LIT) {
9934
9935             emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9936                 popGet(AOP(result),0));
9937
9938             if (((int) operandLitValue(right)))
9939                 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9940                 AOP(result)->aopu.aop_dir,
9941                 AOP(result)->aopu.aop_dir);
9942             else
9943                 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9944                 AOP(result)->aopu.aop_dir,
9945                 AOP(result)->aopu.aop_dir);
9946             goto release;
9947         }
9948
9949         /* the right is also a bit variable */
9950         if (AOP_TYPE(right) == AOP_CRY) {
9951             emitpcode(POC_BCF,    popGet(AOP(result),0));
9952             emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9953             emitpcode(POC_BSF,    popGet(AOP(result),0));
9954
9955             pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9956                 AOP(result)->aopu.aop_dir,
9957                 AOP(result)->aopu.aop_dir);
9958             pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
9959                 AOP(right)->aopu.aop_dir,
9960                 AOP(right)->aopu.aop_dir);
9961             pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9962                 AOP(result)->aopu.aop_dir,
9963                 AOP(result)->aopu.aop_dir);
9964             goto release ;
9965         }
9966
9967         /* we need to or */
9968         emitpcode(POC_BCF,    popGet(AOP(result),0));
9969         pic14_toBoolean(right);
9970         emitSKPZ;
9971         emitpcode(POC_BSF,    popGet(AOP(result),0));
9972         //aopPut(AOP(result),"a",0);
9973         goto release ;
9974     }
9975
9976     /* bit variables done */
9977     /* general case */
9978     size = AOP_SIZE(result);
9979     offset = 0 ;
9980     if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9981         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9982         if(aopIdx(AOP(result),0) == 4) {
9983             DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9984             emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9985             emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9986             goto release;
9987         } else
9988             DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9989     }
9990
9991     know_W=-1;
9992     while (size--) {
9993
9994         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9995         if(AOP_TYPE(right) == AOP_LIT) {
9996             lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
9997             if(lit&0xff) {
9998                 if(know_W != (int)(lit&0xff))
9999                     emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10000                 know_W = lit&0xff;
10001                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10002             } else
10003                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10004
10005         } else if (AOP_TYPE(right) == AOP_CRY) {
10006             emitpcode(POC_CLRF, popGet(AOP(result),offset));
10007             if(offset == 0) {
10008                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10009                 emitpcode(POC_INCF, popGet(AOP(result),0));
10010             }
10011         } else {
10012             mov2w_op (right, offset);
10013             emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10014         }
10015
10016         offset++;
10017     }
10018
10019
10020 release:
10021     freeAsmop (right,NULL,ic,FALSE);
10022     freeAsmop (result,NULL,ic,TRUE);
10023 }
10024
10025 /*-----------------------------------------------------------------*/
10026 /* genJumpTab - genrates code for jump table                       */
10027 /*-----------------------------------------------------------------*/
10028 static void genJumpTab (iCode *ic)
10029 {
10030     symbol *jtab;
10031     char *l;
10032
10033     FENTRY;
10034     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10035
10036     aopOp(IC_JTCOND(ic),ic,FALSE);
10037     /* get the condition into accumulator */
10038     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10039     MOVA(l);
10040     /* multiply by three */
10041     pic14_emitcode("add","a,acc");
10042     pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10043
10044     jtab = newiTempLabel(NULL);
10045     pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10046     pic14_emitcode("jmp","@a+dptr");
10047     pic14_emitcode("","%05d_DS_:",jtab->key+100);
10048
10049     emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10050     emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10051     emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10052     emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10053     emitSKPNC;
10054     emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10055     emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10056     emitpLabel(jtab->key);
10057
10058     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10059
10060     /* now generate the jump labels */
10061     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10062     jtab = setNextItem(IC_JTLABELS(ic))) {
10063         pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10064         emitpcode(POC_GOTO,popGetLabel(jtab->key));
10065
10066     }
10067
10068 }
10069
10070 /*-----------------------------------------------------------------*/
10071 /* genMixedOperation - gen code for operators between mixed types  */
10072 /*-----------------------------------------------------------------*/
10073 /*
10074 TSD - Written for the PIC port - but this unfortunately is buggy.
10075 This routine is good in that it is able to efficiently promote
10076 types to different (larger) sizes. Unfortunately, the temporary
10077 variables that are optimized out by this routine are sometimes
10078 used in other places. So until I know how to really parse the
10079 iCode tree, I'm going to not be using this routine :(.
10080 */
10081 static int genMixedOperation (iCode *ic)
10082 {
10083     FENTRY;
10084 #if 0
10085     operand *result = IC_RESULT(ic);
10086     sym_link *ctype = operandType(IC_LEFT(ic));
10087     operand *right = IC_RIGHT(ic);
10088     int ret = 0;
10089     int big,small;
10090     int offset;
10091
10092     iCode *nextic;
10093     operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10094
10095     pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10096
10097     nextic = ic->next;
10098     if(!nextic)
10099         return 0;
10100
10101     nextright = IC_RIGHT(nextic);
10102     nextleft  = IC_LEFT(nextic);
10103     nextresult = IC_RESULT(nextic);
10104
10105     aopOp(right,ic,FALSE);
10106     aopOp(result,ic,FALSE);
10107     aopOp(nextright,  nextic, FALSE);
10108     aopOp(nextleft,   nextic, FALSE);
10109     aopOp(nextresult, nextic, FALSE);
10110
10111     if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10112
10113         operand *t = right;
10114         right = nextright;
10115         nextright = t;
10116
10117         pic14_emitcode(";remove right +","");
10118
10119     } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10120     /*
10121     operand *t = right;
10122     right = nextleft;
10123     nextleft = t;
10124         */
10125         pic14_emitcode(";remove left +","");
10126     } else
10127         return 0;
10128
10129     big = AOP_SIZE(nextleft);
10130     small = AOP_SIZE(nextright);
10131
10132     switch(nextic->op) {
10133
10134     case '+':
10135         pic14_emitcode(";optimize a +","");
10136         /* if unsigned or not an integral type */
10137         if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10138             pic14_emitcode(";add a bit to something","");
10139         } else {
10140
10141             pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10142
10143             if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10144                 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10145                 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10146             } else
10147                 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10148
10149             offset = 0;
10150             while(--big) {
10151
10152                 offset++;
10153
10154                 if(--small) {
10155                     if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10156                         pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10157                         pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10158                     }
10159
10160                     pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10161                     emitSKPNC;
10162                     pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10163                         AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10164                         AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10165                     pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10166                     pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10167
10168                 } else {
10169                     pic14_emitcode("rlf","known_zero,w");
10170
10171                     /*
10172                     if right is signed
10173                     btfsc  right,7
10174                     addlw ff
10175                     */
10176                     if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10177                         pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10178                         pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10179                     } else {
10180                         pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10181                     }
10182                 }
10183             }
10184             ret = 1;
10185         }
10186     }
10187     ret = 1;
10188
10189 release:
10190     freeAsmop(right,NULL,ic,TRUE);
10191     freeAsmop(result,NULL,ic,TRUE);
10192     freeAsmop(nextright,NULL,ic,TRUE);
10193     freeAsmop(nextleft,NULL,ic,TRUE);
10194     if(ret)
10195         nextic->generated = 1;
10196
10197     return ret;
10198 #else
10199     return 0;
10200 #endif
10201 }
10202 /*-----------------------------------------------------------------*/
10203 /* genCast - gen code for casting                                  */
10204 /*-----------------------------------------------------------------*/
10205 static void genCast (iCode *ic)
10206 {
10207     operand *result = IC_RESULT(ic);
10208     sym_link *restype = operandType(result);
10209     sym_link *rtype = operandType(IC_RIGHT(ic));
10210     operand *right = IC_RIGHT(ic);
10211     int size, offset ;
10212
10213     FENTRY;
10214     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10215     /* if they are equivalent then do nothing */
10216     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10217         return ;
10218
10219     aopOp(right,ic,FALSE) ;
10220     aopOp(result,ic,FALSE);
10221
10222     DEBUGpic14_AopType(__LINE__,NULL,right,result);
10223
10224     /* if the result is a bit */
10225     if (AOP_TYPE(result) == AOP_CRY) {
10226         assert(!"assigning to bit variables is not supported");
10227     }
10228
10229     if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10230         int offset = 1;
10231         size = AOP_SIZE(result);
10232
10233         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10234
10235         emitpcode(POC_CLRF,   popGet(AOP(result),0));
10236         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10237         emitpcode(POC_INCF,   popGet(AOP(result),0));
10238
10239         while (size--)
10240             emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
10241
10242         goto release;
10243     }
10244
10245     if (IS_PTR(restype))
10246     {
10247       operand *result = IC_RESULT(ic);
10248       //operand *left = IC_LEFT(ic);
10249       operand *right = IC_RIGHT(ic);
10250       int tag = 0xff;
10251
10252       /* copy common part */
10253       int max, size = AOP_SIZE(result);
10254       if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10255       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10256
10257       /* warn if we discard generic opinter tag */
10258       if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10259       {
10260         //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10261       } // if
10262
10263       max = size;
10264       while (size--)
10265       {
10266         mov2w_op (right, size);
10267         movwf (AOP(result), size);
10268       } // while
10269
10270       /* upcast into generic pointer type? */
10271       if (IS_GENPTR(restype)
10272         && (size < AOP_SIZE(result))
10273         && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10274       {
10275         //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10276         if (IS_PTR(rtype))
10277         {
10278           switch (DCL_TYPE(rtype))
10279           {
10280           case POINTER: /* __data */
10281           case FPOINTER:    /* __data */
10282         assert (AOP_SIZE(right) == 2);
10283         tag = GPTRTAG_DATA;
10284         break;
10285
10286           case CPOINTER:    /* __code */
10287         assert (AOP_SIZE(right) == 2);
10288         tag = GPTRTAG_CODE;
10289         break;
10290
10291           case GPOINTER:    /* unknown destination, __data or __code */
10292         /* assume __data space (address of immediate) */
10293         assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10294         if (AOP(right)->code)
10295           tag = GPTRTAG_CODE;
10296         else
10297           tag = GPTRTAG_DATA;
10298         break;
10299
10300           default:
10301         assert (!"unhandled pointer type");
10302           } // switch
10303         } else {
10304           /* convert other values into pointers to __data space */
10305           tag = GPTRTAG_DATA;
10306         }
10307
10308         assert (AOP_SIZE(result) == 3);
10309         if (tag == 0) {
10310           emitpcode(POC_CLRF, popGet(AOP(result), 2));
10311         } else {
10312           emitpcode(POC_MOVLW, popGetLit(tag));
10313           movwf(AOP(result), 2);
10314         }
10315       } else {
10316         addSign(result, max, 0);
10317       } // if
10318       goto release;
10319     }
10320
10321     /* if they are the same size : or less */
10322     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10323
10324         /* if they are in the same place */
10325         if (pic14_sameRegs(AOP(right),AOP(result)))
10326             goto release;
10327
10328         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10329         if (IS_PTR_CONST(rtype))
10330             DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10331         if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10332             DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10333
10334         if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10335             emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10336             emitpcode(POC_MOVWF, popGet(AOP(result),0));
10337             emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10338             emitpcode(POC_MOVWF, popGet(AOP(result),1));
10339             if(AOP_SIZE(result) <2)
10340                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10341
10342         } else {
10343
10344             /* if they in different places then copy */
10345             size = AOP_SIZE(result);
10346             offset = 0 ;
10347             while (size--) {
10348                 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10349                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10350
10351                 //aopPut(AOP(result),
10352                 // aopGet(AOP(right),offset,FALSE,FALSE),
10353                 // offset);
10354
10355                 offset++;
10356             }
10357         }
10358         goto release;
10359     }
10360
10361     /* so we now know that the size of destination is greater
10362     than the size of the source.
10363     Now, if the next iCode is an operator then we might be
10364     able to optimize the operation without performing a cast.
10365     */
10366     if(0 && genMixedOperation(ic)) {
10367         /* XXX: cannot optimize: must copy regs! */
10368         goto release;
10369     }
10370
10371     /* we move to result for the size of source */
10372     size = AOP_SIZE(right);
10373     offset = 0 ;
10374     while (size--) {
10375         emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
10376         emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
10377         offset++;
10378     }
10379
10380     addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10381
10382 release:
10383     freeAsmop(right,NULL,ic,TRUE);
10384     freeAsmop(result,NULL,ic,TRUE);
10385
10386 }
10387
10388 /*-----------------------------------------------------------------*/
10389 /* genDjnz - generate decrement & jump if not zero instrucion      */
10390 /*-----------------------------------------------------------------*/
10391 static int genDjnz (iCode *ic, iCode *ifx)
10392 {
10393     symbol *lbl, *lbl1;
10394     FENTRY;
10395     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10396
10397     if (!ifx)
10398         return 0;
10399
10400         /* if the if condition has a false label
10401     then we cannot save */
10402     if (IC_FALSE(ifx))
10403         return 0;
10404
10405         /* if the minus is not of the form
10406     a = a - 1 */
10407     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10408         !IS_OP_LITERAL(IC_RIGHT(ic)))
10409         return 0;
10410
10411     if (operandLitValue(IC_RIGHT(ic)) != 1)
10412         return 0;
10413
10414         /* if the size of this greater than one then no
10415     saving */
10416     if (getSize(operandType(IC_RESULT(ic))) > 1)
10417         return 0;
10418
10419     /* otherwise we can save BIG */
10420     lbl = newiTempLabel(NULL);
10421     lbl1= newiTempLabel(NULL);
10422
10423     aopOp(IC_RESULT(ic),ic,FALSE);
10424
10425     if (IS_AOP_PREG(IC_RESULT(ic))) {
10426         pic14_emitcode("dec","%s",
10427             aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10428         pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10429         pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10430     } else {
10431
10432
10433         emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10434         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10435
10436         pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10437         pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10438
10439     }
10440     /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10441     /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10442     /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10443     /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10444
10445
10446     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10447     ifx->generated = 1;
10448     return 1;
10449 }
10450
10451 /*-----------------------------------------------------------------*/
10452 /* genReceive - generate code for a receive iCode                  */
10453 /*-----------------------------------------------------------------*/
10454 static void genReceive (iCode *ic)
10455 {
10456     FENTRY;
10457     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10458
10459     if (isOperandInFarSpace(IC_RESULT(ic)) &&
10460         ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10461         IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10462
10463         int size = getSize(operandType(IC_RESULT(ic)));
10464         int offset =  fReturnSizePic - size;
10465         while (size--) {
10466             pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10467                 fReturn[fReturnSizePic - offset - 1] : "acc"));
10468             offset++;
10469         }
10470         aopOp(IC_RESULT(ic),ic,FALSE);
10471         size = AOP_SIZE(IC_RESULT(ic));
10472         offset = 0;
10473         while (size--) {
10474             pic14_emitcode ("pop","acc");
10475             aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10476         }
10477
10478     } else {
10479         _G.accInUse++;
10480         aopOp(IC_RESULT(ic),ic,FALSE);
10481         _G.accInUse--;
10482         GpsuedoStkPtr = ic->parmBytes; // address used arg on stack
10483         assignResultValue(IC_RESULT(ic));
10484     }
10485
10486     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10487 }
10488
10489 /*-----------------------------------------------------------------*/
10490 /* genDummyRead - generate code for dummy read of volatiles        */
10491 /*-----------------------------------------------------------------*/
10492 static void
10493 genDummyRead (iCode * ic)
10494 {
10495     FENTRY;
10496     pic14_emitcode ("; genDummyRead","");
10497     pic14_emitcode ("; not implemented","");
10498
10499     ic = ic;
10500 }
10501
10502 /*-----------------------------------------------------------------*/
10503 /* genpic14Code - generate code for pic14 based controllers        */
10504 /*-----------------------------------------------------------------*/
10505 /*
10506 * At this point, ralloc.c has gone through the iCode and attempted
10507 * to optimize in a way suitable for a PIC. Now we've got to generate
10508 * PIC instructions that correspond to the iCode.
10509 *
10510 * Once the instructions are generated, we'll pass through both the
10511 * peep hole optimizer and the pCode optimizer.
10512 *-----------------------------------------------------------------*/
10513
10514 void genpic14Code (iCode *lic)
10515 {
10516     iCode *ic;
10517     int cln = 0;
10518     const char *cline;
10519
10520     FENTRY;
10521     lineHead = lineCurr = NULL;
10522
10523     pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10524     addpBlock(pb);
10525
10526     /* if debug information required */
10527     if (options.debug && debugFile && currFunc) {
10528         debugFile->writeFunction (currFunc, lic);
10529     }
10530
10531
10532     for (ic = lic ; ic ; ic = ic->next ) {
10533
10534         //DEBUGpic14_emitcode(";ic","");
10535         //fprintf (stderr, "in ic loop\n");
10536         //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10537         //ic->lineno, printCLine(ic->filename, ic->lineno));
10538
10539         if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10540           cln = ic->lineno;
10541           //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10542           cline = printCLine (ic->filename, ic->lineno);
10543           if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10544           addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10545           //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10546         }
10547
10548         if (options.iCodeInAsm) {
10549           const char *iLine = printILine(ic);
10550           emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10551                   dbuf_free(iLine);
10552         }
10553         /* if the result is marked as
10554         spilt and rematerializable or code for
10555         this has already been generated then
10556         do nothing */
10557         if (resultRemat(ic) || ic->generated )
10558             continue ;
10559
10560         /* depending on the operation */
10561         switch (ic->op) {
10562         case '!' :
10563             genNot(ic);
10564             break;
10565
10566         case '~' :
10567             genCpl(ic);
10568             break;
10569
10570         case UNARYMINUS:
10571             genUminus (ic);
10572             break;
10573
10574         case IPUSH:
10575             genIpush (ic);
10576             break;
10577
10578         case IPOP:
10579             /* IPOP happens only when trying to restore a
10580             spilt live range, if there is an ifx statement
10581             following this pop then the if statement might
10582             be using some of the registers being popped which
10583             would destory the contents of the register so
10584             we need to check for this condition and handle it */
10585             if (ic->next            &&
10586                 ic->next->op == IFX &&
10587                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10588                 genIfx (ic->next,ic);
10589             else
10590                 genIpop (ic);
10591             break;
10592
10593         case CALL:
10594             genCall (ic);
10595             break;
10596
10597         case PCALL:
10598             genPcall (ic);
10599             break;
10600
10601         case FUNCTION:
10602             genFunction (ic);
10603             break;
10604
10605         case ENDFUNCTION:
10606             genEndFunction (ic);
10607             break;
10608
10609         case RETURN:
10610             genRet (ic);
10611             break;
10612
10613         case LABEL:
10614             genLabel (ic);
10615             break;
10616
10617         case GOTO:
10618             genGoto (ic);
10619             break;
10620
10621         case '+' :
10622             genPlus (ic) ;
10623             break;
10624
10625         case '-' :
10626             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10627                 genMinus (ic);
10628             break;
10629
10630         case '*' :
10631             genMult (ic);
10632             break;
10633
10634         case '/' :
10635             genDiv (ic) ;
10636             break;
10637
10638         case '%' :
10639             genMod (ic);
10640             break;
10641
10642         case '>' :
10643             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10644             break;
10645
10646         case '<' :
10647             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10648             break;
10649
10650         case LE_OP:
10651         case GE_OP:
10652         case NE_OP:
10653
10654             /* note these two are xlated by algebraic equivalence
10655             during parsing SDCC.y */
10656             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10657                 "got '>=' or '<=' shouldn't have come here");
10658             break;
10659
10660         case EQ_OP:
10661             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10662             break;
10663
10664         case AND_OP:
10665             genAndOp (ic);
10666             break;
10667
10668         case OR_OP:
10669             genOrOp (ic);
10670             break;
10671
10672         case '^' :
10673             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10674             break;
10675
10676         case '|' :
10677             genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10678             break;
10679
10680         case BITWISEAND:
10681             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10682             break;
10683
10684         case INLINEASM:
10685             genInline (ic);
10686             break;
10687
10688         case RRC:
10689             genRRC (ic);
10690             break;
10691
10692         case RLC:
10693             genRLC (ic);
10694             break;
10695
10696         case GETHBIT:
10697             genGetHbit (ic);
10698             break;
10699
10700         case LEFT_OP:
10701             genLeftShift (ic);
10702             break;
10703
10704         case RIGHT_OP:
10705             genRightShift (ic);
10706             break;
10707
10708         case GET_VALUE_AT_ADDRESS:
10709             genPointerGet(ic);
10710             break;
10711
10712         case '=' :
10713             if (POINTER_SET(ic))
10714                 genPointerSet(ic);
10715             else
10716                 genAssign(ic);
10717             break;
10718
10719         case IFX:
10720             genIfx (ic,NULL);
10721             break;
10722
10723         case ADDRESS_OF:
10724             genAddrOf (ic);
10725             break;
10726
10727         case JUMPTABLE:
10728             genJumpTab (ic);
10729             break;
10730
10731         case CAST:
10732             genCast (ic);
10733             break;
10734
10735         case RECEIVE:
10736             genReceive(ic);
10737             break;
10738
10739         case SEND:
10740             addSet(&_G.sendSet,ic);
10741             break;
10742
10743         case DUMMY_READ_VOLATILE:
10744             genDummyRead (ic);
10745             break;
10746
10747         default :
10748             fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10749             ic = ic;
10750             break;
10751         }
10752     }
10753
10754
10755     /* now we are ready to call the
10756     peep hole optimizer */
10757     if (!options.nopeep) {
10758         peepHole (&lineHead);
10759     }
10760     /* now do the actual printing */
10761     printLine (lineHead,codeOutBuf);
10762
10763 #ifdef PCODE_DEBUG
10764     DFPRINTF((stderr,"printing pBlock\n\n"));
10765     printpBlock(stdout,pb);
10766 #endif
10767
10768     return;
10769 }
10770
10771 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10772  * (meaning: representing its own address) or not (referencing its contents).
10773  * This can only be decided based on the operand's type. */
10774 int
10775 aop_isLitLike (asmop *aop)
10776 {
10777   assert (aop);
10778   if (aop->type == AOP_LIT) return 1;
10779 if (aop->type == AOP_IMMD) return 1;
10780   if ((aop->type == AOP_PCODE) &&
10781         ((aop->aopu.pcop->type == PO_LITERAL)))
10782   {
10783     /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10784      * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10785     return 1;
10786   }
10787   return 0;
10788 }
10789
10790 int
10791 op_isLitLike (operand *op)
10792 {
10793   assert (op);
10794   if (aop_isLitLike (AOP(op))) return 1;
10795   if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10796   if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;
10797   return 0;
10798 }
10799