* in genGenPointerSet forgot to use postdec1
[fw/sdcc] / src / pic16 / gen.c
1 /*-------------------------------------------------------------------------
2  gen.c - source file for code generation for pic16
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   PIC16 port -  Martin Dubuc m.dubuc@rogers.com (2002)
9              -  Vangelis Rokas vrokas@otenet.gr (2003,2004)
10   
11   This program is free software; you can redistribute it and/or modify it
12   under the terms of the GNU General Public License as published by the
13   Free Software Foundation; either version 2, or (at your option) any
14   later version.
15   
16   This program is distributed in the hope that it will be useful,
17   but WITHOUT ANY WARRANTY; without even the implied warranty of
18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   GNU General Public License for more details.
20   
21   You should have received a copy of the GNU General Public License
22   along with this program; if not, write to the Free Software
23   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24   
25   In other words, you are welcome to use, share and improve this program.
26   You are forbidden to forbid anyone else to use, share and improve
27   what you give them.   Help stamp out software-hoarding!
28   
29   Notes:
30   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
31                 Made everything static
32 -------------------------------------------------------------------------*/
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include "SDCCglobl.h"
39 #include "newalloc.h"
40
41 #include "common.h"
42 #include "SDCCpeeph.h"
43 #include "ralloc.h"
44 #include "pcode.h"
45 #include "gen.h"
46 #include "genutils.h"
47 #include "device.h"
48 #include "main.h"
49
50 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
51 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
52 void pic16_genMult8X8_8 (operand *, operand *,operand *);
53 void pic16_genMult16X16_16(operand *, operand *, operand *);
54 void pic16_genMult32X32_32(operand *, operand *, operand *);
55 pCode *pic16_AssembleLine(char *line, int peeps);
56 extern void pic16_printpBlock(FILE *of, pBlock *pb);
57 static asmop *newAsmop (short type);
58 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
59 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
60 static void mov2w (asmop *aop, int offset);
61 static void mov2f(asmop *dst, asmop *src, int offset);
62 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
63 static pCodeOp *pic16_popRegFromIdx(int rIdx);
64
65 //static int aopIdx (asmop *aop, int offset);
66
67 int pic16_labelOffset=0;
68 extern int pic16_debug_verbose;
69 static int optimized_for_speed = 0;
70 /*
71   hack hack
72
73 */
74
75 /* max_key keeps track of the largest label number used in 
76    a function. This is then used to adjust the label offset
77    for the next function.
78 */
79 static int max_key=0;
80 static int GpsuedoStkPtr=0;
81
82 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
83
84 unsigned int pic16aopLiteral (value *val, int offset);
85 const char *pic16_AopType(short type);
86 static iCode *ifxForOp ( operand *op, iCode *ic );
87
88 void pic16_pushpCodeOp(pCodeOp *pcop);
89 void pic16_poppCodeOp(pCodeOp *pcop);
90
91 static bool is_LitOp(operand *op);
92 static bool is_LitAOp(asmop *aop);
93
94
95 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
96
97 /* this is the down and dirty file with all kinds of 
98    kludgy & hacky stuff. This is what it is all about
99    CODE GENERATION for a specific MCU . some of the
100    routines may be reusable, will have to see */
101
102 static char *zero = "#0x00";
103 static char *one  = "#0x01";
104 //static char *spname = "sp";
105
106
107 /*
108  * Function return value policy (MSB-->LSB):
109  *  8 bits      -> WREG
110  * 16 bits      -> PRODL:WREG
111  * 24 bits      -> PRODH:PRODL:WREG
112  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
113  * >32 bits     -> on stack, and FSR0 points to the beginning
114  *
115  */
116  
117
118 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
119 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
120 static char **fReturn = fReturnpic16;
121
122 static char *accUse[] = {"WREG"};
123
124 //static short rbank = -1;
125
126 static struct {
127     short r0Pushed;
128     short r1Pushed;
129     short fsr0Pushed;
130     short accInUse;
131     short inLine;
132     short debugLine;
133     short nRegsSaved;
134     short ipushRegs;
135     set *sendSet;
136     set *stackRegSet;
137     int interruptvector;
138     int usefastretfie;
139     bitVect *fregsUsed;
140     int stack_lat;                      /* stack offset latency */
141     int resDirect;
142 } _G;
143
144 /* Resolved ifx structure. This structure stores information
145    about an iCode ifx that makes it easier to generate code.
146 */
147 typedef struct resolvedIfx {
148   symbol *lbl;     /* pointer to a label */
149   int condition;   /* true or false ifx */
150   int generated;   /* set true when the code associated with the ifx
151                     * is generated */
152 } resolvedIfx;
153
154 extern int pic16_ptrRegReq ;
155 extern int pic16_nRegs;
156 extern FILE *codeOutFile;
157 //static void saverbank (int, iCode *,bool);
158
159 static lineNode *lineHead = NULL;
160 static lineNode *lineCurr = NULL;
161
162 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
163 0xE0, 0xC0, 0x80, 0x00};
164 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
165 0x07, 0x03, 0x01, 0x00};
166
167 static  pBlock *pb;
168
169 /*-----------------------------------------------------------------*/
170 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
171 /*                 exponent of 2 is returned, otherwise -1 is      */
172 /*                 returned.                                       */
173 /* note that this is similar to the function `powof2' in SDCCsymt  */
174 /* if(n == 2^y)                                                    */
175 /*   return y;                                                     */
176 /* return -1;                                                      */
177 /*-----------------------------------------------------------------*/
178 static int my_powof2 (unsigned long num)
179 {
180   if(num) {
181     if( (num & (num-1)) == 0) {
182       int nshifts = -1;
183       while(num) {
184         num>>=1;
185         nshifts++;
186       }
187       return nshifts;
188     }
189   }
190
191   return -1;
192 }
193
194 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
195 {
196   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
197                        line_no,
198                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
199                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
200                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
201                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
202                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
203                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
204                        ((result) ? AOP_SIZE(result) : 0));
205 }
206
207 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
208 {
209
210   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
211                        line_no,
212                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
213                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
214                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
215                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
216                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
217                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
218
219 }
220
221 void pic16_emitpcomment (char *fmt, ...)
222 {
223     va_list ap;
224     char lb[INITIAL_INLINEASM];  
225     char *lbp = lb;
226
227     va_start(ap,fmt);   
228
229     lb[0] = ';';
230     vsprintf(lb+1,fmt,ap);
231
232     while (isspace(*lbp)) lbp++;
233
234     if (lbp && *lbp) 
235         lineCurr = (lineCurr ?
236                     connectLine(lineCurr,newLineNode(lb)) :
237                     (lineHead = newLineNode(lb)));
238     lineCurr->isInline = _G.inLine;
239     lineCurr->isDebug  = _G.debugLine;
240
241     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
242     va_end(ap);
243
244 //      fprintf(stderr, "%s\n", lb);
245 }
246
247 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
248 {
249     va_list ap;
250     char lb[INITIAL_INLINEASM];  
251     char *lbp = lb;
252
253     if(!pic16_debug_verbose)
254       return;
255
256     va_start(ap,fmt);   
257
258     if (inst && *inst) {
259         if (fmt && *fmt)
260             sprintf(lb,"%s\t",inst);
261         else
262             sprintf(lb,"%s",inst);
263         vsprintf(lb+(strlen(lb)),fmt,ap);
264     }  else
265         vsprintf(lb,fmt,ap);
266
267     while (isspace(*lbp)) lbp++;
268
269     if (lbp && *lbp) 
270         lineCurr = (lineCurr ?
271                     connectLine(lineCurr,newLineNode(lb)) :
272                     (lineHead = newLineNode(lb)));
273     lineCurr->isInline = _G.inLine;
274     lineCurr->isDebug  = _G.debugLine;
275
276     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
277     va_end(ap);
278
279 //      fprintf(stderr, "%s\n", lb);
280 }
281
282 void pic16_emitpLabel(int key)
283 {
284   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
285 }
286
287 void pic16_emitpLabelFORCE(int key)
288 {
289   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
290 }
291
292 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
293 {
294
295   if(pcop)
296     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
297   else
298     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
299     
300 //    fprintf(stderr, "%s\n", pcop->name);
301 }
302
303 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
304 {
305
306   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
307
308 }
309
310
311 #if 1
312 #define pic16_emitcode  DEBUGpic16_emitcode
313 #else
314 /*-----------------------------------------------------------------*/
315 /* pic16_emitcode - writes the code into a file : for now it is simple    */
316 /*-----------------------------------------------------------------*/
317 void pic16_emitcode (char *inst,char *fmt, ...)
318 {
319     va_list ap;
320     char lb[INITIAL_INLINEASM];  
321     char *lbp = lb;
322
323     va_start(ap,fmt);   
324
325     if (inst && *inst) {
326         if (fmt && *fmt)
327             sprintf(lb,"%s\t",inst);
328         else
329             sprintf(lb,"%s",inst);
330         vsprintf(lb+(strlen(lb)),fmt,ap);
331     }  else
332         vsprintf(lb,fmt,ap);
333
334     while (isspace(*lbp)) lbp++;
335
336     if (lbp && *lbp) 
337         lineCurr = (lineCurr ?
338                     connectLine(lineCurr,newLineNode(lb)) :
339                     (lineHead = newLineNode(lb)));
340     lineCurr->isInline = _G.inLine;
341     lineCurr->isDebug  = _G.debugLine;
342
343 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
344
345 //    if(pic16_debug_verbose)
346 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
347
348     va_end(ap);
349 }
350 #endif
351
352
353 /*-----------------------------------------------------------------*/
354 /* pic16_emitDebuggerSymbol - associate the current code location  */
355 /*   with a debugger symbol                                        */
356 /*-----------------------------------------------------------------*/
357 void
358 pic16_emitDebuggerSymbol (char * debugSym)
359 {
360   _G.debugLine = 1;
361   pic16_emitcode (";", "%s ==.", debugSym);
362   _G.debugLine = 0;
363 }
364
365
366 /*-----------------------------------------------------------------*/
367 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
368 /*-----------------------------------------------------------------*/
369 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
370 {
371 //    bool r0iu = FALSE , r1iu = FALSE;
372 //    bool r0ou = FALSE , r1ou = FALSE;
373     bool fsr0iu = FALSE, fsr0ou;
374     bool fsr2iu = FALSE, fsr2ou;
375     
376     fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
377
378     
379     fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
380     fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
381     
382     fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
383     fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
384
385     if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
386         fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
387         DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
388     }
389
390     if(!fsr0iu && !fsr0ou) {
391         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
392         (*aopp)->type = AOP_FSR0;
393
394         fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
395         
396       return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
397     }
398
399 #if 0
400     /* no usage of FSR2 */
401     if(!fsr2iu && !fsr2ou) {
402         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
403         (*aopp)->type = AOP_FSR2;
404
405       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
406     }
407 #endif
408         
409     /* now we know they both have usage */
410     /* if fsr0 not used in this instruction */
411     if (!fsr0iu) {
412         if (!_G.fsr0Pushed) {
413                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
414                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
415                 _G.fsr0Pushed++;
416         }
417
418         ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
419         (*aopp)->type = AOP_FSR0;
420
421 //      fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
422
423       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
424     }
425         
426
427     fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
428     assert( 0 );
429
430     return NULL;
431 #if 0
432     /* the logic: if r0 & r1 used in the instruction
433     then we are in trouble otherwise */
434
435     /* first check if r0 & r1 are used by this
436     instruction, in which case we are in trouble */
437     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
438         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
439     {
440         goto endOfWorld;      
441     }
442
443     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
444     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
445
446     /* if no usage of r0 then return it */
447     if (!r0iu && !r0ou) {
448         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
449         (*aopp)->type = AOP_R0; 
450         
451         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
452     }
453
454     /* if no usage of r1 then return it */
455     if (!r1iu && !r1ou) {
456         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
457         (*aopp)->type = AOP_R1;
458
459         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
460     }    
461
462     /* now we know they both have usage */
463     /* if r0 not used in this instruction */
464     if (!r0iu) {
465         /* push it if not already pushed */
466         if (!_G.r0Pushed) {
467           //pic16_emitcode ("push","%s",
468           //          pic16_regWithIdx(R0_IDX)->dname);
469             _G.r0Pushed++ ;
470         }
471         
472         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
473         (*aopp)->type = AOP_R0;
474
475         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
476     }
477
478     /* if r1 not used then */
479
480     if (!r1iu) {
481         /* push it if not already pushed */
482         if (!_G.r1Pushed) {
483           //pic16_emitcode ("push","%s",
484           //          pic16_regWithIdx(R1_IDX)->dname);
485             _G.r1Pushed++ ;
486         }
487         
488         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
489         (*aopp)->type = AOP_R1;
490         return pic16_regWithIdx(R1_IDX);
491     }
492
493 endOfWorld :
494     /* I said end of world but not quite end of world yet */
495     /* if this is a result then we can push it on the stack*/
496     if (result) {
497         (*aopp)->type = AOP_STK;    
498         return NULL;
499     }
500
501     /* other wise this is true end of the world */
502     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
503            "getFreePtr should never reach here");
504     exit(0);
505 #endif
506 }
507
508 /*-----------------------------------------------------------------*/
509 /* newAsmop - creates a new asmOp                                  */
510 /*-----------------------------------------------------------------*/
511 static asmop *newAsmop (short type)
512 {
513     asmop *aop;
514
515     aop = Safe_calloc(1,sizeof(asmop));
516     aop->type = type;
517     return aop;
518 }
519
520 static void genSetDPTR(int n)
521 {
522     if (!n)
523     {
524         pic16_emitcode(";", "Select standard DPTR");
525         pic16_emitcode("mov", "dps, #0x00");
526     }
527     else
528     {
529         pic16_emitcode(";", "Select alternate DPTR");
530         pic16_emitcode("mov", "dps, #0x01");
531     }
532 }
533
534 /*-----------------------------------------------------------------*/
535 /* resolveIfx - converts an iCode ifx into a form more useful for  */
536 /*              generating code                                    */
537 /*-----------------------------------------------------------------*/
538 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
539 {
540
541   DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
542
543   if(!resIfx) 
544     return;
545
546
547   resIfx->condition = 1;    /* assume that the ifx is true */
548   resIfx->generated = 0;    /* indicate that the ifx has not been used */
549
550   if(!ifx) {
551     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
552
553 #if 1
554     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
555                         __FUNCTION__,__LINE__,resIfx->lbl->key);
556 #endif
557
558   } else {
559     if(IC_TRUE(ifx)) {
560       resIfx->lbl = IC_TRUE(ifx);
561     } else {
562       resIfx->lbl = IC_FALSE(ifx);
563       resIfx->condition = 0;
564     }
565
566 #if 1
567     if(IC_TRUE(ifx)) 
568       DEBUGpic16_emitcode("; ***","ifx true is non-null");
569     if(IC_FALSE(ifx)) 
570       DEBUGpic16_emitcode("; ***","ifx false is non-null");
571 #endif
572   }
573
574   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
575
576 }
577 #if 0
578 /*-----------------------------------------------------------------*/
579 /* pointerCode - returns the code for a pointer type               */
580 /*-----------------------------------------------------------------*/
581 static int pointerCode (sym_link *etype)
582 {
583
584     return PTR_TYPE(SPEC_OCLS(etype));
585
586 }
587 #endif
588
589 /*-----------------------------------------------------------------*/
590 /* aopForSym - for a true symbol                                   */
591 /*-----------------------------------------------------------------*/
592 static asmop *aopForSym (iCode *ic, operand *op, bool result)
593 {
594     symbol *sym=OP_SYMBOL(op);
595     asmop *aop;
596     memmap *space= SPEC_OCLS(sym->etype);
597
598     DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
599
600     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
601     
602 //    sym = OP_SYMBOL(op);
603
604     /* if already has one */
605     if (sym->aop) {
606             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
607         return sym->aop;
608     }
609
610 #if 0
611     /* if symbol was initially placed onStack then we must re-place it
612      * to direct memory, since pic16 does not have a specific stack */
613     if(sym->onStack) {
614         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
615     }
616 #endif
617
618 #if 1
619     /* assign depending on the storage class */
620     /* if it is on the stack or indirectly addressable */
621     /* space we need to assign either r0 or r1 to it   */    
622     if (sym->onStack || sym->iaccess) {
623       pCodeOp *pcop[4];
624       int i;
625       
626         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
627                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
628         
629         /* acquire a temporary register -- it is saved in function */
630
631         sym->aop = aop = newAsmop(AOP_STA);
632         aop->aopu.stk.stk = sym->stack;
633         aop->size = getSize(sym->type);
634
635
636         DEBUGpic16_emitcode("; +++", "%s:%d", __FILE__, __LINE__);
637         pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
638         if((ic->op == '=') && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
639           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG) ) {
640           
641           for(i=0;i<aop->size;i++)
642             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
643             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
644         } else
645           for(i=0;i<aop->size;i++) {
646             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond( _G.fregsUsed, 0 );
647             _G.fregsUsed = bitVectSetBit(_G.fregsUsed, PCOR(pcop[i])->r->rIdx);
648           }
649
650
651 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
652
653 #if 1
654         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
655         
656         if(_G.accInUse) {
657                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
658         }
659         
660         for(i=0;i<aop->size;i++) {
661
662           /* initialise for stack access via frame pointer */
663           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack + i + _G.stack_lat));
664
665           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
666                           pic16_popCopyReg(&pic16_pc_plusw2), pcop[i]));
667         }
668         
669         if(_G.accInUse) {
670                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
671         }
672         
673         return (aop);
674 #endif
675
676 #if 0
677         /* now assign the address of the variable to 
678         the pointer register */
679         if (aop->type != AOP_STK) {
680
681             if (sym->onStack) {
682                     if ( _G.accInUse )
683                         pic16_emitcode("push","acc");
684
685                     pic16_emitcode("mov","a,_bp");
686                     pic16_emitcode("add","a,#0x%02x",
687                              ((sym->stack < 0) ?
688                               ((char)(sym->stack - _G.nRegsSaved )) :
689                               ((char)sym->stack)) & 0xff);
690                     pic16_emitcode("mov","%s,a",
691                              aop->aopu.aop_ptr->name);
692
693                     if ( _G.accInUse )
694                         pic16_emitcode("pop","acc");
695             } else
696                 pic16_emitcode("mov","%s,#%s",
697                          aop->aopu.aop_ptr->name,
698                          sym->rname);
699             aop->paged = space->paged;
700         } else
701             aop->aopu.aop_stk = sym->stack;
702         return aop;
703 #endif
704
705     }
706 #endif
707
708 #if 0
709     if (sym->onStack && options.stack10bit)
710     {
711         /* It's on the 10 bit stack, which is located in
712          * far data space.
713          */
714          
715       //DEBUGpic16_emitcode(";","%d",__LINE__);
716
717         if ( _G.accInUse )
718                 pic16_emitcode("push","acc");
719
720         pic16_emitcode("mov","a,_bp");
721         pic16_emitcode("add","a,#0x%02x",
722                  ((sym->stack < 0) ?
723                    ((char)(sym->stack - _G.nRegsSaved )) :
724                    ((char)sym->stack)) & 0xff);
725         
726         genSetDPTR(1);
727         pic16_emitcode ("mov","dpx1,#0x40");
728         pic16_emitcode ("mov","dph1,#0x00");
729         pic16_emitcode ("mov","dpl1, a");
730         genSetDPTR(0);
731         
732         if ( _G.accInUse )
733             pic16_emitcode("pop","acc");
734             
735         sym->aop = aop = newAsmop(AOP_DPTR2);
736         aop->size = getSize(sym->type); 
737         return aop;
738     }
739 #endif
740     //DEBUGpic16_emitcode(";","%d",__LINE__);
741     /* if in bit space */
742     if (IN_BITSPACE(space)) {
743         sym->aop = aop = newAsmop (AOP_CRY);
744         aop->aopu.aop_dir = sym->rname ;
745         aop->size = getSize(sym->type);
746         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
747         return aop;
748     }
749     /* if it is in direct space */
750     if (IN_DIRSPACE(space)) {
751         sym->aop = aop = newAsmop (AOP_DIR);
752         aop->aopu.aop_dir = sym->rname ;
753         aop->size = getSize(sym->type);
754         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
755         pic16_allocDirReg( IC_LEFT(ic) );
756         return aop;
757     }
758
759     if (IN_FARSPACE(space)) {
760         sym->aop = aop = newAsmop (AOP_DIR);
761         aop->aopu.aop_dir = sym->rname ;
762         aop->size = getSize(sym->type);
763         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
764         pic16_allocDirReg( IC_LEFT(ic) );
765         return aop;
766     }
767
768 #if 0                                                                                           // patch 14
769     /* special case for a function */
770     if (IS_FUNC(sym->type)) {   
771         sym->aop = aop = newAsmop(AOP_IMMD);    
772         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
773         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
774         strcpy(aop->aopu.aop_immd,sym->rname);
775         aop->size = FPTRSIZE; 
776         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
777         return aop;
778     }
779 #endif                                                                                          // patch 14
780
781
782     /* only remaining is far space */
783     /* in which case DPTR gets the address */
784     sym->aop = aop = newAsmop(AOP_PCODE);
785
786 /* change the next if to 1 to revert to good old immediate code */
787         if(IN_CODESPACE(space)) {
788                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
789                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
790                 PCOI(aop->aopu.pcop)->index = 0;
791         } else {
792                 /* try to allocate via direct register */
793                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
794 //              aop->size = getSize( sym->type );
795         }
796
797         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
798                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
799
800 #if 0
801         if(!pic16_allocDirReg (IC_LEFT(ic)))
802                 return NULL;
803 #endif
804
805         if(IN_DIRSPACE( space ))
806                 aop->size = PTRSIZE;
807         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
808                 aop->size = FPTRSIZE;
809         else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
810         else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
811         else if(sym->onStack) {
812                 aop->size = PTRSIZE;
813         } else {
814                 assert( 0 );
815         }
816
817     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
818
819     /* if it is in code space */
820     if (IN_CODESPACE(space))
821         aop->code = 1;
822
823     return aop;     
824 }
825
826 /*-----------------------------------------------------------------*/
827 /* aopForRemat - rematerialzes an object                           */
828 /*-----------------------------------------------------------------*/
829 static asmop *aopForRemat (operand *op) // x symbol *sym)
830 {
831   symbol *sym = OP_SYMBOL(op);
832   operand *refop;
833   iCode *ic = NULL, *oldic;
834   asmop *aop = newAsmop(AOP_PCODE);
835   int val = 0;
836   int offset = 0;
837   int viaimmd=0;
838
839
840         ic = sym->rematiCode;
841
842         DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
843         
844         if(IS_OP_POINTER(op)) {
845                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
846         }
847
848         for (;;) {
849                 oldic = ic;
850
851 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
852         
853                 if (ic->op == '+') {
854                         val += (int) operandLitValue(IC_RIGHT(ic));
855                 } else if (ic->op == '-') {
856                         val -= (int) operandLitValue(IC_RIGHT(ic));
857                 } else
858                         break;
859                 
860                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
861         }
862
863         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
864         refop = IC_LEFT(ic);
865
866         if(!op->isaddr)viaimmd++; else viaimmd=0;
867                 
868 /* set the following if to 1 to revert to good old immediate code */
869         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
870                 || viaimmd) {
871
872                 DEBUGpic16_emitcode(";", "%s:%d immediate", __FILE__, __LINE__);
873
874                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
875
876 #if 0
877                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
878 #else
879                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
880 #endif
881
882                 PCOI(aop->aopu.pcop)->index = val;
883         } else {
884                 DEBUGpic16_emitcode(";", "%s:%d dir", __FILE__, __LINE__);
885
886                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
887                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
888 //              aop->size = AOP_SIZE( IC_LEFT(ic) );
889         }
890
891
892         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
893                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
894 #if 0
895                 val, IS_PTR_CONST(operandType(op)));
896 #else
897                 val, IS_CODEPTR(operandType(op)));
898 #endif
899
900 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
901
902         pic16_allocDirReg (IC_LEFT(ic));
903
904         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
905                 aop->code = 1;
906
907   return aop;        
908 }
909
910 #if 0
911 static int aopIdx (asmop *aop, int offset)
912 {
913   if(!aop)
914     return -1;
915
916   if(aop->type !=  AOP_REG)
917     return -2;
918         
919   return aop->aopu.aop_reg[offset]->rIdx;
920
921 }
922 #endif
923
924 /*-----------------------------------------------------------------*/
925 /* regsInCommon - two operands have some registers in common       */
926 /*-----------------------------------------------------------------*/
927 static bool regsInCommon (operand *op1, operand *op2)
928 {
929     symbol *sym1, *sym2;
930     int i;
931
932     /* if they have registers in common */
933     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
934         return FALSE ;
935
936     sym1 = OP_SYMBOL(op1);
937     sym2 = OP_SYMBOL(op2);
938
939     if (sym1->nRegs == 0 || sym2->nRegs == 0)
940         return FALSE ;
941
942     for (i = 0 ; i < sym1->nRegs ; i++) {
943         int j;
944         if (!sym1->regs[i])
945             continue ;
946
947         for (j = 0 ; j < sym2->nRegs ;j++ ) {
948             if (!sym2->regs[j])
949                 continue ;
950
951             if (sym2->regs[j] == sym1->regs[i])
952                 return TRUE ;
953         }
954     }
955
956     return FALSE ;
957 }
958
959 /*-----------------------------------------------------------------*/
960 /* operandsEqu - equivalent                                        */
961 /*-----------------------------------------------------------------*/
962 static bool operandsEqu ( operand *op1, operand *op2)
963 {
964     symbol *sym1, *sym2;
965
966     /* if they not symbols */
967     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
968         return FALSE;
969
970     sym1 = OP_SYMBOL(op1);
971     sym2 = OP_SYMBOL(op2);
972
973     /* if both are itemps & one is spilt
974        and the other is not then false */
975     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
976         sym1->isspilt != sym2->isspilt )
977         return FALSE ;
978
979     /* if they are the same */
980     if (sym1 == sym2)
981         return TRUE ;
982
983     if (sym1->rname[0] && sym2->rname[0]
984         && strcmp (sym1->rname, sym2->rname) == 0)
985         return TRUE;
986
987
988     /* if left is a tmp & right is not */
989     if (IS_ITEMP(op1)  && 
990         !IS_ITEMP(op2) &&
991         sym1->isspilt  &&
992         (sym1->usl.spillLoc == sym2))
993         return TRUE;
994
995     if (IS_ITEMP(op2)  && 
996         !IS_ITEMP(op1) &&
997         sym2->isspilt  &&
998         sym1->level > 0 &&
999         (sym2->usl.spillLoc == sym1))
1000         return TRUE ;
1001
1002     return FALSE ;
1003 }
1004
1005 /*-----------------------------------------------------------------*/
1006 /* pic16_sameRegs - two asmops have the same registers                   */
1007 /*-----------------------------------------------------------------*/
1008 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1009 {
1010     int i;
1011
1012     if (aop1 == aop2)
1013         return TRUE ;
1014
1015     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1016                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1017
1018     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1019
1020     if (aop1->type != AOP_REG ||
1021         aop2->type != AOP_REG )
1022         return FALSE ;
1023
1024     if (aop1->size != aop2->size )
1025         return FALSE ;
1026
1027     for (i = 0 ; i < aop1->size ; i++ ) {
1028 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1029
1030 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1031         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1032             return FALSE ;
1033     }
1034
1035     return TRUE ;
1036 }
1037
1038 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1039 {
1040     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1041                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1042
1043     if(aop1 == aop2)return TRUE;
1044     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1045       
1046       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1047     
1048   return TRUE;
1049 }
1050
1051
1052 /*-----------------------------------------------------------------*/
1053 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1054 /*-----------------------------------------------------------------*/
1055 void pic16_aopOp (operand *op, iCode *ic, bool result)
1056 {
1057     asmop *aop;
1058     symbol *sym;
1059     int i;
1060
1061     if (!op)
1062         return ;
1063
1064 //      DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1065
1066     /* if this a literal */
1067     if (IS_OP_LITERAL(op)) {
1068         op->aop = aop = newAsmop(AOP_LIT);
1069         aop->aopu.aop_lit = op->operand.valOperand;
1070         aop->size = getSize(operandType(op));
1071         return;
1072     }
1073
1074     {
1075       sym_link *type = operandType(op);
1076 #if 0
1077       if(IS_PTR_CONST(type))
1078 #else
1079       if(IS_CODEPTR(type))
1080 #endif
1081         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1082     }
1083
1084     /* if already has a asmop then continue */
1085     if (op->aop)
1086         return ;
1087
1088     /* if the underlying symbol has a aop */
1089     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1090       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1091         op->aop = OP_SYMBOL(op)->aop;
1092         return;
1093     }
1094
1095     /* if this is a true symbol */
1096     if (IS_TRUE_SYMOP(op)) {    
1097         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1098       op->aop = aopForSym(ic, op, result);
1099       return ;
1100     }
1101
1102     /* this is a temporary : this has
1103     only four choices :
1104     a) register
1105     b) spillocation
1106     c) rematerialize 
1107     d) conditional   
1108     e) can be a return use only */
1109
1110     sym = OP_SYMBOL(op);
1111
1112         DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
1113     /* if the type is a conditional */
1114     if (sym->regType == REG_CND) {
1115         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1116         aop->size = 0;
1117         return;
1118     }
1119
1120     /* if it is spilt then two situations
1121     a) is rematerialize 
1122     b) has a spill location */
1123     if (sym->isspilt || sym->nRegs == 0) {
1124
1125       DEBUGpic16_emitcode(";","%d",__LINE__);
1126         /* rematerialize it NOW */
1127         if (sym->remat) {
1128
1129             sym->aop = op->aop = aop = aopForRemat (op);
1130             aop->size = getSize(sym->type);
1131             //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1132             return;
1133         }
1134
1135 #if 1
1136         if (sym->accuse) {
1137             int i;
1138             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1139             aop->size = getSize(sym->type);
1140             for ( i = 0 ; i < 1 ; i++ ) {
1141                 aop->aopu.aop_str[i] = accUse[i];
1142 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1143             }
1144             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1145             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1146             return;  
1147         }
1148 #endif
1149
1150 #if 1
1151         if (sym->ruonly ) {
1152           /*
1153           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1154           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1155           //pic16_allocDirReg (IC_LEFT(ic));
1156           aop->size = getSize(sym->type);
1157           */
1158
1159           unsigned i;
1160
1161           aop = op->aop = sym->aop = newAsmop(AOP_STR);
1162           aop->size = getSize(sym->type);
1163           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1164             aop->aopu.aop_str[i] = fReturn[i];
1165
1166           DEBUGpic16_emitcode(";","%d",__LINE__);
1167           return;
1168         }
1169 #endif
1170         /* else spill location  */
1171         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1172             /* force a new aop if sizes differ */
1173             sym->usl.spillLoc->aop = NULL;
1174         }
1175
1176 #if 0
1177         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1178                             __FUNCTION__,__LINE__,
1179                             sym->usl.spillLoc->rname,
1180                             sym->rname, sym->usl.spillLoc->offset);
1181 #endif
1182
1183         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1184         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1185         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1186                                           getSize(sym->type), 
1187                                           sym->usl.spillLoc->offset, op);
1188         aop->size = getSize(sym->type);
1189
1190         return;
1191     }
1192
1193     {
1194       sym_link *type = operandType(op);
1195 #if 0
1196       if(IS_PTR_CONST(type)) 
1197 #else
1198       if(IS_CODEPTR(type)) 
1199 #endif
1200         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1201     }
1202
1203     /* must be in a register */
1204     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1205     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1206     aop->size = sym->nRegs;
1207     for ( i = 0 ; i < sym->nRegs ;i++)
1208         aop->aopu.aop_reg[i] = sym->regs[i];
1209 }
1210
1211 /*-----------------------------------------------------------------*/
1212 /* pic16_freeAsmop - free up the asmop given to an operand               */
1213 /*----------------------------------------------------------------*/
1214 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1215 {   
1216     asmop *aop ;
1217
1218     if (!op)
1219         aop = aaop;
1220     else 
1221         aop = op->aop;
1222
1223     if (!aop)
1224         return ;
1225
1226     if (aop->freed)
1227         goto dealloc; 
1228
1229     aop->freed = 1;
1230
1231     /* depending on the asmop type only three cases need work AOP_RO
1232        , AOP_R1 && AOP_STK */
1233 #if 1
1234     switch (aop->type) {
1235         case AOP_FSR0 :
1236             if (_G.fsr0Pushed ) {
1237                 if (pop) {
1238                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1239                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1240 //                    pic16_emitcode ("pop","ar0");
1241                     _G.fsr0Pushed--;
1242                 }
1243             }
1244             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1245             break;
1246
1247         case AOP_FSR2 :
1248             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1249             break;
1250
1251         case AOP_R0 :
1252             if (_G.r0Pushed ) {
1253                 if (pop) {
1254                     pic16_emitcode ("pop","ar0");     
1255                     _G.r0Pushed--;
1256                 }
1257             }
1258             bitVectUnSetBit(ic->rUsed,R0_IDX);
1259             break;
1260
1261         case AOP_R1 :
1262             if (_G.r1Pushed ) {
1263                 if (pop) {
1264                     pic16_emitcode ("pop","ar1");
1265                     _G.r1Pushed--;
1266                 }
1267             }
1268             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1269             break;
1270
1271         case AOP_STA:
1272           {
1273             int i;
1274
1275               /* we must store the result on stack */
1276               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1277                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1278                 for(i=0;i<aop->size;i++) {
1279                   /* initialise for stack access via frame pointer */
1280                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(OP_SYMBOL(IC_RESULT(ic))->stack + i + _G.stack_lat));
1281
1282                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1283                         aop->aopu.stk.pop[i], pic16_popCopyReg(&pic16_pc_plusw2)));
1284                 }
1285         
1286                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1287               }
1288
1289               if(!_G.resDirect) {
1290                 for(i=0;i<aop->size;i++)
1291                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1292               }
1293               _G.resDirect = 0;
1294           }
1295           break;
1296 #if 0
1297         case AOP_STK :
1298         {
1299             int sz = aop->size;    
1300             int stk = aop->aopu.aop_stk + aop->size;
1301             bitVectUnSetBit(ic->rUsed,R0_IDX);
1302             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1303
1304             getFreePtr(ic,&aop,FALSE);
1305             
1306             if (options.stack10bit)
1307             {
1308                 /* I'm not sure what to do here yet... */
1309                 /* #STUB */
1310                 fprintf(stderr, 
1311                         "*** Warning: probably generating bad code for "
1312                         "10 bit stack mode.\n");
1313             }
1314             
1315             if (stk) {
1316                 pic16_emitcode ("mov","a,_bp");
1317                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1318                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1319             } else {
1320                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1321             }
1322
1323             while (sz--) {
1324                 pic16_emitcode("pop","acc");
1325                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1326                 if (!sz) break;
1327                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1328             }
1329             op->aop = aop;
1330             pic16_freeAsmop(op,NULL,ic,TRUE);
1331             if (_G.r0Pushed) {
1332                 pic16_emitcode("pop","ar0");
1333                 _G.r0Pushed--;
1334             }
1335
1336             if (_G.r1Pushed) {
1337                 pic16_emitcode("pop","ar1");
1338                 _G.r1Pushed--;
1339             }       
1340         }
1341 #endif
1342
1343     }
1344 #endif
1345
1346 dealloc:
1347     /* all other cases just dealloc */
1348     if (op ) {
1349         op->aop = NULL;
1350         if (IS_SYMOP(op)) {
1351             OP_SYMBOL(op)->aop = NULL;    
1352             /* if the symbol has a spill */
1353             if (SPIL_LOC(op))
1354                 SPIL_LOC(op)->aop = NULL;
1355         }
1356     }
1357 }
1358
1359 /*-----------------------------------------------------------------*/
1360 /* pic16_aopGet - for fetching value of the aop                          */
1361 /*-----------------------------------------------------------------*/
1362 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1363 {
1364     char *s = buffer ;
1365     char *rs;
1366
1367     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1368
1369     /* offset is greater than size then zero */
1370     if (offset > (aop->size - 1) &&
1371         aop->type != AOP_LIT)
1372         return zero;
1373
1374     /* depending on type */
1375     switch (aop->type) {
1376
1377     case AOP_FSR0:
1378     case AOP_FSR2:
1379       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1380       rs = Safe_calloc(1, strlen(s)+1);
1381       strcpy(rs, s);
1382       return (rs);
1383       
1384 #if 0
1385       /* if we need to increment it */
1386       while (offset > aop->coff)
1387         {
1388           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1389           aop->coff++;
1390         }
1391
1392       while (offset < aop->coff)
1393         {
1394           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1395           aop->coff--;
1396         }
1397       aop->coff = offset;
1398       if (aop->paged)
1399         {
1400           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1401           return (dname ? "acc" : "a");
1402         }
1403       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1404       rs = Safe_calloc (1, strlen (s) + 1);
1405       strcpy (rs, s);
1406       return rs;
1407 #endif
1408
1409         
1410     case AOP_IMMD:
1411         if (bit16) 
1412             sprintf (s,"%s",aop->aopu.aop_immd);
1413         else
1414             if (offset) 
1415                 sprintf(s,"(%s >> %d)",
1416                         aop->aopu.aop_immd,
1417                         offset*8);
1418             else
1419                 sprintf(s,"%s",
1420                         aop->aopu.aop_immd);
1421         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1422         rs = Safe_calloc(1,strlen(s)+1);
1423         strcpy(rs,s);   
1424         return rs;
1425         
1426     case AOP_DIR:
1427       if (offset) {
1428         sprintf(s,"(%s + %d)",
1429                 aop->aopu.aop_dir,
1430                 offset);
1431         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1432       } else
1433             sprintf(s,"%s",aop->aopu.aop_dir);
1434         rs = Safe_calloc(1,strlen(s)+1);
1435         strcpy(rs,s);   
1436         return rs;
1437         
1438     case AOP_REG:
1439       //if (dname) 
1440       //    return aop->aopu.aop_reg[offset]->dname;
1441       //else
1442             return aop->aopu.aop_reg[offset]->name;
1443         
1444     case AOP_CRY:
1445       //pic16_emitcode(";","%d",__LINE__);
1446       return aop->aopu.aop_dir;
1447         
1448     case AOP_ACC:
1449         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1450 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1451 //        assert( 0 );
1452 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1453         rs = Safe_strdup("WREG");
1454         return (rs);
1455
1456     case AOP_LIT:
1457         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1458         rs = Safe_calloc(1,strlen(s)+1);
1459         strcpy(rs,s);   
1460         return rs;
1461         
1462     case AOP_STR:
1463         aop->coff = offset ;
1464         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1465             dname)
1466             return "acc";
1467         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1468         
1469         return aop->aopu.aop_str[offset];
1470         
1471     case AOP_PCODE:
1472       {
1473         pCodeOp *pcop = aop->aopu.pcop;
1474         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1475         if(pcop->name) {
1476           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1477           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1478           sprintf(s,"%s", pcop->name);
1479         } else
1480           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1481
1482       }
1483       rs = Safe_calloc(1,strlen(s)+1);
1484       strcpy(rs,s);   
1485       return rs;
1486
1487     case AOP_STA:
1488         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1489         return (rs);
1490         
1491     case AOP_STK:
1492 //        pCodeOp *pcop = aop->aop
1493         break;
1494
1495     }
1496
1497     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1498     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1499            "aopget got unsupported aop->type");
1500     exit(0);
1501 }
1502
1503
1504
1505 /* lock has the following meaning: When allocating temporary registers
1506  * for stack variables storage, the value of the temporary register is
1507  * saved on stack. Its value is restored at the end. This procedure is
1508  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1509  * a possibility that before a call to pic16_aopOp, a temporary register
1510  * is allocated for a while and it is freed after some time, this will
1511  * mess the stack and values will not be restored properly. So use lock=1
1512  * to allocate temporary registers used internally by the programmer, and
1513  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1514  * to inform the compiler developer about a possible bug. This is an internal
1515  * feature for developing the compiler -- VR */
1516  
1517 int _TempReg_lock = 0;
1518 /*-----------------------------------------------------------------*/
1519 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1520 /*-----------------------------------------------------------------*/
1521 pCodeOp *pic16_popGetTempReg(int lock)
1522 {
1523   pCodeOp *pcop;
1524   symbol *cfunc;
1525
1526 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1527     if(_TempReg_lock) {
1528       werror(W_POSSBUG2, __FILE__, __LINE__);
1529     }
1530     
1531     _TempReg_lock += lock;
1532     
1533     cfunc = currFunc;
1534     currFunc = NULL;
1535
1536     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1537     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1538       PCOR(pcop)->r->wasUsed=1;
1539       PCOR(pcop)->r->isFree=0;
1540
1541       /* push value on stack */
1542       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1543     }
1544
1545     currFunc = cfunc;
1546
1547   return pcop;
1548 }
1549
1550 /*-----------------------------------------------------------------*/
1551 /* pic16_popGetTempRegCond - create a new temporary pCodeOp, but   */
1552 /*                            don't save if inside v               */
1553 /*-----------------------------------------------------------------*/
1554 pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock)
1555 {
1556   pCodeOp *pcop;
1557   symbol *cfunc;
1558
1559 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1560
1561     if(_TempReg_lock) {
1562       werror(W_POSSBUG2, __FILE__, __LINE__);
1563     }
1564
1565     _TempReg_lock += lock;
1566
1567     cfunc = currFunc;
1568     currFunc = NULL;
1569
1570     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1571     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1572       PCOR(pcop)->r->wasUsed=1;
1573       PCOR(pcop)->r->isFree=0;
1574
1575       if(!bitVectBitValue(v, PCOR(pcop)->r->rIdx)) {
1576       /* push value on stack */
1577         pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1578       }
1579     }
1580
1581     currFunc = cfunc;
1582
1583   return pcop;
1584 }
1585
1586
1587 /*-----------------------------------------------------------------*/
1588 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1589 /*-----------------------------------------------------------------*/
1590 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1591 {
1592   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1593
1594   _TempReg_lock -= lock;
1595
1596   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1597     PCOR(pcop)->r->isFree = 1;
1598     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1599   }
1600 }
1601 /*-----------------------------------------------------------------*/
1602 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1603 /*-----------------------------------------------------------------*/
1604 pCodeOp *pic16_popGetLabel(unsigned int key)
1605 {
1606
1607   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1608
1609   if(key>max_key)
1610     max_key = key;
1611
1612   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1613 }
1614
1615 /*-----------------------------------------------------------------*/
1616 /* pic16_popCopyReg - copy a pcode operator                              */
1617 /*-----------------------------------------------------------------*/
1618 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1619 {
1620   pCodeOpReg *pcor;
1621
1622   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1623   pcor->pcop.type = pc->pcop.type;
1624   if(pc->pcop.name) {
1625     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1626       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1627   } else
1628     pcor->pcop.name = NULL;
1629
1630   pcor->r = pc->r;
1631   pcor->rIdx = pc->rIdx;
1632   pcor->r->wasUsed=1;
1633
1634 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1635
1636   return PCOP(pcor);
1637 }
1638
1639 /*-----------------------------------------------------------------*/
1640 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1641 /*-----------------------------------------------------------------*/
1642 pCodeOp *pic16_popGetLit(int lit)
1643 {
1644   return pic16_newpCodeOpLit(lit);
1645 }
1646
1647 /*-----------------------------------------------------------------*/
1648 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1649 /*-----------------------------------------------------------------*/
1650 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1651 {
1652   return pic16_newpCodeOpLit2(lit, arg2);
1653 }
1654
1655
1656 /*-----------------------------------------------------------------*/
1657 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1658 /*-----------------------------------------------------------------*/
1659 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1660 {
1661   return pic16_newpCodeOpImmd(name, offset,index, 0);
1662 }
1663
1664
1665 /*-----------------------------------------------------------------*/
1666 /* pic16_popGet - asm operator to pcode operator conversion              */
1667 /*-----------------------------------------------------------------*/
1668 pCodeOp *pic16_popGetWithString(char *str)
1669 {
1670   pCodeOp *pcop;
1671
1672
1673   if(!str) {
1674     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1675     exit (1);
1676   }
1677
1678   pcop = pic16_newpCodeOp(str,PO_STR);
1679
1680   return pcop;
1681 }
1682
1683 /*-----------------------------------------------------------------*/
1684 /* pic16_popRegFromString -                                        */
1685 /*-----------------------------------------------------------------*/
1686 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1687 {
1688
1689   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1690   pcop->type = PO_DIR;
1691
1692   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1693   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1694
1695   if(!str)
1696     str = "BAD_STRING";
1697
1698   pcop->name = Safe_calloc(1,strlen(str)+1);
1699   strcpy(pcop->name,str);
1700
1701   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1702
1703   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1704
1705   /* make sure that register doesn't exist,
1706    * and operand isn't NULL
1707    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1708   if((PCOR(pcop)->r == NULL) 
1709     && (op)
1710     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1711 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1712 //              __FUNCTION__, __LINE__, str, size, offset);
1713
1714     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1715     fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1716
1717   }
1718   PCOR(pcop)->instance = offset;
1719
1720   return pcop;
1721 }
1722
1723 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1724 {
1725   pCodeOp *pcop;
1726
1727 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1728
1729         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1730         PCOR(pcop)->rIdx = rIdx;
1731         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1732
1733         PCOR(pcop)->r->isFree = 0;
1734         PCOR(pcop)->r->wasUsed = 1;
1735
1736         pcop->type = PCOR(pcop)->r->pc_type;
1737
1738   return pcop;
1739 }
1740
1741 /*---------------------------------------------------------------------------------*/
1742 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1743 /*                 VR 030601                                                       */
1744 /*---------------------------------------------------------------------------------*/
1745 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1746 {
1747   pCodeOpReg2 *pcop2;
1748   pCodeOp *temp;
1749   
1750         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1751
1752         /* comment the following check, so errors to throw up */
1753 //      if(!pcop2)return NULL;
1754
1755         temp = pic16_popGet(aop_dst, offset);
1756         pcop2->pcop2 = temp;
1757         
1758   return PCOP(pcop2);
1759 }
1760
1761
1762
1763 /*--------------------------------------------------------------------------------.-*/
1764 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1765 /*                  VR 030601 , adapted by Hans Dorn                                */
1766 /*--------------------------------------------------------------------------------.-*/
1767 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1768 {
1769   pCodeOpReg2 *pcop2;
1770  
1771         pcop2 = (pCodeOpReg2 *)src;
1772         pcop2->pcop2 = dst;
1773         
1774         return PCOP(pcop2);
1775 }
1776
1777
1778
1779 /*---------------------------------------------------------------------------------*/
1780 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1781 /*                     movff instruction                                           */
1782 /*---------------------------------------------------------------------------------*/
1783 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1784 {
1785   pCodeOpReg2 *pcop2;
1786
1787         if(!noalloc) {
1788                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1789                 pcop2->pcop2 = pic16_popCopyReg(dst);
1790         } else {
1791                 /* the pCodeOp may be already allocated */
1792                 pcop2 = (pCodeOpReg2 *)(src);
1793                 pcop2->pcop2 = (pCodeOp *)(dst);
1794         }
1795
1796   return PCOP(pcop2);
1797 }
1798
1799
1800 /*-----------------------------------------------------------------*/
1801 /* pic16_popGet - asm operator to pcode operator conversion              */
1802 /*-----------------------------------------------------------------*/
1803 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1804 {
1805   //char *s = buffer ;
1806   char *rs;
1807   pCodeOp *pcop;
1808
1809     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1810     /* offset is greater than
1811     size then zero */
1812
1813 //    if (offset > (aop->size - 1) &&
1814 //        aop->type != AOP_LIT)
1815 //      return NULL;  //zero;
1816
1817     /* depending on type */
1818     switch (aop->type) {
1819         
1820     case AOP_R0:
1821     case AOP_R1:
1822     case AOP_DPTR:
1823     case AOP_DPTR2:
1824         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1825         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1826         assert( 0 );
1827         return NULL;
1828
1829
1830     case AOP_FSR0:
1831     case AOP_FSR2:
1832       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1833       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
1834       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1835       PCOR(pcop)->r->wasUsed = 1;
1836       PCOR(pcop)->r->isFree = 0;
1837       
1838       PCOR(pcop)->instance = offset;
1839       pcop->type = PCOR(pcop)->r->pc_type;
1840       return (pcop);
1841
1842     case AOP_IMMD:
1843       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1844       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1845
1846     case AOP_STA:
1847       /* pCodeOp is already allocated from aopForSym */
1848         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1849         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1850           
1851       return (pcop);
1852       
1853     case AOP_ACC:
1854       {
1855         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1856
1857         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1858
1859         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1860         
1861         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1862         PCOR(pcop)->rIdx = rIdx;
1863         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1864         PCOR(pcop)->r->wasUsed=1;
1865         PCOR(pcop)->r->isFree=0;
1866
1867         PCOR(pcop)->instance = offset;
1868         pcop->type = PCOR(pcop)->r->pc_type;
1869 //      rs = aop->aopu.aop_reg[offset]->name;
1870 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1871         return pcop;
1872
1873
1874 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1875 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1876
1877 //      assert( 0 );
1878       }
1879         
1880     case AOP_DIR:
1881       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1882       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1883         
1884     case AOP_REG:
1885       {
1886         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1887
1888         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1889         
1890         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1891 //      pcop->type = PO_GPR_REGISTER;
1892         PCOR(pcop)->rIdx = rIdx;
1893         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
1894         PCOR(pcop)->r->wasUsed=1;
1895         PCOR(pcop)->r->isFree=0;
1896
1897         PCOR(pcop)->instance = offset;
1898         pcop->type = PCOR(pcop)->r->pc_type;
1899         rs = aop->aopu.aop_reg[offset]->name;
1900         DEBUGpic16_emitcode(";","%d regiser idx = %d name = %s",__LINE__,rIdx,rs);
1901         return pcop;
1902       }
1903
1904     case AOP_CRY:
1905         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1906
1907       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1908       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1909       //if(PCOR(pcop)->r == NULL)
1910       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1911       return pcop;
1912         
1913     case AOP_LIT:
1914         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1915       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1916
1917     case AOP_STR:
1918       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1919       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1920
1921       /*
1922       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1923       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1924       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1925       pcop->type = PCOR(pcop)->r->pc_type;
1926       pcop->name = PCOR(pcop)->r->name;
1927
1928       return pcop;
1929       */
1930
1931     case AOP_PCODE:
1932       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1933                           __LINE__, 
1934                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1935       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1936 #if 1
1937         switch( aop->aopu.pcop->type ) {
1938                 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1939                 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1940                 default:
1941                         assert( 0 );    /* should never reach here */;
1942         }
1943 #else
1944       PCOI(pcop)->offset = offset;
1945 #endif
1946       return pcop;
1947     }
1948
1949     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1950            "pic16_popGet got unsupported aop->type");
1951     exit(0);
1952 }
1953 /*-----------------------------------------------------------------*/
1954 /* pic16_aopPut - puts a string for a aop                                */
1955 /*-----------------------------------------------------------------*/
1956 void pic16_aopPut (asmop *aop, char *s, int offset)
1957 {
1958     char *d = buffer ;
1959     symbol *lbl ;
1960
1961     return;
1962
1963     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1964
1965     if (aop->size && offset > ( aop->size - 1)) {
1966         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1967                "pic16_aopPut got offset > aop->size");
1968         exit(0);
1969     }
1970
1971     /* will assign value to value */
1972     /* depending on where it is ofcourse */
1973     switch (aop->type) {
1974     case AOP_DIR:
1975       if (offset) {
1976         sprintf(d,"(%s + %d)",
1977                 aop->aopu.aop_dir,offset);
1978         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1979
1980       } else
1981             sprintf(d,"%s",aop->aopu.aop_dir);
1982         
1983         if (strcmp(d,s)) {
1984           DEBUGpic16_emitcode(";","%d",__LINE__);
1985           if(strcmp(s,"W"))
1986             pic16_emitcode("movf","%s,w",s);
1987           pic16_emitcode("movwf","%s",d);
1988
1989           if(strcmp(s,"W")) {
1990             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1991             if(offset >= aop->size) {
1992               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1993               break;
1994             } else
1995               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1996           }
1997
1998           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1999
2000
2001         }
2002         break;
2003         
2004     case AOP_REG:
2005       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2006         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2007           /*
2008             if (*s == '@'           ||
2009                 strcmp(s,"r0") == 0 ||
2010                 strcmp(s,"r1") == 0 ||
2011                 strcmp(s,"r2") == 0 ||
2012                 strcmp(s,"r3") == 0 ||
2013                 strcmp(s,"r4") == 0 ||
2014                 strcmp(s,"r5") == 0 ||
2015                 strcmp(s,"r6") == 0 || 
2016                 strcmp(s,"r7") == 0 )
2017                 pic16_emitcode("mov","%s,%s  ; %d",
2018                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2019             else
2020           */
2021
2022           if(strcmp(s,"W")==0 )
2023             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2024
2025           pic16_emitcode("movwf","%s",
2026                    aop->aopu.aop_reg[offset]->name);
2027
2028           if(strcmp(s,zero)==0) {
2029             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2030
2031           } else if(strcmp(s,"W")==0) {
2032             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2033             pcop->type = PO_GPR_REGISTER;
2034
2035             PCOR(pcop)->rIdx = -1;
2036             PCOR(pcop)->r = NULL;
2037
2038             DEBUGpic16_emitcode(";","%d",__LINE__);
2039             pcop->name = Safe_strdup(s);
2040             pic16_emitpcode(POC_MOVFW,pcop);
2041             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2042           } else if(strcmp(s,one)==0) {
2043             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2044             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2045           } else {
2046             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2047           }
2048         }
2049         break;
2050         
2051     case AOP_DPTR:
2052     case AOP_DPTR2:
2053     
2054     if (aop->type == AOP_DPTR2)
2055     {
2056         genSetDPTR(1);
2057     }
2058     
2059         if (aop->code) {
2060             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2061                    "pic16_aopPut writting to code space");
2062             exit(0);
2063         }
2064         
2065         while (offset > aop->coff) {
2066             aop->coff++;
2067             pic16_emitcode ("inc","dptr");
2068         }
2069         
2070         while (offset < aop->coff) {
2071             aop->coff-- ;
2072             pic16_emitcode("lcall","__decdptr");
2073         }
2074         
2075         aop->coff = offset;
2076         
2077         /* if not in accumulater */
2078         MOVA(s);        
2079         
2080         pic16_emitcode ("movx","@dptr,a");
2081         
2082     if (aop->type == AOP_DPTR2)
2083     {
2084         genSetDPTR(0);
2085     }
2086         break;
2087         
2088     case AOP_R0:
2089     case AOP_R1:
2090         while (offset > aop->coff) {
2091             aop->coff++;
2092             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2093         }
2094         while (offset < aop->coff) {
2095             aop->coff-- ;
2096             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2097         }
2098         aop->coff = offset;
2099         
2100         if (aop->paged) {
2101             MOVA(s);           
2102             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2103             
2104         } else
2105             if (*s == '@') {
2106                 MOVA(s);
2107                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2108             } else
2109                 if (strcmp(s,"r0") == 0 ||
2110                     strcmp(s,"r1") == 0 ||
2111                     strcmp(s,"r2") == 0 ||
2112                     strcmp(s,"r3") == 0 ||
2113                     strcmp(s,"r4") == 0 ||
2114                     strcmp(s,"r5") == 0 ||
2115                     strcmp(s,"r6") == 0 || 
2116                     strcmp(s,"r7") == 0 ) {
2117                     char buffer[10];
2118                     sprintf(buffer,"a%s",s);
2119                     pic16_emitcode("mov","@%s,%s",
2120                              aop->aopu.aop_ptr->name,buffer);
2121                 } else
2122                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2123         
2124         break;
2125         
2126     case AOP_STK:
2127         if (strcmp(s,"a") == 0)
2128             pic16_emitcode("push","acc");
2129         else
2130             pic16_emitcode("push","%s",s);
2131         
2132         break;
2133         
2134     case AOP_CRY:
2135         /* if bit variable */
2136         if (!aop->aopu.aop_dir) {
2137             pic16_emitcode("clr","a");
2138             pic16_emitcode("rlc","a");
2139         } else {
2140             if (s == zero) 
2141                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2142             else
2143                 if (s == one)
2144                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2145                 else
2146                     if (!strcmp(s,"c"))
2147                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2148                     else {
2149                         lbl = newiTempLabel(NULL);
2150                         
2151                         if (strcmp(s,"a")) {
2152                             MOVA(s);
2153                         }
2154                         pic16_emitcode("clr","c");
2155                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2156                         pic16_emitcode("cpl","c");
2157                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2158                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2159                     }
2160         }
2161         break;
2162         
2163     case AOP_STR:
2164         aop->coff = offset;
2165         if (strcmp(aop->aopu.aop_str[offset],s))
2166             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2167         break;
2168         
2169     case AOP_ACC:
2170         aop->coff = offset;
2171         if (!offset && (strcmp(s,"acc") == 0))
2172             break;
2173         
2174         if (strcmp(aop->aopu.aop_str[offset],s))
2175             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2176         break;
2177
2178     default :
2179         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2180 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2181 //             "pic16_aopPut got unsupported aop->type");
2182 //      exit(0);    
2183     }    
2184
2185 }
2186
2187 /*-----------------------------------------------------------------*/
2188 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
2189 /*-----------------------------------------------------------------*/
2190 static void mov2w (asmop *aop, int offset)
2191 {
2192   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2193
2194   if(is_LitAOp(aop))
2195     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2196   else
2197     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2198 }
2199
2200 static void mov2f(asmop *dst, asmop *src, int offset)
2201 {
2202   if(is_LitAOp(src)) {
2203     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2204     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2205   } else {
2206     if(pic16_sameRegsOfs(src, dst, offset))return;
2207     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2208                       pic16_popGet(dst, offset)));
2209   }
2210 }
2211
2212 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2213 {
2214   if(is_LitAOp(src)) {
2215     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2216     pic16_emitpcode(POC_MOVWF, dst);
2217   } else {
2218     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2219   }
2220 }
2221
2222
2223 /* push pcop into stack */
2224 void pic16_pushpCodeOp(pCodeOp *pcop)
2225 {
2226 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2227         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
2228 }
2229
2230 /* pop pcop from stack */
2231 void pic16_poppCodeOp(pCodeOp *pcop)
2232 {
2233         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
2234 }
2235
2236
2237 /*-----------------------------------------------------------------*/
2238 /* pushw - pushes wreg to stack                                    */
2239 /*-----------------------------------------------------------------*/
2240 void pushw(void)
2241 {
2242         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2243         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
2244 }
2245
2246                 
2247 /*-----------------------------------------------------------------*/
2248 /* pushaop - pushes aop to stack                                   */
2249 /*-----------------------------------------------------------------*/
2250 void pushaop(asmop *aop, int offset)
2251 {
2252         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2253         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
2254 }
2255
2256 /*-----------------------------------------------------------------*/
2257 /* popaop - pops aop from stack                                    */
2258 /*-----------------------------------------------------------------*/
2259 void popaop(asmop *aop, int offset)
2260 {
2261         DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2262         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
2263 }
2264
2265 void popaopidx(asmop *aop, int offset, int index)
2266 {
2267   int ofs=1;
2268
2269         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2270
2271         if(STACK_MODEL_LARGE)ofs++;
2272
2273         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2274         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
2275 }
2276
2277 /*-----------------------------------------------------------------*/
2278 /* reAdjustPreg - points a register back to where it should        */
2279 /*-----------------------------------------------------------------*/
2280 static void reAdjustPreg (asmop *aop)
2281 {
2282     int size ;
2283
2284     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2285     aop->coff = 0;
2286     if ((size = aop->size) <= 1)
2287         return ;
2288     size-- ;
2289     switch (aop->type) {
2290         case AOP_R0 :
2291         case AOP_R1 :
2292             while (size--)
2293                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2294             break;          
2295         case AOP_DPTR :
2296         case AOP_DPTR2:
2297             if (aop->type == AOP_DPTR2)
2298             {
2299                 genSetDPTR(1);
2300             } 
2301             while (size--)
2302             {
2303                 pic16_emitcode("lcall","__decdptr");
2304             }
2305                 
2306             if (aop->type == AOP_DPTR2)
2307             {
2308                 genSetDPTR(0);
2309             }                
2310             break;  
2311
2312     }   
2313
2314 }
2315
2316
2317 #if 0
2318 /*-----------------------------------------------------------------*/
2319 /* opIsGptr: returns non-zero if the passed operand is             */   
2320 /* a generic pointer type.                                         */
2321 /*-----------------------------------------------------------------*/ 
2322 static int opIsGptr(operand *op)
2323 {
2324     sym_link *type = operandType(op);
2325     
2326     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2327     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2328     {
2329         return 1;
2330     }
2331     return 0;        
2332 }
2333 #endif
2334
2335 /*-----------------------------------------------------------------*/
2336 /* pic16_getDataSize - get the operand data size                         */
2337 /*-----------------------------------------------------------------*/
2338 int pic16_getDataSize(operand *op)
2339 {
2340     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2341
2342
2343     return AOP_SIZE(op);
2344
2345     // tsd- in the pic port, the genptr size is 1, so this code here
2346     // fails. ( in the 8051 port, the size was 4).
2347 #if 0
2348     int size;
2349     size = AOP_SIZE(op);
2350     if (size == GPTRSIZE)
2351     {
2352         sym_link *type = operandType(op);
2353         if (IS_GENPTR(type))
2354         {
2355             /* generic pointer; arithmetic operations
2356              * should ignore the high byte (pointer type).
2357              */
2358             size--;
2359     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2360         }
2361     }
2362     return size;
2363 #endif
2364 }
2365
2366 /*-----------------------------------------------------------------*/
2367 /* pic16_outAcc - output Acc                                             */
2368 /*-----------------------------------------------------------------*/
2369 void pic16_outAcc(operand *result)
2370 {
2371   int size,offset;
2372   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2373   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2374
2375
2376   size = pic16_getDataSize(result);
2377   if(size){
2378     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2379     size--;
2380     offset = 1;
2381     /* unsigned or positive */
2382     while(size--)
2383       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2384   }
2385
2386 }
2387
2388 /*-----------------------------------------------------------------*/
2389 /* pic16_outBitC - output a bit C                                  */
2390 /*                 Move to result the value of Carry flag -- VR    */
2391 /*-----------------------------------------------------------------*/
2392 void pic16_outBitC(operand *result)
2393 {
2394   int i;
2395
2396     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2397     /* if the result is bit */
2398     if (AOP_TYPE(result) == AOP_CRY) {
2399         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2400         pic16_aopPut(AOP(result),"c",0);
2401     } else {
2402
2403         i = AOP_SIZE(result);
2404         while(i--) {
2405                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2406         }
2407         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2408         
2409 /*
2410         pic16_emitcode("clr","a  ; %d", __LINE__);
2411         pic16_emitcode("rlc","a");
2412         pic16_outAcc(result);
2413 */
2414     }
2415 }
2416
2417 /*-----------------------------------------------------------------*/
2418 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2419 /*-----------------------------------------------------------------*/
2420 void pic16_toBoolean(operand *oper)
2421 {
2422     int size = AOP_SIZE(oper) - 1;
2423     int offset = 1;
2424
2425     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2426
2427     if ( AOP_TYPE(oper) != AOP_ACC) {
2428       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2429     }
2430     while (size--) {
2431       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2432     }
2433 }
2434
2435
2436 #if !defined(GEN_Not)
2437 /*-----------------------------------------------------------------*/
2438 /* genNot - generate code for ! operation                          */
2439 /*-----------------------------------------------------------------*/
2440 static void pic16_genNot (iCode *ic)
2441 {
2442   symbol *tlbl;
2443   int size;
2444
2445   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2446   /* assign asmOps to operand & result */
2447   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2448   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2449
2450   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2451   /* if in bit space then a special case */
2452   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2453     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2454       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2455       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2456     } else {
2457       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2458       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2459       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2460     }
2461     goto release;
2462   }
2463
2464   size = AOP_SIZE(IC_LEFT(ic));
2465   if(size == 1) {
2466     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2467     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2468     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2469     goto release;
2470   }
2471   pic16_toBoolean(IC_LEFT(ic));
2472
2473   tlbl = newiTempLabel(NULL);
2474   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2475   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2476   pic16_outBitC(IC_RESULT(ic));
2477
2478  release:    
2479   /* release the aops */
2480   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2481   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2482 }
2483 #endif
2484
2485
2486 #if !defined(GEN_Cpl)
2487 /*-----------------------------------------------------------------*/
2488 /* genCpl - generate code for complement                           */
2489 /*-----------------------------------------------------------------*/
2490 static void pic16_genCpl (iCode *ic)
2491 {
2492     int offset = 0;
2493     int size ;
2494
2495
2496     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2497     /* assign asmOps to operand & result */
2498     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2499     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2500
2501     /* if both are in bit space then 
2502     a special case */
2503     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2504         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2505
2506         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2507         pic16_emitcode("cpl","c"); 
2508         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2509         goto release; 
2510     } 
2511
2512     size = AOP_SIZE(IC_RESULT(ic));
2513     while (size--) {
2514 /*
2515         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2516         MOVA(l);       
2517         pic16_emitcode("cpl","a");
2518         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2519 */
2520         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2521               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2522         } else {
2523                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2524                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2525         }
2526         offset++;
2527
2528     }
2529
2530
2531 release:
2532     /* release the aops */
2533     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2534     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2535 }
2536 #endif
2537
2538 /*-----------------------------------------------------------------*/
2539 /* genUminusFloat - unary minus for floating points                */
2540 /*-----------------------------------------------------------------*/
2541 static void genUminusFloat(operand *op,operand *result)
2542 {
2543     int size ,offset =0 ;
2544     char *l;
2545
2546     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2547     /* for this we just need to flip the 
2548     first it then copy the rest in place */
2549     size = AOP_SIZE(op) - 1;
2550     l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2551
2552     MOVA(l);    
2553
2554     pic16_emitcode("cpl","acc.7");
2555     pic16_aopPut(AOP(result),"a",3);    
2556
2557     while(size--) {
2558         pic16_aopPut(AOP(result),
2559                pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2560                offset);
2561         offset++;
2562     }          
2563 }
2564
2565 /*-----------------------------------------------------------------*/
2566 /* genUminus - unary minus code generation                         */
2567 /*-----------------------------------------------------------------*/
2568 static void genUminus (iCode *ic)
2569 {
2570   int size, i;
2571   sym_link *optype, *rtype;
2572
2573         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2574         
2575         /* assign asmops */
2576         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2577         pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2578
2579         /* if both in bit space then special case */
2580         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2581                 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2582
2583                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2584                 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2585                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2586                 
2587                 goto release; 
2588         } 
2589
2590         optype = operandType(IC_LEFT(ic));
2591         rtype = operandType(IC_RESULT(ic));
2592
2593         /* if float then do float stuff */
2594         if (IS_FLOAT(optype)) {
2595                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2596                 goto release;
2597         }
2598
2599         /* otherwise subtract from zero by taking the 2's complement */
2600         size = AOP_SIZE(IC_LEFT(ic));
2601
2602         for(i=0; i<size; i++) {
2603                 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2604                         pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2605                 else {
2606                         pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2607                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2608                 }
2609         }
2610
2611         pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2612         for(i=1; i<size; i++) {
2613                 emitSKPNZ;
2614                 pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2615         }
2616
2617 release:
2618         /* release the aops */
2619         pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2620         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2621 }
2622
2623 #if 0
2624 /*-----------------------------------------------------------------*/
2625 /* saveRegisters - will look for a call and save the registers     */
2626 /*-----------------------------------------------------------------*/
2627 static void saveRegisters(iCode *lic) 
2628 {
2629     int i;
2630     iCode *ic;
2631     bitVect *rsave;
2632     sym_link *dtype;
2633
2634     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2635     /* look for call */
2636     for (ic = lic ; ic ; ic = ic->next) 
2637         if (ic->op == CALL || ic->op == PCALL)
2638             break;
2639
2640     if (!ic) {
2641         fprintf(stderr,"found parameter push with no function call\n");
2642         return ;
2643     }
2644
2645     /* if the registers have been saved already then
2646     do nothing */
2647     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2648         return ;
2649
2650     /* find the registers in use at this time 
2651     and push them away to safety */
2652     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2653                           ic->rUsed);
2654
2655     ic->regsSaved = 1;
2656     if (options.useXstack) {
2657         if (bitVectBitValue(rsave,R0_IDX))
2658             pic16_emitcode("mov","b,r0");
2659         pic16_emitcode("mov","r0,%s",spname);
2660         for (i = 0 ; i < pic16_nRegs ; i++) {
2661             if (bitVectBitValue(rsave,i)) {
2662                 if (i == R0_IDX)
2663                     pic16_emitcode("mov","a,b");
2664                 else
2665                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2666                 pic16_emitcode("movx","@r0,a");
2667                 pic16_emitcode("inc","r0");
2668             }
2669         }
2670         pic16_emitcode("mov","%s,r0",spname);
2671         if (bitVectBitValue(rsave,R0_IDX))
2672             pic16_emitcode("mov","r0,b");           
2673     }// else
2674     //for (i = 0 ; i < pic16_nRegs ; i++) {
2675     //    if (bitVectBitValue(rsave,i))
2676     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2677     //}
2678
2679     dtype = operandType(IC_LEFT(ic));
2680     if (currFunc && dtype && 
2681         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2682         IFFUNC_ISISR(currFunc->type) &&
2683         !ic->bankSaved) 
2684
2685         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2686
2687 }
2688 /*-----------------------------------------------------------------*/
2689 /* unsaveRegisters - pop the pushed registers                      */
2690 /*-----------------------------------------------------------------*/
2691 static void unsaveRegisters (iCode *ic)
2692 {
2693     int i;
2694     bitVect *rsave;
2695
2696     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2697     /* find the registers in use at this time 
2698     and push them away to safety */
2699     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2700                           ic->rUsed);
2701     
2702     if (options.useXstack) {
2703         pic16_emitcode("mov","r0,%s",spname);   
2704         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2705             if (bitVectBitValue(rsave,i)) {
2706                 pic16_emitcode("dec","r0");
2707                 pic16_emitcode("movx","a,@r0");
2708                 if (i == R0_IDX)
2709                     pic16_emitcode("mov","b,a");
2710                 else
2711                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2712             }       
2713
2714         }
2715         pic16_emitcode("mov","%s,r0",spname);
2716         if (bitVectBitValue(rsave,R0_IDX))
2717             pic16_emitcode("mov","r0,b");
2718     } //else
2719     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2720     //    if (bitVectBitValue(rsave,i))
2721     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2722     //}
2723
2724 }  
2725 #endif
2726
2727 #if 0  // patch 14
2728 /*-----------------------------------------------------------------*/
2729 /* pushSide -                                                      */
2730 /*-----------------------------------------------------------------*/
2731 static void pushSide(operand * oper, int size)
2732 {
2733         int offset = 0;
2734     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2735         while (size--) {
2736                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2737                 if (AOP_TYPE(oper) != AOP_REG &&
2738                     AOP_TYPE(oper) != AOP_DIR &&
2739                     strcmp(l,"a") ) {
2740                         pic16_emitcode("mov","a,%s",l);
2741                         pic16_emitcode("push","acc");
2742                 } else
2743                         pic16_emitcode("push","%s",l);
2744         }
2745 }
2746 #endif // patch 14
2747
2748 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2749 {
2750   if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2751     pic16_emitpcode(POC_MOVFW, src);
2752     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2753   } else {
2754     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2755         src, pic16_popGet(AOP(op), offset)));
2756   }
2757 }
2758
2759
2760 /*-----------------------------------------------------------------*/
2761 /* assignResultValue - assign results to oper, rescall==1 is       */
2762 /*                     called from genCall() or genPCall()         */
2763 /*-----------------------------------------------------------------*/
2764 static void assignResultValue(operand * oper, int rescall)
2765 {
2766   int size = AOP_SIZE(oper);
2767   int offset=0;
2768   
2769     DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2770     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2771
2772     if(rescall) {
2773       /* assign result from a call/pcall function() */
2774                 
2775       /* function results are stored in a special order,
2776        * see top of file with Function return policy, or manual */
2777
2778       if(size <= 4) {
2779         /* 8-bits, result in WREG */
2780         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2781                         
2782         if(size>1) {
2783           /* 16-bits, result in PRODL:WREG */
2784           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2785         }
2786                         
2787         if(size>2) {
2788           /* 24-bits, result in PRODH:PRODL:WREG */
2789           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2790         }
2791                         
2792         if(size>3) {
2793           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2794           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2795         }
2796       
2797       } else {
2798         /* >32-bits, result on stack, and FSR0 points to beginning.
2799          * Fix stack when done */
2800         /* FIXME FIXME */
2801         while (size--) {
2802 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2803 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2804                 
2805           popaopidx(AOP(oper), size, GpsuedoStkPtr);
2806           GpsuedoStkPtr++;
2807         }
2808                         
2809         /* fix stack */
2810         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2811         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2812         if(STACK_MODEL_LARGE) {
2813           emitSKPNC;
2814           pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2815         }
2816       }                 
2817     } else {
2818       int areg = 0;             /* matching argument register */
2819       
2820       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2821       /* its called from genReceive (probably) */
2822       if(!GpsuedoStkPtr) {
2823 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2824         /* The last byte in the assignment is in W */
2825         if(areg <= GpsuedoStkPtr) {
2826           size--;
2827           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2828           offset++;
2829         }
2830         GpsuedoStkPtr++;
2831         _G.stack_lat = AOP_SIZE(oper)-1;
2832       }
2833
2834       while (size) {
2835 //        DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2836 //        DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2837         if(areg <= GpsuedoStkPtr) {
2838           size--;
2839           popaopidx(AOP(oper), offset, GpsuedoStkPtr);
2840           offset++;
2841         }
2842         GpsuedoStkPtr++;
2843       }
2844     }
2845 }
2846
2847
2848 /*-----------------------------------------------------------------*/
2849 /* genIpush - genrate code for pushing this gets a little complex  */
2850 /*-----------------------------------------------------------------*/
2851 static void genIpush (iCode *ic)
2852 {
2853 //  int size, offset=0;
2854
2855   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2856
2857
2858   if(ic->parmPush) {
2859     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
2860
2861     /* send to stack as normal */
2862     addSet(&_G.sendSet,ic);
2863 //    addSetHead(&_G.sendSet,ic);
2864     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2865   }
2866
2867         
2868 #if 0
2869     int size, offset = 0 ;
2870     char *l;
2871
2872
2873     /* if this is not a parm push : ie. it is spill push 
2874     and spill push is always done on the local stack */
2875     if (!ic->parmPush) {
2876
2877         /* and the item is spilt then do nothing */
2878         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2879             return ;
2880
2881         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2882         size = AOP_SIZE(IC_LEFT(ic));
2883         /* push it on the stack */
2884         while(size--) {
2885             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2886             if (*l == '#') {
2887                 MOVA(l);
2888                 l = "acc";
2889             }
2890             pic16_emitcode("push","%s",l);
2891         }
2892         return ;        
2893     }
2894
2895     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2896 #endif
2897 }
2898
2899 /*-----------------------------------------------------------------*/
2900 /* genIpop - recover the registers: can happen only for spilling   */
2901 /*-----------------------------------------------------------------*/
2902 static void genIpop (iCode *ic)
2903 {
2904   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2905 #if 0
2906     int size,offset ;
2907
2908
2909     /* if the temp was not pushed then */
2910     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2911         return ;
2912
2913     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2914     size = AOP_SIZE(IC_LEFT(ic));
2915     offset = (size-1);
2916     while (size--) 
2917         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2918                                    FALSE,TRUE));
2919
2920     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2921 #endif
2922 }
2923
2924 #if 0
2925 /*-----------------------------------------------------------------*/
2926 /* unsaverbank - restores the resgister bank from stack            */
2927 /*-----------------------------------------------------------------*/
2928 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2929 {
2930   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2931 #if 0
2932     int i;
2933     asmop *aop ;
2934     regs *r = NULL;
2935
2936     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2937     if (popPsw) {
2938         if (options.useXstack) {
2939             aop = newAsmop(0);
2940             r = getFreePtr(ic,&aop,FALSE);
2941             
2942             
2943             pic16_emitcode("mov","%s,_spx",r->name);
2944             pic16_emitcode("movx","a,@%s",r->name);
2945             pic16_emitcode("mov","psw,a");
2946             pic16_emitcode("dec","%s",r->name);
2947             
2948         }else
2949             pic16_emitcode ("pop","psw");
2950     }
2951
2952     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2953         if (options.useXstack) {       
2954             pic16_emitcode("movx","a,@%s",r->name);
2955             //pic16_emitcode("mov","(%s+%d),a",
2956             //       regspic16[i].base,8*bank+regspic16[i].offset);
2957             pic16_emitcode("dec","%s",r->name);
2958
2959         } else 
2960           pic16_emitcode("pop",""); //"(%s+%d)",
2961         //regspic16[i].base,8*bank); //+regspic16[i].offset);
2962     }
2963
2964     if (options.useXstack) {
2965
2966         pic16_emitcode("mov","_spx,%s",r->name);
2967         pic16_freeAsmop(NULL,aop,ic,TRUE);
2968
2969     }
2970 #endif 
2971 }
2972
2973 /*-----------------------------------------------------------------*/
2974 /* saverbank - saves an entire register bank on the stack          */
2975 /*-----------------------------------------------------------------*/
2976 static void saverbank (int bank, iCode *ic, bool pushPsw)
2977 {
2978   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2979 #if 0
2980     int i;
2981     asmop *aop ;
2982     regs *r = NULL;
2983
2984     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2985     if (options.useXstack) {
2986
2987         aop = newAsmop(0);
2988         r = getFreePtr(ic,&aop,FALSE);  
2989         pic16_emitcode("mov","%s,_spx",r->name);
2990
2991     }
2992
2993     for (i = 0 ; i < pic16_nRegs ;i++) {
2994         if (options.useXstack) {
2995             pic16_emitcode("inc","%s",r->name);
2996             //pic16_emitcode("mov","a,(%s+%d)",
2997             //         regspic16[i].base,8*bank+regspic16[i].offset);
2998             pic16_emitcode("movx","@%s,a",r->name);           
2999         } else 
3000           pic16_emitcode("push","");// "(%s+%d)",
3001                      //regspic16[i].base,8*bank+regspic16[i].offset);
3002     }
3003     
3004     if (pushPsw) {
3005         if (options.useXstack) {
3006             pic16_emitcode("mov","a,psw");
3007             pic16_emitcode("movx","@%s,a",r->name);     
3008             pic16_emitcode("inc","%s",r->name);
3009             pic16_emitcode("mov","_spx,%s",r->name);       
3010             pic16_freeAsmop (NULL,aop,ic,TRUE);
3011             
3012         } else
3013             pic16_emitcode("push","psw");
3014         
3015         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3016     }
3017     ic->bankSaved = 1;
3018 #endif
3019 }
3020 #endif  /* 0 */
3021
3022
3023 /*-----------------------------------------------------------------*/
3024 /* genCall - generates a call statement                            */
3025 /*-----------------------------------------------------------------*/
3026 static void genCall (iCode *ic)
3027 {
3028   sym_link *ftype;   
3029   int stackParms=0;
3030   int use_wreg=0;
3031   char *fname;
3032   
3033     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3034
3035     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3036     /* if caller saves & we have not saved then */
3037 //    if (!ic->regsSaved)
3038 //      saveRegisters(ic);
3039
3040         /* initialise stackParms for IPUSH pushes */
3041 //      stackParms = psuedoStkPtr;
3042 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3043     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3044
3045 #if 0
3046     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3047 #endif
3048
3049     /* if send set is not empty the assign */
3050     if (_G.sendSet) {
3051       iCode *sic;
3052       int psuedoStkPtr=-1; 
3053       int firstTimeThruLoop = 1;
3054
3055
3056 #if 1
3057         /* reverse sendSet if function is not reentrant */
3058         if(!IFFUNC_ISREENT(ftype))
3059           _G.sendSet = reverseSet(_G.sendSet);
3060 #endif
3061
3062         /* First figure how many parameters are getting passed */
3063
3064 /*      do we really need to know this ? -- VR 
3065         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3066           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3067           psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
3068           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
3069         }
3070 */
3071
3072
3073 //        stackParms = psuedoStkPtr;
3074         stackParms = 0;
3075         use_wreg = 0;
3076         
3077         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3078           int size, offset = 0;
3079
3080             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3081             size = AOP_SIZE(IC_LEFT(sic));
3082
3083             stackParms += size;
3084
3085             while (size--) {
3086               DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3087                     pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3088               DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3089
3090               if(!firstTimeThruLoop) {
3091                 /* If this is not the first time we've been through the loop
3092                  * then we need to save the parameter in a temporary
3093                  * register. The last byte of the last parameter is
3094                  * passed in W. */
3095
3096                 pushw();
3097 //                --psuedoStkPtr;               // sanity check
3098               }
3099                 
3100               firstTimeThruLoop=0;
3101
3102               mov2w (AOP(IC_LEFT(sic)), size);
3103
3104               offset++;
3105             }
3106             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3107           }
3108
3109           /* save last parameter to stack if functions has varargs */
3110           if(IFFUNC_HASVARARGS(ftype))pushw();
3111           else use_wreg = 1;            /* last parameter in WREG */
3112           
3113           _G.stackRegSet = _G.sendSet;
3114           _G.sendSet = NULL;
3115     }
3116
3117     /* make the call */
3118     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3119
3120     GpsuedoStkPtr=0;
3121     /* if we need to assign a result value */
3122     if ((IS_ITEMP(IC_RESULT(ic))
3123           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3124               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3125         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3126
3127       _G.accInUse++;
3128       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3129       _G.accInUse--;
3130
3131       assignResultValue(IC_RESULT(ic), 1);
3132
3133       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3134                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3135                 
3136       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3137     }
3138
3139     if(!stackParms && ic->parmBytes) {
3140       stackParms = ic->parmBytes;
3141     }
3142       
3143     stackParms -= use_wreg;
3144       
3145     if(stackParms>0) {
3146       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3147       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3148       if(STACK_MODEL_LARGE) {
3149         emitSKPNC;
3150         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3151       }
3152     }
3153
3154 #if 0
3155     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3156 #endif
3157
3158     /* adjust the stack for parameters if required */
3159 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3160
3161 #if 0
3162       /* if register bank was saved then pop them */
3163       if (ic->bankSaved)
3164         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3165
3166       /* if we hade saved some registers then unsave them */
3167       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3168         unsaveRegisters (ic);
3169 #endif
3170 }
3171
3172
3173
3174 /*-----------------------------------------------------------------*/
3175 /* genPcall - generates a call by pointer statement                */
3176 /*            new version, created from genCall - HJD              */
3177 /*-----------------------------------------------------------------*/
3178 static void genPcall (iCode *ic)
3179 {
3180   sym_link *ftype;
3181   int stackParms=0;
3182   symbol *retlbl = newiTempLabel(NULL);
3183   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3184   int use_wreg=0;
3185   
3186     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3187
3188     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3189     
3190     /* if send set is not empty the assign */
3191     if (_G.sendSet) {
3192       iCode *sic;
3193       int psuedoStkPtr=-1; 
3194       int firstTimeThruLoop = 1;
3195
3196       /* For the Pic port, there is no data stack.
3197        * So parameters passed to functions are stored
3198        * in registers. (The pCode optimizer will get
3199        * rid of most of these :). */
3200
3201
3202 #if 1
3203       /* reverse sendSet if function is not reentrant */
3204       if(!IFFUNC_ISREENT(ftype))
3205         _G.sendSet = reverseSet(_G.sendSet);
3206 #endif
3207
3208       /* First figure how many parameters are getting passed */
3209 #if 0
3210       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3211         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3212         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
3213         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
3214       }
3215 #endif
3216
3217 //      stackParms = psuedoStkPtr;
3218       stackParms = 0;
3219
3220       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3221         int size, offset = 0;
3222
3223           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3224           size = AOP_SIZE(IC_LEFT(sic));
3225           stackParms += size;
3226
3227           while (size--) {
3228             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3229             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3230             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3231
3232             if(!firstTimeThruLoop) {
3233               /* If this is not the first time we've been through the loop
3234                * then we need to save the parameter in a temporary
3235                * register. The last byte of the last parameter is
3236                * passed in W. */
3237
3238               pushw();
3239               --psuedoStkPtr;           // sanity check
3240             }
3241                         
3242             firstTimeThruLoop=0;
3243
3244             mov2w (AOP(IC_LEFT(sic)), size);
3245
3246             offset++;
3247           }
3248
3249
3250           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3251       }
3252
3253       if(IFFUNC_HASVARARGS(ftype))
3254         pushw();
3255       else
3256         use_wreg = 1;           /* last parameter in WREG */
3257
3258       _G.stackRegSet = _G.sendSet;
3259       _G.sendSet = NULL;
3260     }
3261
3262     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3263
3264     // push return address
3265     // push $ on return stack, then replace with retlbl
3266
3267     pic16_emitpcodeNULLop(POC_PUSH);
3268
3269     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3270     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3271     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3272     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3273     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3274     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3275   
3276     /* make the call by writing the pointer into pc */
3277     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3278     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3279
3280     // note: MOVFF to PCL not allowed
3281     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3282     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3283
3284
3285     /* return address is here: (X) */
3286     pic16_emitpLabelFORCE(retlbl->key);
3287
3288     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3289
3290     GpsuedoStkPtr=0;
3291     /* if we need assign a result value */
3292     if ((IS_ITEMP(IC_RESULT(ic))
3293           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3294               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3295         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3296
3297       _G.accInUse++;
3298       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3299       _G.accInUse--;
3300
3301       assignResultValue(IC_RESULT(ic), 1);
3302
3303       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3304               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3305                 
3306       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3307     }
3308
3309     stackParms -= use_wreg;
3310     
3311     if(stackParms>0) {
3312       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3313       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3314       if(STACK_MODEL_LARGE) {
3315         /* this implies that stackParms < 256 !!! -- VR */
3316         emitSKPNC;
3317         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3318       }
3319     }
3320 }
3321
3322 /*-----------------------------------------------------------------*/
3323 /* resultRemat - result  is rematerializable                       */
3324 /*-----------------------------------------------------------------*/
3325 static int resultRemat (iCode *ic)
3326 {
3327   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3328   if (SKIP_IC(ic) || ic->op == IFX)
3329     return 0;
3330
3331   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3332     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3333     if (sym->remat && !POINTER_SET(ic)) 
3334       return 1;
3335   }
3336
3337   return 0;
3338 }
3339
3340 #if defined(__BORLANDC__) || defined(_MSC_VER)
3341 #define STRCASECMP stricmp
3342 #else
3343 #define STRCASECMP strcasecmp
3344 #endif
3345
3346 #if 0
3347 /*-----------------------------------------------------------------*/
3348 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3349 /*-----------------------------------------------------------------*/
3350 static bool inExcludeList(char *s)
3351 {
3352   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3353     int i =0;
3354     
3355     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3356     if (options.excludeRegs[i] &&
3357     STRCASECMP(options.excludeRegs[i],"none") == 0)
3358         return FALSE ;
3359
3360     for ( i = 0 ; options.excludeRegs[i]; i++) {
3361         if (options.excludeRegs[i] &&
3362         STRCASECMP(s,options.excludeRegs[i]) == 0)
3363             return TRUE;
3364     }
3365     return FALSE ;
3366 }
3367 #endif
3368
3369 /*-----------------------------------------------------------------*/
3370 /* genFunction - generated code for function entry                 */
3371 /*-----------------------------------------------------------------*/
3372 static void genFunction (iCode *ic)
3373 {
3374   symbol *sym;
3375   sym_link *ftype;
3376   
3377         DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3378
3379         pic16_labelOffset += (max_key+4);
3380         max_key=0;
3381         GpsuedoStkPtr=0;
3382         _G.nRegsSaved = 0;
3383         
3384         ftype = operandType(IC_LEFT(ic));
3385         sym = OP_SYMBOL(IC_LEFT(ic));
3386
3387         if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3388                 /* create an absolute section at the interrupt vector:
3389                  * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3390           symbol *asym;
3391           char asymname[128];
3392           pBlock *apb;
3393
3394                 {
3395                   int i, found=-1;
3396
3397                         sym = OP_SYMBOL( IC_LEFT(ic));
3398                         for(i=0;i<=2;i++) {
3399                                 if(interrupts[i]->name
3400                                         && !STRCASECMP(interrupts[i]->name, sym->name)) {
3401                                         found = i;
3402                                         break;
3403                                 }
3404                         }
3405                         
3406                         if(found == -1) {
3407                                 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3408                                         __FILE__, __LINE__, sym->name);
3409                                 assert( 0 );
3410                         }
3411                         _G.interruptvector = found;
3412                 }
3413
3414                 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3415                 asym = newSymbol(asymname, 0);
3416
3417                 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3418                 pic16_addpBlock( apb );
3419
3420                 pic16_addpCode2pBlock(apb,
3421                         pic16_newpCodeCharP(";-----------------------------------------"));
3422
3423
3424                 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3425
3426                 pic16_addpCode2pBlock(apb,
3427                         pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3428                 
3429                 /* mark the end of this tiny function */
3430                 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3431
3432                 {
3433                   absSym *abSym;
3434
3435                         abSym = Safe_calloc(1, sizeof(absSym));
3436                         abSym->name = Safe_strdup( asymname );
3437
3438                         switch( _G.interruptvector ) {
3439                                 case 0: abSym->address = 0x000000; break;
3440                                 case 1: abSym->address = 0x000008; break;
3441                                 case 2: abSym->address = 0x000018; break;
3442                         }
3443
3444                         /* relocate interrupt vectors if needed */
3445                         abSym->address += pic16_options.ivt_loc;
3446
3447                         addSet(&absSymSet, abSym);
3448                 }
3449         }
3450
3451
3452         /* create the function header */
3453         pic16_emitcode(";","-----------------------------------------");
3454         pic16_emitcode(";"," function %s",sym->name);
3455         pic16_emitcode(";","-----------------------------------------");
3456
3457         pic16_emitcode("","%s:",sym->rname);
3458         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3459
3460
3461         {
3462           absSym *ab;
3463
3464                 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
3465                         if(!strcmp(ab->name, sym->name)) {
3466                                 pic16_pBlockConvert2Absolute(pb);
3467                                 break;
3468                         }
3469
3470         }
3471
3472
3473         if(IFFUNC_ISNAKED(ftype)) {
3474                 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3475                 return;
3476         }
3477         
3478         /* if critical function then turn interrupts off */
3479         if (IFFUNC_ISCRITICAL(ftype)) {
3480           //pic16_emitcode("clr","ea");
3481         }
3482
3483         _G.fregsUsed = sym->regsUsed;
3484
3485         /* if this is an interrupt service routine then
3486          * save acc, b, dpl, dph  */
3487         if (IFFUNC_ISISR(sym->type)) {
3488           int i;
3489
3490                 _G.usefastretfie = 1;   /* use shadow registers by default */
3491                 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3492                 if(!(_G.interruptvector == 1)) {
3493
3494                         /* do not save WREG,STATUS,BSR for high priority interrupts
3495                          * because they are stored in the hardware shadow registers already */
3496                         _G.usefastretfie = 0;
3497                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3498                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3499                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3500                 }
3501
3502
3503                 /* these should really be optimized somehow, because not all
3504                  * interrupt handlers modify them */
3505                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3506                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3507                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3508                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3509
3510 //                pic16_pBlockConvert2ISR(pb);
3511                 
3512                 /* if any registers used */
3513                 if (sym->regsUsed) {
3514                         /* save the registers used */
3515                         DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3516                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3517                                 if (bitVectBitValue(sym->regsUsed,i)) {
3518 #if 0
3519                                         fprintf(stderr, "%s:%d function %s uses register %s\n",
3520                                                         __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3521                                                         pic16_regWithIdx(i)->name);
3522 #endif
3523
3524                                         pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3525                                         _G.nRegsSaved++;
3526
3527                                         if(!pic16_regWithIdx(i)->wasUsed) {
3528                                                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3529                                                         __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3530
3531                                                 pic16_regWithIdx(i)->wasUsed = 1;
3532                                         }
3533                                 }
3534                         }
3535                 }
3536         } else {
3537                 /* emit code to setup stack frame if user enabled,
3538                  * and function is not main() */
3539          
3540 //              fprintf(stderr, "function name: %s\n", sym->name);
3541                 if(strcmp(sym->name, "main")) {
3542                         if(/*!options.ommitFramePtr || sym->regsUsed*/1) {
3543                         /* setup the stack frame */
3544                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3545                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3546                                 if(STACK_MODEL_LARGE)
3547                                         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3548                         }
3549                 }
3550
3551                 /* if callee-save to be used for this function
3552                 * then save the registers being used in this function */
3553 //              if (IFFUNC_CALLEESAVES(sym->type))
3554                 {
3555                   int i;
3556
3557 //                      fprintf(stderr, "%s:%d function sym->regsUsed= %d\n", __FILE__, __LINE__, sym->regsUsed->size);
3558
3559 //                      pic16_emitpcomment("entry regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3560
3561                         /* if any registers used */
3562                         if (sym->regsUsed) {
3563                                 /* save the registers used */
3564                                 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3565                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3566                                         if (bitVectBitValue(sym->regsUsed,i)) {
3567
3568 #if 0
3569                                                 fprintf(stderr, "%s:%d function %s uses register %s (wasUsed: %d, %p)\n",
3570                                                                 __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3571                                                                 pic16_regWithIdx(i)->name,
3572                                                                 pic16_regWithIdx(i)->wasUsed,
3573                                                                 pic16_regWithIdx(i));
3574 #endif
3575
3576                                                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3577
3578 //                                              pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3579 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
3580 //                                                      &pic16_pc_postdec1, 0));
3581
3582                                                 _G.nRegsSaved++;
3583
3584                                                 if(!pic16_regWithIdx(i)->wasUsed) {
3585                                                         fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3586                                                                 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3587
3588                                                         pic16_regWithIdx(i)->wasUsed = 1;
3589                                                 }
3590                                         
3591                                         }
3592                                 }
3593                         }
3594                 }
3595         }
3596
3597
3598         
3599 #if 0
3600         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3601
3602                 if (options.useXstack) {
3603                         pic16_emitcode("mov","r0,%s",spname);
3604                         pic16_emitcode("mov","a,_bp");
3605                         pic16_emitcode("movx","@r0,a");
3606                         pic16_emitcode("inc","%s",spname);
3607                 } else {
3608                         /* set up the stack */
3609                         pic16_emitcode ("push","_bp");     /* save the callers stack  */
3610                 }
3611                 pic16_emitcode ("mov","_bp,%s",spname);
3612         }
3613 #endif
3614         DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3615
3616         /* adjust the stack for the function */
3617         if (sym->stack) {
3618           int i = sym->stack;
3619
3620                 if (i > 127 ) 
3621                         werror(W_STACK_OVERFLOW,sym->name);
3622
3623                 if (i > 3 && sym->recvSize < 4) {              
3624                         pic16_emitcode ("mov","a,sp");
3625                         pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3626                         pic16_emitcode ("mov","sp,a");
3627                 } else
3628                         while(i--)
3629                                 pic16_emitcode("inc","sp");
3630         }
3631
3632         if (sym->xstack) {
3633                 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3634
3635                 pic16_emitcode ("mov","a,_spx");
3636                 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3637                 pic16_emitcode ("mov","_spx,a");
3638         }
3639     
3640 }
3641
3642 /*-----------------------------------------------------------------*/
3643 /* genEndFunction - generates epilogue for functions               */
3644 /*-----------------------------------------------------------------*/
3645 static void genEndFunction (iCode *ic)
3646 {
3647     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3648
3649     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3650
3651     if(IFFUNC_ISNAKED(sym->type)) {
3652         DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3653         return;
3654     }
3655
3656     _G.stack_lat = 0;
3657
3658     /* add code for ISCRITICAL */
3659     if(IFFUNC_ISCRITICAL(sym->type)) {
3660       /* if critical function, turn on interrupts */
3661       
3662       /* TODO: add code here -- VR */
3663     }
3664     
3665
3666 #if 0
3667     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3668     {
3669         pic16_emitcode ("mov","%s,_bp",spname);
3670     }
3671 #endif
3672
3673     /* if use external stack but some variables were
3674     added to the local stack then decrement the
3675     local stack */
3676     if (options.useXstack && sym->stack) {      
3677         pic16_emitcode("mov","a,sp");
3678         pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3679         pic16_emitcode("mov","sp,a");
3680     }
3681
3682
3683 #if 0
3684     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3685         if (options.useXstack) {
3686             pic16_emitcode("mov","r0,%s",spname);
3687             pic16_emitcode("movx","a,@r0");
3688             pic16_emitcode("mov","_bp,a");
3689             pic16_emitcode("dec","%s",spname);
3690         }
3691         else
3692         {
3693             pic16_emitcode ("pop","_bp");
3694         }
3695     }
3696 #endif
3697
3698         if (IFFUNC_ISISR(sym->type)) {
3699                 /* now we need to restore the registers */
3700                 /* if any registers used */
3701                 if (sym->regsUsed) {
3702                   int i;
3703
3704                         /* restore registers used */
3705                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3706                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3707                                 if (bitVectBitValue(sym->regsUsed,i)) {
3708
3709 //                                      fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3710 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3711 //                                                      pic16_regWithIdx(i)->name);
3712
3713                                         pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3714
3715 //                                      pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3716 //                                                      &pic16_pc_preinc1,
3717 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3718
3719                                 }
3720                         }
3721                 }
3722         
3723                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3724                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3725                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3726                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3727
3728                 if(!(_G.interruptvector == 1)) {
3729                         /* do not restore interrupt vector for WREG,STATUS,BSR
3730                          * for high priority interrupt, see genFunction */
3731                          
3732                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3733                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3734                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3735                 }
3736         
3737                 _G.interruptvector = 0;         /* sanity check */
3738
3739 //              pic16_pBlockConvert2ISR(pb);
3740
3741
3742                 /* if debug then send end of function */
3743 /*      if (options.debug && currFunc)  */
3744                 if (currFunc) {
3745                         debugFile->writeEndFunction (currFunc, ic, 1);
3746                 }
3747         
3748                 if(_G.usefastretfie)
3749                         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3750                 else
3751                 pic16_emitpcodeNULLop(POC_RETFIE);
3752                 _G.usefastretfie = 0;
3753         } else {
3754                 if (IFFUNC_ISCRITICAL(sym->type))
3755                         pic16_emitcode("setb","ea");
3756         
3757
3758 //              pic16_emitpcomment("exit regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3759
3760                 /* if any registers used */
3761                 if (sym->regsUsed) {
3762                   int i;
3763                         /* save the registers used */
3764                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3765                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3766                                 if (bitVectBitValue(sym->regsUsed,i)) {
3767         
3768 //                                      fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3769 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3770 //                                                      pic16_regWithIdx(i)->name);
3771         
3772                                         pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3773                                         
3774 //                                      pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3775 //                                              &pic16_pc_preinc1,
3776 //                                              PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3777
3778                                         _G.nRegsSaved--;
3779                                 }
3780                         }
3781                 }
3782         
3783 //              pic16_emitpcomment("%s: _G.nRegsSaved upon exit from function: %d\n", __FUNCTION__, _G.nRegsSaved);
3784                 /* if debug then send end of function */
3785                 if (currFunc) {
3786                         debugFile->writeEndFunction (currFunc, ic, 1);
3787                 }
3788
3789                 /* insert code to restore stack frame, if user enabled it
3790                  * and function is not main() */
3791          
3792
3793                 if(strcmp(sym->name, "main")) {
3794                         if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) {
3795                                 /* restore stack frame */
3796                                 if(STACK_MODEL_LARGE)
3797                                         pic16_emitpcode(POC_MOVFF,
3798                                                 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3799                                 pic16_emitpcode(POC_MOVFF,
3800                                                 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3801                         }
3802                 }
3803
3804                 pic16_emitpcodeNULLop(POC_RETURN);
3805
3806                 /* Mark the end of a function */
3807                 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3808         }
3809
3810 }
3811
3812
3813 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3814 {
3815
3816         if(is_LitOp(op)) {
3817                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12
3818
3819                 if(dest->type != PO_WREG)
3820                         pic16_emitpcode(POC_MOVWF, dest);
3821         } else {
3822                 if(dest->type == PO_WREG && (offset == 0)) {
3823                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3824                         return;
3825                 }
3826                 
3827                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3828                         pic16_popGet(AOP(op), offset), dest));
3829         }
3830 }
3831
3832 /*-----------------------------------------------------------------*/
3833 /* genRet - generate code for return statement                     */
3834 /*-----------------------------------------------------------------*/
3835 static void genRet (iCode *ic)
3836 {
3837   int size;
3838   operand *left;
3839
3840         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3841         /* if we have no return value then
3842          * just generate the "ret" */
3843         
3844         if (!IC_LEFT(ic)) 
3845                 goto jumpret;       
3846     
3847         /* we have something to return then
3848          * move the return value into place */
3849         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3850         size = AOP_SIZE(IC_LEFT(ic));
3851
3852         if(size <= 4) {
3853                 if(size>3) {
3854                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3855 //                      pic16_emitpcode(POC_MOVFF,
3856 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3857                 }
3858                 if(size>2) {
3859                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3860 //                      pic16_emitpcode(POC_MOVFF,
3861 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3862                 }
3863                 if(size>1) {
3864                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3865 //                      pic16_emitpcode(POC_MOVFF,
3866 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3867                 }
3868
3869 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3870
3871                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3872 //              pic16_emitpcode(POC_MOVFF,
3873 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3874
3875         } else {
3876                 /* >32-bits, setup stack and FSR0 */
3877                 while (size--) {
3878 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3879 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3880
3881                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3882
3883 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3884                         GpsuedoStkPtr++;
3885                 }
3886                         
3887                 /* setup FSR0 */
3888                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3889                         pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3890
3891                 if(STACK_MODEL_LARGE) {
3892                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3893                                 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3894                 } else {
3895                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3896                 }
3897         }
3898                                 
3899 #if 0
3900         /* old code, left here for reference -- VR */    
3901         while (size--) {
3902           char *l ;
3903
3904                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3905                         /* #NOCHANGE */
3906                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3907                         pic16_emitpcomment("push %s",l);
3908                         pushed++;
3909                 } else {
3910                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3911                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3912                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3913                         
3914                         if (strcmp(fReturn[offset],l)) {
3915                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3916                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3917                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3918                                 } else {
3919                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3920                                 }
3921                                 
3922                                 if(size) {
3923                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3924                                 }
3925                                 offset++;
3926                         }
3927                 }
3928         }    
3929
3930         if (pushed) {
3931                 while(pushed) {
3932                         pushed--;
3933                         if (strcmp(fReturn[pushed],"a"))
3934                                 pic16_emitcode("pop",fReturn[pushed]);
3935                         else
3936                                 pic16_emitcode("pop","acc");
3937                 }
3938         }
3939 #endif
3940
3941
3942         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3943     
3944 jumpret:
3945         /* generate a jump to the return label
3946          * if the next is not the return statement */
3947         if (!(ic->next && ic->next->op == LABEL
3948                 && IC_LABEL(ic->next) == returnLabel)) {
3949         
3950                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3951                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3952         }
3953 }
3954
3955 /*-----------------------------------------------------------------*/
3956 /* genLabel - generates a label                                    */
3957 /*-----------------------------------------------------------------*/
3958 static void genLabel (iCode *ic)
3959 {
3960
3961
3962     /* special case never generate */
3963     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3964     if (IC_LABEL(ic) == entryLabel)
3965         return ;
3966
3967     pic16_emitpLabel(IC_LABEL(ic)->key);
3968     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3969 }
3970
3971 /*-----------------------------------------------------------------*/
3972 /* genGoto - generates a goto                                      */
3973 /*-----------------------------------------------------------------*/
3974 //tsd
3975 static void genGoto (iCode *ic)
3976 {
3977   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3978   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3979 }
3980
3981
3982 /*-----------------------------------------------------------------*/
3983 /* genMultbits :- multiplication of bits                           */
3984 /*-----------------------------------------------------------------*/
3985 static void genMultbits (operand *left, 
3986                          operand *right, 
3987                          operand *result)
3988 {
3989   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3990
3991   if(!pic16_sameRegs(AOP(result),AOP(right)))
3992     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3993
3994   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3995   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3996   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3997
3998 }
3999
4000
4001 /*-----------------------------------------------------------------*/
4002 /* genMultOneByte : 8 bit multiplication & division                */
4003 /*-----------------------------------------------------------------*/
4004 static void genMultOneByte (operand *left,
4005                             operand *right,
4006                             operand *result)
4007 {
4008
4009   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4010   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4011   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4012
4013   /* (if two literals, the value is computed before) */
4014   /* if one literal, literal on the right */
4015   if (AOP_TYPE(left) == AOP_LIT){
4016     operand *t = right;
4017     right = left;
4018     left = t;
4019   }
4020
4021         /* size is already checked in genMult == 1 */
4022 //      size = AOP_SIZE(result);
4023
4024         if (AOP_TYPE(right) == AOP_LIT){
4025                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4026                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4027                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4028                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4029         } else {
4030                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4031                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4032                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4033                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4034         }
4035         
4036         pic16_genMult8X8_8 (left, right,result);
4037 }
4038
4039 /*-----------------------------------------------------------------*/
4040 /* genMultOneWord : 16 bit multiplication                          */
4041 /*-----------------------------------------------------------------*/
4042 static void genMultOneWord (operand *left,
4043                             operand *right,
4044                             operand *result)
4045 {
4046
4047         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4048         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4049         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4050
4051         /* (if two literals, the value is computed before)
4052          * if one literal, literal on the right */
4053         if (AOP_TYPE(left) == AOP_LIT){
4054           operand *t = right;
4055                 right = left;
4056                 left = t;
4057         }
4058
4059         /* size is checked already == 2 */
4060 //      size = AOP_SIZE(result);
4061
4062         if (AOP_TYPE(right) == AOP_LIT) {
4063                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4064                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4065                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4066                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4067         } else {
4068                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4069                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4070                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4071                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4072         }
4073         
4074         pic16_genMult16X16_16(left, right,result);
4075 }
4076
4077 /*-----------------------------------------------------------------*/
4078 /* genMultOneLong : 32 bit multiplication                          */
4079 /*-----------------------------------------------------------------*/
4080 static void genMultOneLong (operand *left,
4081                             operand *right,
4082                             operand *result)
4083 {
4084
4085         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4086         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4087         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4088
4089         /* (if two literals, the value is computed before)
4090          * if one literal, literal on the right */
4091         if (AOP_TYPE(left) == AOP_LIT){
4092           operand *t = right;
4093                 right = left;
4094                 left = t;
4095         }
4096
4097         /* size is checked already == 4 */
4098 //      size = AOP_SIZE(result);
4099
4100         if (AOP_TYPE(right) == AOP_LIT) {
4101                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4102                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4103                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4104                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4105         } else {
4106                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4107                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4108                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4109                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4110         }
4111         
4112         pic16_genMult32X32_32(left, right,result);
4113 }
4114
4115
4116
4117 /*-----------------------------------------------------------------*/
4118 /* genMult - generates code for multiplication                     */
4119 /*-----------------------------------------------------------------*/
4120 static void genMult (iCode *ic)
4121 {
4122   operand *left = IC_LEFT(ic);
4123   operand *right = IC_RIGHT(ic);
4124   operand *result= IC_RESULT(ic);   
4125
4126         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4127         /* assign the amsops */
4128         pic16_aopOp (left,ic,FALSE);
4129         pic16_aopOp (right,ic,FALSE);
4130         pic16_aopOp (result,ic,TRUE);
4131
4132         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4133
4134         /* special cases first *
4135         * both are bits */
4136         if (AOP_TYPE(left) == AOP_CRY
4137                 && AOP_TYPE(right)== AOP_CRY) {
4138                 genMultbits(left,right,result);
4139           goto release ;
4140         }
4141
4142         /* if both are of size == 1 */
4143         if(AOP_SIZE(left) == 1
4144                 && AOP_SIZE(right) == 1) {
4145                 genMultOneByte(left,right,result);
4146           goto release ;
4147         }
4148
4149         /* if both are of size == 2 */
4150         if(AOP_SIZE(left) == 2
4151                 && AOP_SIZE(right) == 2) {
4152                 genMultOneWord(left, right, result);
4153           goto release;
4154         }
4155         
4156         /* if both are of size == 4 */
4157         if(AOP_SIZE(left) == 4
4158                 && AOP_SIZE(right) == 4) {
4159                 genMultOneLong(left, right, result);
4160           goto release;
4161         }
4162         
4163         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4164
4165
4166         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4167         /* should have been converted to function call */
4168         assert(0) ;
4169
4170 release :
4171         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4172         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4173         pic16_freeAsmop(result,NULL,ic,TRUE); 
4174 }
4175
4176 /*-----------------------------------------------------------------*/
4177 /* genDivbits :- division of bits                                  */
4178 /*-----------------------------------------------------------------*/
4179 static void genDivbits (operand *left, 
4180                         operand *right, 
4181                         operand *result)
4182 {
4183
4184     char *l;
4185
4186     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4187     /* the result must be bit */    
4188     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4189     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4190
4191     MOVA(l);    
4192
4193     pic16_emitcode("div","ab");
4194     pic16_emitcode("rrc","a");
4195     pic16_aopPut(AOP(result),"c",0);
4196 }
4197
4198 /*-----------------------------------------------------------------*/
4199 /* genDivOneByte : 8 bit division                                  */
4200 /*-----------------------------------------------------------------*/
4201 static void genDivOneByte (operand *left,
4202                            operand *right,
4203                            operand *result)
4204 {
4205     sym_link *opetype = operandType(result);
4206     char *l ;
4207     symbol *lbl ;
4208     int size,offset;
4209
4210         /* result = divident / divisor
4211          * - divident may be a register or a literal,
4212          * - divisor may be a register or a literal,
4213          * so there are 3 cases (literal / literal is optimized
4214          * by the front-end) to handle.
4215          * In addition we must handle signed and unsigned, which
4216          * result in 6 final different cases -- VR */
4217
4218     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4219     size = AOP_SIZE(result) - 1;
4220     offset = 1;
4221     /* signed or unsigned */
4222     if (SPEC_USIGN(opetype)) {
4223       pCodeOp *pct1,    /* count */
4224                 *pct2,  /* reste */
4225                 *pct3;  /* temp */
4226       symbol *label1, *label2, *label3;;
4227
4228
4229         /* unsigned is easy */
4230
4231         pct1 = pic16_popGetTempReg(1);
4232         pct2 = pic16_popGetTempReg(1);
4233         pct3 = pic16_popGetTempReg(1);
4234         
4235         label1 = newiTempLabel(NULL);
4236         label2 = newiTempLabel(NULL);
4237         label3 = newiTempLabel(NULL);
4238
4239         /* the following algorithm is extracted from divuint.c */
4240
4241         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4242         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4243         
4244         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4245
4246         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4247         
4248         pic16_emitpLabel(label1->key);
4249         
4250         emitCLRC;
4251         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4252
4253
4254         emitCLRC;
4255         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4256         
4257
4258         emitSKPNC;
4259         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4260         
4261         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4262         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4263         
4264         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4265         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4266         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4267         
4268         pic16_emitpLabel( label3->key );
4269         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4270         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4271         
4272         
4273
4274         pic16_emitpLabel(label2->key);
4275         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4276         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4277         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4278         
4279         /* result is in wreg */
4280         if(AOP_TYPE(result) != AOP_ACC)
4281                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4282
4283         pic16_popReleaseTempReg( pct3, 1);
4284         pic16_popReleaseTempReg( pct2, 1);
4285         pic16_popReleaseTempReg( pct1, 1);
4286
4287         return ;
4288     }
4289
4290     /* signed is a little bit more difficult */
4291
4292     /* save the signs of the operands */
4293     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4294     MOVA(l);    
4295     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4296     pic16_emitcode("push","acc"); /* save it on the stack */
4297
4298     /* now sign adjust for both left & right */
4299     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4300     MOVA(l);       
4301     lbl = newiTempLabel(NULL);
4302     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4303     pic16_emitcode("cpl","a");   
4304     pic16_emitcode("inc","a");
4305     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4306     pic16_emitcode("mov","b,a");
4307
4308     /* sign adjust left side */
4309     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4310     MOVA(l);
4311
4312     lbl = newiTempLabel(NULL);
4313     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4314     pic16_emitcode("cpl","a");
4315     pic16_emitcode("inc","a");
4316     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4317
4318     /* now the division */
4319     pic16_emitcode("div","ab");
4320     /* we are interested in the lower order
4321     only */
4322     pic16_emitcode("mov","b,a");
4323     lbl = newiTempLabel(NULL);
4324     pic16_emitcode("pop","acc");   
4325     /* if there was an over flow we don't 
4326     adjust the sign of the result */
4327     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4328     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4329     CLRC;
4330     pic16_emitcode("clr","a");
4331     pic16_emitcode("subb","a,b");
4332     pic16_emitcode("mov","b,a");
4333     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4334
4335     /* now we are done */
4336     pic16_aopPut(AOP(result),"b",0);
4337     if(size > 0){
4338         pic16_emitcode("mov","c,b.7");
4339         pic16_emitcode("subb","a,acc");   
4340     }
4341     while (size--)
4342         pic16_aopPut(AOP(result),"a",offset++);
4343
4344 }
4345
4346 /*-----------------------------------------------------------------*/
4347 /* genDiv - generates code for division                            */
4348 /*-----------------------------------------------------------------*/
4349 static void genDiv (iCode *ic)
4350 {
4351     operand *left = IC_LEFT(ic);
4352     operand *right = IC_RIGHT(ic);
4353     operand *result= IC_RESULT(ic);   
4354
4355
4356         /* Division is a very lengthy algorithm, so it is better
4357          * to call support routines than inlining algorithm.
4358          * Division functions written here just in case someone
4359          * wants to inline and not use the support libraries -- VR */
4360
4361     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4362     /* assign the amsops */
4363     pic16_aopOp (left,ic,FALSE);
4364     pic16_aopOp (right,ic,FALSE);
4365     pic16_aopOp (result,ic,TRUE);
4366
4367     /* special cases first */
4368     /* both are bits */
4369     if (AOP_TYPE(left) == AOP_CRY &&
4370         AOP_TYPE(right)== AOP_CRY) {
4371         genDivbits(left,right,result);
4372         goto release ;
4373     }
4374
4375     /* if both are of size == 1 */
4376     if (AOP_SIZE(left) == 1 &&
4377         AOP_SIZE(right) == 1 ) {
4378         genDivOneByte(left,right,result);
4379         goto release ;
4380     }
4381
4382     /* should have been converted to function call */
4383     assert(0);
4384 release :
4385     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4386     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4387     pic16_freeAsmop(result,NULL,ic,TRUE); 
4388 }
4389
4390 /*-----------------------------------------------------------------*/
4391 /* genModbits :- modulus of bits                                   */
4392 /*-----------------------------------------------------------------*/
4393 static void genModbits (operand *left, 
4394                         operand *right, 
4395                         operand *result)
4396 {
4397
4398     char *l;
4399
4400     /* the result must be bit */    
4401     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4402     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4403
4404     MOVA(l);       
4405
4406     pic16_emitcode("div","ab");
4407     pic16_emitcode("mov","a,b");
4408     pic16_emitcode("rrc","a");
4409     pic16_aopPut(AOP(result),"c",0);
4410 }
4411
4412 /*-----------------------------------------------------------------*/
4413 /* genModOneByte : 8 bit modulus                                   */
4414 /*-----------------------------------------------------------------*/
4415 static void genModOneByte (operand *left,
4416                            operand *right,
4417                            operand *result)
4418 {
4419     sym_link *opetype = operandType(result);
4420     char *l ;
4421     symbol *lbl ;
4422
4423     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4424     /* signed or unsigned */
4425     if (SPEC_USIGN(opetype)) {
4426         /* unsigned is easy */
4427         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4428         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4429         MOVA(l);    
4430         pic16_emitcode("div","ab");
4431         pic16_aopPut(AOP(result),"b",0);
4432         return ;
4433     }
4434
4435     /* signed is a little bit more difficult */
4436
4437     /* save the signs of the operands */
4438     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4439     MOVA(l);
4440
4441     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4442     pic16_emitcode("push","acc"); /* save it on the stack */
4443
4444     /* now sign adjust for both left & right */
4445     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4446     MOVA(l);
4447
4448     lbl = newiTempLabel(NULL);
4449     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4450     pic16_emitcode("cpl","a");   
4451     pic16_emitcode("inc","a");
4452     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4453     pic16_emitcode("mov","b,a"); 
4454
4455     /* sign adjust left side */
4456     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4457     MOVA(l);
4458
4459     lbl = newiTempLabel(NULL);
4460     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4461     pic16_emitcode("cpl","a");   
4462     pic16_emitcode("inc","a");
4463     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4464
4465     /* now the multiplication */
4466     pic16_emitcode("div","ab");
4467     /* we are interested in the lower order
4468     only */
4469     lbl = newiTempLabel(NULL);
4470     pic16_emitcode("pop","acc");   
4471     /* if there was an over flow we don't 
4472     adjust the sign of the result */
4473     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4474     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4475     CLRC ;
4476     pic16_emitcode("clr","a");
4477     pic16_emitcode("subb","a,b");
4478     pic16_emitcode("mov","b,a");
4479     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4480
4481     /* now we are done */
4482     pic16_aopPut(AOP(result),"b",0);
4483
4484 }
4485
4486 /*-----------------------------------------------------------------*/
4487 /* genMod - generates code for division                            */
4488 /*-----------------------------------------------------------------*/
4489 static void genMod (iCode *ic)
4490 {
4491     operand *left = IC_LEFT(ic);
4492     operand *right = IC_RIGHT(ic);
4493     operand *result= IC_RESULT(ic);  
4494
4495     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4496     /* assign the amsops */
4497     pic16_aopOp (left,ic,FALSE);
4498     pic16_aopOp (right,ic,FALSE);
4499     pic16_aopOp (result,ic,TRUE);
4500
4501     /* special cases first */
4502     /* both are bits */
4503     if (AOP_TYPE(left) == AOP_CRY &&
4504         AOP_TYPE(right)== AOP_CRY) {
4505         genModbits(left,right,result);
4506         goto release ;
4507     }
4508
4509     /* if both are of size == 1 */
4510     if (AOP_SIZE(left) == 1 &&
4511         AOP_SIZE(right) == 1 ) {
4512         genModOneByte(left,right,result);
4513         goto release ;
4514     }
4515
4516     /* should have been converted to function call */
4517     assert(0);
4518
4519 release :
4520     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4521     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4522     pic16_freeAsmop(result,NULL,ic,TRUE); 
4523 }
4524
4525 /*-----------------------------------------------------------------*/
4526 /* genIfxJump :- will create a jump depending on the ifx           */
4527 /*-----------------------------------------------------------------*/
4528 /*
4529   note: May need to add parameter to indicate when a variable is in bit space.
4530 */
4531 static void genIfxJump (iCode *ic, char *jval)
4532 {
4533
4534     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4535     /* if true label then we jump if condition
4536     supplied is true */
4537     if ( IC_TRUE(ic) ) {
4538
4539         if(strcmp(jval,"a") == 0)
4540           emitSKPZ;
4541         else if (strcmp(jval,"c") == 0)
4542           emitSKPC;
4543         else {
4544           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4545           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4546         }
4547
4548         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4549         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4550
4551     }
4552     else {
4553         /* false label is present */
4554         if(strcmp(jval,"a") == 0)
4555           emitSKPNZ;
4556         else if (strcmp(jval,"c") == 0)
4557           emitSKPNC;
4558         else {
4559           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4560           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4561         }
4562
4563         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4564         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4565
4566     }
4567
4568
4569     /* mark the icode as generated */
4570     ic->generated = 1;
4571 }
4572
4573 #if 0
4574 // not needed ATM
4575
4576 /*-----------------------------------------------------------------*/
4577 /* genSkip                                                         */
4578 /*-----------------------------------------------------------------*/
4579 static void genSkip(iCode *ifx,int status_bit)
4580 {
4581   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4582   if(!ifx)
4583     return;
4584
4585   if ( IC_TRUE(ifx) ) {
4586     switch(status_bit) {
4587     case 'z':
4588       emitSKPNZ;
4589       break;
4590
4591     case 'c':
4592       emitSKPNC;
4593       break;
4594
4595     case 'd':
4596       emitSKPDC;
4597       break;
4598
4599     }
4600
4601     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4602     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4603
4604   } else {
4605
4606     switch(status_bit) {
4607
4608     case 'z':
4609       emitSKPZ;
4610       break;
4611
4612     case 'c':
4613       emitSKPC;
4614       break;
4615
4616     case 'd':
4617       emitSKPDC;
4618       break;
4619     }
4620     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4621     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4622
4623   }
4624
4625 }
4626 #endif
4627
4628 /*-----------------------------------------------------------------*/
4629 /* genSkipc                                                        */
4630 /*-----------------------------------------------------------------*/
4631 static void genSkipc(resolvedIfx *rifx)
4632 {
4633   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4634   
4635   if(!rifx)
4636     return;
4637
4638   if(rifx->condition)
4639     emitSKPC;
4640   else
4641     emitSKPNC;
4642
4643   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4644   rifx->generated = 1;
4645 }
4646
4647 /*-----------------------------------------------------------------*/
4648 /* genSkipz2                                                       */
4649 /*-----------------------------------------------------------------*/
4650 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4651 {
4652   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4653   
4654   if(!rifx)
4655     return;
4656
4657   if( (rifx->condition ^ invert_condition) & 1)
4658     emitSKPZ;
4659   else
4660     emitSKPNZ;
4661
4662   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4663   rifx->generated = 1;
4664 }
4665
4666 #if 0
4667 /*-----------------------------------------------------------------*/
4668 /* genSkipz                                                        */
4669 /*-----------------------------------------------------------------*/
4670 static void genSkipz(iCode *ifx, int condition)
4671 {
4672   if(!ifx)
4673     return;
4674
4675   if(condition)
4676     emitSKPNZ;
4677   else
4678     emitSKPZ;
4679
4680   if ( IC_TRUE(ifx) )
4681     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4682   else
4683     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4684
4685   if ( IC_TRUE(ifx) )
4686     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4687   else
4688     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4689
4690 }
4691 #endif
4692
4693 /*-----------------------------------------------------------------*/
4694 /* genSkipCond                                                     */
4695 /*-----------------------------------------------------------------*/
4696 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4697 {
4698   if(!rifx)
4699     return;
4700
4701   if(rifx->condition)
4702     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4703   else
4704     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4705
4706
4707   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4708   rifx->generated = 1;
4709 }
4710
4711 #if 0
4712 /*-----------------------------------------------------------------*/
4713 /* genChkZeroes :- greater or less than comparison                 */
4714 /*     For each byte in a literal that is zero, inclusive or the   */
4715 /*     the corresponding byte in the operand with W                */
4716 /*     returns true if any of the bytes are zero                   */
4717 /*-----------------------------------------------------------------*/
4718 static int genChkZeroes(operand *op, int lit,  int size)
4719 {
4720
4721   int i;
4722   int flag =1;
4723
4724   while(size--) {
4725     i = (lit >> (size*8)) & 0xff;
4726
4727     if(i==0) {
4728       if(flag) 
4729         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4730       else
4731         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4732       flag = 0;
4733     }
4734   }
4735
4736   return (flag==0);
4737 }
4738 #endif
4739
4740 /*-----------------------------------------------------------------*/
4741 /* genCmp :- greater or less than comparison                       */
4742 /*-----------------------------------------------------------------*/
4743 static void genCmp (operand *left,operand *right,
4744                     operand *result, iCode *ifx, int sign)
4745 {
4746   int size; //, offset = 0 ;
4747   unsigned long lit = 0L,i = 0;
4748   resolvedIfx rFalseIfx;
4749   //  resolvedIfx rTrueIfx;
4750   symbol *truelbl;
4751   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4752 /*
4753   if(ifx) {
4754     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4755     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4756   }
4757 */
4758
4759   resolveIfx(&rFalseIfx,ifx);
4760   truelbl  = newiTempLabel(NULL);
4761   size = max(AOP_SIZE(left),AOP_SIZE(right));
4762
4763   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4764
4765 #define _swapp
4766
4767   /* if literal is on the right then swap with left */
4768   if ((AOP_TYPE(right) == AOP_LIT)) {
4769     operand *tmp = right ;
4770     unsigned long mask = (0x100 << (8*(size-1))) - 1;
4771     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4772 #ifdef _swapp
4773
4774     lit = (lit - 1) & mask;
4775     right = left;
4776     left = tmp;
4777     rFalseIfx.condition ^= 1;
4778 #endif
4779
4780   } else if ((AOP_TYPE(left) == AOP_LIT)) {
4781     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4782   }
4783
4784
4785   //if(IC_TRUE(ifx) == NULL)
4786   /* if left & right are bit variables */
4787   if (AOP_TYPE(left) == AOP_CRY &&
4788       AOP_TYPE(right) == AOP_CRY ) {
4789     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4790     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4791   } else {
4792     /* subtract right from left if at the
4793        end the carry flag is set then we know that
4794        left is greater than right */
4795
4796     symbol *lbl  = newiTempLabel(NULL);
4797
4798 #if 0
4799         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4800                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
4801 #endif
4802
4803 #ifndef _swapp
4804     if(AOP_TYPE(right) == AOP_LIT) {
4805
4806       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4807
4808       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4809
4810       /* special cases */
4811
4812       if(lit == 0) {
4813
4814         if(sign != 0) 
4815           genSkipCond(&rFalseIfx,left,size-1,7);
4816         else 
4817           /* no need to compare to 0...*/
4818           /* NOTE: this is a de-generate compare that most certainly 
4819            *       creates some dead code. */
4820           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4821
4822         if(ifx) ifx->generated = 1;
4823         return;
4824
4825       }
4826       size--;
4827
4828       if(size == 0) {
4829         //i = (lit >> (size*8)) & 0xff;
4830         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4831         
4832         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4833
4834         i = ((0-lit) & 0xff);
4835         if(sign) {
4836           if( i == 0x81) { 
4837             /* lit is 0x7f, all signed chars are less than
4838              * this except for 0x7f itself */
4839             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4840             genSkipz2(&rFalseIfx,0);
4841           } else {
4842             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4843             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4844             genSkipc(&rFalseIfx);
4845           }
4846
4847         } else {
4848           if(lit == 1) {
4849             genSkipz2(&rFalseIfx,1);
4850           } else {
4851             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4852             genSkipc(&rFalseIfx);
4853           }
4854         }
4855
4856         if(ifx) ifx->generated = 1;
4857         return;
4858       }
4859
4860       /* chars are out of the way. now do ints and longs */
4861
4862
4863       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4864         
4865       /* special cases */
4866
4867       if(sign) {
4868
4869         if(lit == 0) {
4870           genSkipCond(&rFalseIfx,left,size,7);
4871           if(ifx) ifx->generated = 1;
4872           return;
4873         }
4874
4875         if(lit <0x100) {
4876           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4877
4878           //rFalseIfx.condition ^= 1;
4879           //genSkipCond(&rFalseIfx,left,size,7);
4880           //rFalseIfx.condition ^= 1;
4881
4882           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4883           if(rFalseIfx.condition)
4884             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4885           else
4886             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4887
4888           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4889           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4890           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4891
4892           while(size > 1)
4893             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4894
4895           if(rFalseIfx.condition) {
4896             emitSKPZ;
4897             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4898
4899           } else {
4900             emitSKPNZ;
4901           }
4902
4903           genSkipc(&rFalseIfx);
4904           pic16_emitpLabel(truelbl->key);
4905           if(ifx) ifx->generated = 1;
4906           return;
4907
4908         }
4909
4910         if(size == 1) {
4911
4912           if( (lit & 0xff) == 0) {
4913             /* lower byte is zero */
4914             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4915             i = ((lit >> 8) & 0xff) ^0x80;
4916             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4917             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4918             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4919             genSkipc(&rFalseIfx);
4920
4921
4922             if(ifx) ifx->generated = 1;
4923             return;
4924
4925           }
4926         } else {
4927           /* Special cases for signed longs */
4928           if( (lit & 0xffffff) == 0) {
4929             /* lower byte is zero */
4930             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4931             i = ((lit >> 8*3) & 0xff) ^0x80;
4932             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4933             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4934             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4935             genSkipc(&rFalseIfx);
4936
4937
4938             if(ifx) ifx->generated = 1;
4939             return;
4940
4941           }
4942
4943         }
4944
4945
4946         if(lit & (0x80 << (size*8))) {
4947           /* lit is negative */
4948           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4949
4950           //genSkipCond(&rFalseIfx,left,size,7);
4951
4952           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4953
4954           if(rFalseIfx.condition)
4955             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4956           else
4957             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4958
4959
4960         } else {
4961           /* lit is positive */
4962           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4963           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4964           if(rFalseIfx.condition)
4965             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4966           else
4967             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4968
4969         }
4970
4971         /*
4972           This works, but is only good for ints.
4973           It also requires a "known zero" register.
4974           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4975           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4976           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4977           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4978           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4979           genSkipc(&rFalseIfx);
4980
4981           pic16_emitpLabel(truelbl->key);
4982           if(ifx) ifx->generated = 1;
4983           return;
4984         **/
4985           
4986         /* There are no more special cases, so perform a general compare */
4987   
4988         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4989         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4990
4991         while(size--) {
4992
4993           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4994           emitSKPNZ;
4995           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4996         }
4997         //rFalseIfx.condition ^= 1;
4998         genSkipc(&rFalseIfx);
4999
5000         pic16_emitpLabel(truelbl->key);
5001
5002         if(ifx) ifx->generated = 1;
5003         return;
5004
5005
5006       }
5007
5008
5009       /* sign is out of the way. So now do an unsigned compare */
5010       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5011
5012
5013       /* General case - compare to an unsigned literal on the right.*/
5014
5015       i = (lit >> (size*8)) & 0xff;
5016       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5017       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5018       while(size--) {
5019         i = (lit >> (size*8)) & 0xff;
5020
5021         if(i) {
5022           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5023           emitSKPNZ;
5024           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5025         } else {
5026           /* this byte of the lit is zero, 
5027            *if it's not the last then OR in the variable */
5028           if(size)
5029             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5030         }
5031       }
5032
5033
5034       pic16_emitpLabel(lbl->key);
5035 //      pic16_emitpLabel(truelbl->key);
5036       //if(emitFinalCheck)
5037       genSkipc(&rFalseIfx);
5038       if(sign)
5039         pic16_emitpLabel(truelbl->key);
5040
5041       if(ifx) ifx->generated = 1;
5042       return;
5043
5044
5045     }
5046 #endif  // _swapp
5047
5048     if(AOP_TYPE(left) == AOP_LIT) {
5049       //symbol *lbl = newiTempLabel(NULL);
5050
5051       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5052
5053
5054       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5055
5056       /* Special cases */
5057       if((lit == 0) && (sign == 0)){
5058
5059         size--;
5060         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5061         while(size) 
5062           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5063
5064         genSkipz2(&rFalseIfx,0);
5065         if(ifx) ifx->generated = 1;
5066         return;
5067       }
5068
5069       if(size==1) {
5070         /* Special cases */
5071         lit &= 0xff;
5072         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5073           /* degenerate compare can never be true */
5074           if(rFalseIfx.condition == 0)
5075             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5076
5077           if(ifx) ifx->generated = 1;
5078           return;
5079         }
5080
5081         if(sign) {
5082           /* signed comparisons to a literal byte */
5083
5084           int lp1 = (lit+1) & 0xff;
5085
5086           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5087           switch (lp1) {
5088           case 0:
5089             rFalseIfx.condition ^= 1;
5090             genSkipCond(&rFalseIfx,right,0,7);
5091             break;
5092           case 0x7f:
5093             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5094             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5095             genSkipz2(&rFalseIfx,1);
5096             break;
5097           default:
5098             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5099             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5100             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5101             rFalseIfx.condition ^= 1;
5102             genSkipc(&rFalseIfx);
5103             break;
5104           }
5105         } else {
5106           /* unsigned comparisons to a literal byte */
5107
5108           switch(lit & 0xff ) {
5109           case 0:
5110             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5111             genSkipz2(&rFalseIfx,0);
5112             break;
5113           case 0x7f:
5114             rFalseIfx.condition ^= 1;
5115             genSkipCond(&rFalseIfx,right,0,7);
5116             break;
5117
5118           default:
5119             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5120             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5121             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5122             rFalseIfx.condition ^= 1;
5123             if (AOP_TYPE(result) == AOP_CRY)
5124               genSkipc(&rFalseIfx);
5125             else {
5126               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5127               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5128             }         
5129             break;
5130           }
5131         }
5132
5133         if(ifx) ifx->generated = 1;
5134         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5135                 goto check_carry;
5136         return;
5137
5138       } else {
5139
5140         /* Size is greater than 1 */
5141
5142         if(sign) {
5143           int lp1 = lit+1;
5144
5145           size--;
5146
5147           if(lp1 == 0) {
5148             /* this means lit = 0xffffffff, or -1 */
5149
5150
5151             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5152             rFalseIfx.condition ^= 1;
5153             genSkipCond(&rFalseIfx,right,size,7);
5154             if(ifx) ifx->generated = 1;
5155             return;
5156           }
5157
5158           if(lit == 0) {
5159             int s = size;
5160
5161             if(rFalseIfx.condition) {
5162               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5163               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5164             }
5165
5166             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5167             while(size--)
5168               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5169
5170
5171             emitSKPZ;
5172             if(rFalseIfx.condition) {
5173               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5174               pic16_emitpLabel(truelbl->key);
5175             }else {
5176               rFalseIfx.condition ^= 1;
5177               genSkipCond(&rFalseIfx,right,s,7);
5178             }
5179
5180             if(ifx) ifx->generated = 1;
5181             return;
5182           }
5183
5184           if((size == 1) &&  (0 == (lp1&0xff))) {
5185             /* lower byte of signed word is zero */
5186             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5187             i = ((lp1 >> 8) & 0xff) ^0x80;
5188             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5189             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5190             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5191             rFalseIfx.condition ^= 1;
5192             genSkipc(&rFalseIfx);
5193
5194
5195             if(ifx) ifx->generated = 1;
5196             return;
5197           }
5198
5199           if(lit & (0x80 << (size*8))) {
5200             /* Lit is less than zero */
5201             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5202             //rFalseIfx.condition ^= 1;
5203             //genSkipCond(&rFalseIfx,left,size,7);
5204             //rFalseIfx.condition ^= 1;
5205             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5206             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5207
5208             if(rFalseIfx.condition)
5209               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5210             else
5211               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5212
5213
5214           } else {
5215             /* Lit is greater than or equal to zero */
5216             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5217             //rFalseIfx.condition ^= 1;
5218             //genSkipCond(&rFalseIfx,right,size,7);
5219             //rFalseIfx.condition ^= 1;
5220
5221             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5222             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5223
5224             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5225             if(rFalseIfx.condition)
5226               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5227             else
5228               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5229
5230           }
5231
5232
5233           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5234           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5235
5236           while(size--) {
5237
5238             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5239             emitSKPNZ;
5240             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5241           }
5242           rFalseIfx.condition ^= 1;
5243           //rFalseIfx.condition = 1;
5244           genSkipc(&rFalseIfx);
5245
5246           pic16_emitpLabel(truelbl->key);
5247
5248           if(ifx) ifx->generated = 1;
5249           return;
5250           // end of if (sign)
5251         } else {
5252
5253           /* compare word or long to an unsigned literal on the right.*/
5254
5255
5256           size--;
5257           if(lit < 0xff) {
5258             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5259             switch (lit) {
5260             case 0:
5261               break; /* handled above */
5262 /*
5263             case 0xff:
5264               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5265               while(size--)
5266                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5267               genSkipz2(&rFalseIfx,0);
5268               break;
5269 */
5270             default:
5271               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5272               while(--size)
5273                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5274
5275               emitSKPZ;
5276               if(rFalseIfx.condition)
5277                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5278               else
5279                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5280
5281
5282               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5283               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5284
5285               rFalseIfx.condition ^= 1;
5286               genSkipc(&rFalseIfx);
5287             }
5288
5289             pic16_emitpLabel(truelbl->key);
5290
5291             if(ifx) ifx->generated = 1;
5292             return;
5293           }
5294
5295
5296           lit++;
5297           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5298           i = (lit >> (size*8)) & 0xff;
5299
5300           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5301           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5302
5303           while(size--) {
5304             i = (lit >> (size*8)) & 0xff;
5305
5306             if(i) {
5307               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5308               emitSKPNZ;
5309               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5310             } else {
5311               /* this byte of the lit is zero, 
5312                * if it's not the last then OR in the variable */
5313               if(size)
5314                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5315             }
5316           }
5317
5318
5319           pic16_emitpLabel(lbl->key);
5320
5321           rFalseIfx.condition ^= 1;
5322
5323           genSkipc(&rFalseIfx);
5324         }
5325
5326         if(sign)
5327           pic16_emitpLabel(truelbl->key);
5328         if(ifx) ifx->generated = 1;
5329         return;
5330       }
5331     }
5332     /* Compare two variables */
5333
5334     DEBUGpic16_emitcode(";sign","%d",sign);
5335
5336     size--;
5337     if(sign) {
5338       /* Sigh. thus sucks... */
5339       if(size) {
5340         pCodeOp *pctemp;
5341         
5342         pctemp = pic16_popGetTempReg(1);
5343         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5344         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5345         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5346         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5347         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5348         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5349         pic16_popReleaseTempReg(pctemp, 1);
5350       } else {
5351         /* Signed char comparison */
5352         /* Special thanks to Nikolai Golovchenko for this snippet */
5353         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5354         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5355         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5356         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5357         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5358         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5359
5360         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5361         genSkipc(&rFalseIfx);
5362           
5363         if(ifx) ifx->generated = 1;
5364         return;
5365       }
5366
5367     } else {
5368
5369       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5370       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5371     }
5372
5373
5374     /* The rest of the bytes of a multi-byte compare */
5375     while (size) {
5376
5377       emitSKPZ;
5378       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5379       size--;
5380
5381       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5382       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5383
5384
5385     }
5386
5387     pic16_emitpLabel(lbl->key);
5388
5389     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5390     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5391         (AOP_TYPE(result) == AOP_REG)) {
5392       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5393       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5394     } else {
5395       genSkipc(&rFalseIfx);
5396     }         
5397     //genSkipc(&rFalseIfx);
5398     if(ifx) ifx->generated = 1;
5399
5400     return;
5401
5402   }
5403
5404 check_carry:
5405   if ((AOP_TYPE(result) != AOP_CRY) 
5406         && AOP_SIZE(result)) {
5407     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5408
5409     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5410
5411     pic16_outBitC(result);
5412   } else {
5413     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5414     /* if the result is used in the next
5415        ifx conditional branch then generate
5416        code a little differently */
5417     if (ifx )
5418       genIfxJump (ifx,"c");
5419     else
5420       pic16_outBitC(result);
5421     /* leave the result in acc */
5422   }
5423
5424 }
5425
5426 /*-----------------------------------------------------------------*/
5427 /* genCmpGt :- greater than comparison                             */
5428 /*-----------------------------------------------------------------*/
5429 static void genCmpGt (iCode *ic, iCode *ifx)
5430 {
5431     operand *left, *right, *result;
5432     sym_link *letype , *retype;
5433     int sign ;
5434
5435     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5436     left = IC_LEFT(ic);
5437     right= IC_RIGHT(ic);
5438     result = IC_RESULT(ic);
5439
5440     letype = getSpec(operandType(left));
5441     retype =getSpec(operandType(right));
5442     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5443     /* assign the amsops */
5444     pic16_aopOp (left,ic,FALSE);
5445     pic16_aopOp (right,ic,FALSE);
5446     pic16_aopOp (result,ic,TRUE);
5447
5448     genCmp(right, left, result, ifx, sign);
5449
5450     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5451     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5452     pic16_freeAsmop(result,NULL,ic,TRUE); 
5453 }
5454
5455 /*-----------------------------------------------------------------*/
5456 /* genCmpLt - less than comparisons                                */
5457 /*-----------------------------------------------------------------*/
5458 static void genCmpLt (iCode *ic, iCode *ifx)
5459 {
5460     operand *left, *right, *result;
5461     sym_link *letype , *retype;
5462     int sign ;
5463
5464     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5465     left = IC_LEFT(ic);
5466     right= IC_RIGHT(ic);
5467     result = IC_RESULT(ic);
5468
5469     letype = getSpec(operandType(left));
5470     retype =getSpec(operandType(right));
5471     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5472
5473     /* assign the amsops */
5474     pic16_aopOp (left,ic,FALSE);
5475     pic16_aopOp (right,ic,FALSE);
5476     pic16_aopOp (result,ic,TRUE);
5477
5478     genCmp(left, right, result, ifx, sign);
5479
5480     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5481     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5482     pic16_freeAsmop(result,NULL,ic,TRUE); 
5483 }
5484
5485 #if 0
5486 // not needed ATM
5487 // FIXME reenable literal optimisation when the pic16 port is stable
5488
5489 /*-----------------------------------------------------------------*/
5490 /* genc16bit2lit - compare a 16 bit value to a literal             */
5491 /*-----------------------------------------------------------------*/
5492 static void genc16bit2lit(operand *op, int lit, int offset)
5493 {
5494   int i;
5495
5496   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
5497   if( (lit&0xff) == 0) 
5498     i=1;
5499   else
5500     i=0;
5501
5502   switch( BYTEofLONG(lit,i)) { 
5503   case 0:
5504     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5505     break;
5506   case 1:
5507     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5508     break;
5509   case 0xff:
5510     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5511     break;
5512   default:
5513     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5514     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5515   }
5516
5517   i ^= 1;
5518
5519   switch( BYTEofLONG(lit,i)) { 
5520   case 0:
5521     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5522     break;
5523   case 1:
5524     emitSKPNZ;
5525     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5526     break;
5527   case 0xff:
5528     emitSKPNZ;
5529     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5530     break;
5531   default:
5532     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5533     emitSKPNZ;
5534     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5535
5536   }
5537
5538 }
5539 #endif
5540
5541 #if 0
5542 // not needed ATM
5543 /*-----------------------------------------------------------------*/
5544 /* gencjneshort - compare and jump if not equal                    */
5545 /*-----------------------------------------------------------------*/
5546 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5547 {
5548   int size = max(AOP_SIZE(left),AOP_SIZE(right));
5549   int offset = 0;
5550   int res_offset = 0;  /* the result may be a different size then left or right */
5551   int res_size = AOP_SIZE(result);
5552   resolvedIfx rIfx;
5553   symbol *lbl, *lbl_done;
5554
5555   unsigned long lit = 0L;
5556   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5557
5558   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5559   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5560   if(result)
5561     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
5562   resolveIfx(&rIfx,ifx);
5563   lbl =  newiTempLabel(NULL);
5564   lbl_done =  newiTempLabel(NULL);
5565
5566
5567   /* if the left side is a literal or 
5568      if the right is in a pointer register and left 
5569      is not */
5570   if ((AOP_TYPE(left) == AOP_LIT) || 
5571       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5572     operand *t = right;
5573     right = left;
5574     left = t;
5575   }
5576   if(AOP_TYPE(right) == AOP_LIT)
5577     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5578
5579   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5580     preserve_result = 1;
5581
5582   if(result && !preserve_result)
5583     {
5584       int i;
5585       for(i = 0; i < AOP_SIZE(result); i++)
5586         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5587     }
5588
5589
5590   /* if the right side is a literal then anything goes */
5591   if (AOP_TYPE(right) == AOP_LIT &&
5592       AOP_TYPE(left) != AOP_DIR ) {
5593     switch(size) {
5594     case 2:
5595       genc16bit2lit(left, lit, 0);
5596       emitSKPZ;
5597       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5598       break;
5599     default:
5600       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5601       while (size--) {
5602         if(lit & 0xff) {
5603           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5604           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5605         } else {
5606           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5607         }
5608
5609         emitSKPZ;
5610         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5611         offset++;
5612         if(res_offset < res_size-1)
5613           res_offset++;
5614         lit >>= 8;
5615       }
5616       break;
5617     }
5618   }
5619
5620   /* if the right side is in a register or in direct space or
5621      if the left is a pointer register & right is not */    
5622   else if (AOP_TYPE(right) == AOP_REG ||
5623            AOP_TYPE(right) == AOP_DIR || 
5624            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5625            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5626     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5627     int lbl_key = lbl->key;
5628
5629     if(result) {
5630       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5631       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5632     }else {
5633       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5634       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5635               __FUNCTION__,__LINE__);
5636       return;
5637     }
5638    
5639 /*     switch(size) { */
5640 /*     case 2: */
5641 /*       genc16bit2lit(left, lit, 0); */
5642 /*       emitSKPNZ; */
5643 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5644 /*       break; */
5645 /*     default: */
5646     while (size--) {
5647       int emit_skip=1;
5648       if((AOP_TYPE(left) == AOP_DIR) && 
5649          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5650
5651         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5652         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5653
5654       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5655             
5656         switch (lit & 0xff) {
5657         case 0:
5658           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5659           break;
5660         case 1:
5661           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5662           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5663           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5664           emit_skip=0;
5665           break;
5666         case 0xff:
5667           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5668           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5669           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5670           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5671           emit_skip=0;
5672           break;
5673         default:
5674           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5675           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5676         }
5677         lit >>= 8;
5678
5679       } else {
5680         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5681       }
5682       if(emit_skip) {
5683         if(AOP_TYPE(result) == AOP_CRY) {
5684           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5685           if(rIfx.condition)
5686             emitSKPNZ;
5687           else
5688             emitSKPZ;
5689           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5690         } else {
5691           /* fix me. probably need to check result size too */
5692           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5693           if(rIfx.condition)
5694             emitSKPZ;
5695           else
5696             emitSKPNZ;
5697           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5698           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5699         }
5700         if(ifx)
5701           ifx->generated=1;
5702       }
5703       emit_skip++;
5704       offset++;
5705       if(res_offset < res_size-1)
5706         res_offset++;
5707     }
5708 /*       break; */
5709 /*     } */
5710   } else if(AOP_TYPE(right) == AOP_REG &&
5711             AOP_TYPE(left) != AOP_DIR){
5712
5713     while(size--) {
5714       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5715       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5716       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5717       if(rIfx.condition)
5718         emitSKPNZ;
5719       else
5720         emitSKPZ;
5721       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5722       offset++;
5723       if(res_offset < res_size-1)
5724         res_offset++;
5725     }
5726       
5727   }else{
5728     /* right is a pointer reg need both a & b */
5729     while(size--) {
5730       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5731       if(strcmp(l,"b"))
5732         pic16_emitcode("mov","b,%s",l);
5733       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5734       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5735       offset++;
5736     }
5737   }
5738
5739   if(result && preserve_result)
5740     {
5741       int i;
5742       for(i = 0; i < AOP_SIZE(result); i++)
5743         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5744     }
5745
5746   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
5747
5748   if(result && preserve_result)
5749     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
5750
5751   if(!rIfx.condition)
5752     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5753
5754   pic16_emitpLabel(lbl->key);
5755
5756   if(result && preserve_result)
5757     {
5758       int i;
5759       for(i = 0; i < AOP_SIZE(result); i++)
5760         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5761
5762       pic16_emitpLabel(lbl_done->key);
5763    }
5764
5765   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5766
5767   if(ifx)
5768     ifx->generated = 1;
5769 }
5770 #endif
5771
5772 #if 0
5773 /*-----------------------------------------------------------------*/
5774 /* gencjne - compare and jump if not equal                         */
5775 /*-----------------------------------------------------------------*/
5776 static void gencjne(operand *left, operand *right, iCode *ifx)
5777 {
5778     symbol *tlbl  = newiTempLabel(NULL);
5779
5780     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5781     gencjneshort(left, right, lbl);
5782
5783     pic16_emitcode("mov","a,%s",one);
5784     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5785     pic16_emitcode("","%05d_DS_:",lbl->key+100);
5786     pic16_emitcode("clr","a");
5787     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5788
5789     pic16_emitpLabel(lbl->key);
5790     pic16_emitpLabel(tlbl->key);
5791
5792 }
5793 #endif
5794
5795
5796 /*-----------------------------------------------------------------*/
5797 /* is_LitOp - check if operand has to be treated as literal        */
5798 /*-----------------------------------------------------------------*/
5799 static bool is_LitOp(operand *op)
5800 {
5801   return (AOP_TYPE(op) == AOP_LIT)
5802       || ( (AOP_TYPE(op) == AOP_PCODE)
5803           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
5804               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ));  
5805 }
5806
5807 /*-----------------------------------------------------------------*/
5808 /* is_LitAOp - check if operand has to be treated as literal        */
5809 /*-----------------------------------------------------------------*/
5810 static bool is_LitAOp(asmop *aop)
5811 {
5812   return (aop->type == AOP_LIT)
5813       || ( (aop->type == AOP_PCODE)
5814           && ( (aop->aopu.pcop->type == PO_LITERAL)
5815               || (aop->aopu.pcop->type == PO_IMMEDIATE) ));  
5816 }
5817
5818
5819
5820 /*-----------------------------------------------------------------*/
5821 /* genCmpEq - generates code for equal to                          */
5822 /*-----------------------------------------------------------------*/
5823 static void genCmpEq (iCode *ic, iCode *ifx)
5824 {
5825   operand *left, *right, *result;
5826   symbol *falselbl = newiTempLabel(NULL);
5827   symbol *donelbl = newiTempLabel(NULL);
5828
5829   int preserve_result = 0;
5830   int generate_result = 0;
5831   int i=0;
5832
5833   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5834   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5835   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5836  
5837   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5838   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5839
5840   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
5841     {
5842       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5843       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
5844       goto release;
5845     }
5846
5847   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
5848     {
5849       operand *tmp = right ;
5850       right = left;
5851       left = tmp;
5852     }
5853
5854   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5855     preserve_result = 1;
5856
5857   if(result && AOP_SIZE(result))
5858     generate_result = 1;
5859
5860   if(generate_result && !preserve_result)
5861     {
5862       for(i = 0; i < AOP_SIZE(result); i++)
5863         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5864     }
5865
5866   for(i=0; i < AOP_SIZE(left); i++)
5867     {
5868       if(AOP_TYPE(left) != AOP_ACC)
5869         {
5870           if(is_LitOp(left))
5871             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
5872           else
5873             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
5874         }
5875       if(is_LitOp(right))
5876         pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
5877       else
5878         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
5879
5880       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
5881     }
5882
5883   // result == true
5884
5885   if(generate_result && preserve_result)
5886     {
5887       for(i = 0; i < AOP_SIZE(result); i++)
5888         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5889     }
5890
5891   if(generate_result)
5892     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
5893
5894   if(generate_result && preserve_result)
5895     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5896
5897   if(ifx && IC_TRUE(ifx))
5898     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5899
5900   if(ifx && IC_FALSE(ifx))
5901     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5902
5903   pic16_emitpLabel(falselbl->key);
5904
5905   // result == false
5906
5907   if(ifx && IC_FALSE(ifx))
5908     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5909
5910   if(generate_result && preserve_result)
5911     {
5912       for(i = 0; i < AOP_SIZE(result); i++)
5913         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5914     }
5915
5916   pic16_emitpLabel(donelbl->key);
5917
5918   if(ifx)
5919     ifx->generated = 1;
5920
5921 release:
5922   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5923   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5924   pic16_freeAsmop(result,NULL,ic,TRUE);
5925
5926 }
5927
5928
5929 #if 0
5930 // old version kept for reference
5931
5932 /*-----------------------------------------------------------------*/
5933 /* genCmpEq - generates code for equal to                          */
5934 /*-----------------------------------------------------------------*/
5935 static void genCmpEq (iCode *ic, iCode *ifx)
5936 {
5937     operand *left, *right, *result;
5938     unsigned long lit = 0L;
5939     int size,offset=0;
5940     symbol *falselbl  = newiTempLabel(NULL);
5941
5942
5943     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5944
5945     if(ifx)
5946       DEBUGpic16_emitcode ("; ifx is non-null","");
5947     else
5948       DEBUGpic16_emitcode ("; ifx is null","");
5949
5950     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5951     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5952     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5953
5954     size = max(AOP_SIZE(left),AOP_SIZE(right));
5955
5956     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5957
5958     /* if literal, literal on the right or 
5959     if the right is in a pointer register and left 
5960     is not */
5961     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
5962         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5963       operand *tmp = right ;
5964       right = left;
5965       left = tmp;
5966     }
5967
5968
5969     if(ifx && !AOP_SIZE(result)){
5970         symbol *tlbl;
5971         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
5972         /* if they are both bit variables */
5973         if (AOP_TYPE(left) == AOP_CRY &&
5974             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5975                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
5976             if(AOP_TYPE(right) == AOP_LIT){
5977                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5978                 if(lit == 0L){
5979                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5980                     pic16_emitcode("cpl","c");
5981                 } else if(lit == 1L) {
5982                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5983                 } else {
5984                     pic16_emitcode("clr","c");
5985                 }
5986                 /* AOP_TYPE(right) == AOP_CRY */
5987             } else {
5988                 symbol *lbl = newiTempLabel(NULL);
5989                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5990                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5991                 pic16_emitcode("cpl","c");
5992                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5993             }
5994             /* if true label then we jump if condition
5995             supplied is true */
5996             tlbl = newiTempLabel(NULL);
5997             if ( IC_TRUE(ifx) ) {
5998                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5999                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6000             } else {
6001                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6002                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6003             }
6004             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6005
6006                 {
6007                 /* left and right are both bit variables, result is carry */
6008                         resolvedIfx rIfx;
6009               
6010                         resolveIfx(&rIfx,ifx);
6011
6012                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6013                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6014                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6015                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6016                         genSkipz2(&rIfx,0);
6017                 }
6018         } else {
6019
6020                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6021
6022                         /* They're not both bit variables. Is the right a literal? */
6023                         if(AOP_TYPE(right) == AOP_LIT) {
6024                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6025             
6026                         switch(size) {
6027
6028                                 case 1:
6029                                         switch(lit & 0xff) {
6030                                                 case 1:
6031                                                                 if ( IC_TRUE(ifx) ) {
6032                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6033                                                                         emitSKPNZ;
6034                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6035                                                                 } else {
6036                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6037                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6038                                                                 }
6039                                                                 break;
6040                                                 case 0xff:
6041                                                                 if ( IC_TRUE(ifx) ) {
6042                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6043                                                                         emitSKPNZ;
6044                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6045                                                                 } else {
6046                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6047                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6048                                                                 }
6049                                                                 break;
6050                                                 default:
6051                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6052                                                                 if(lit)
6053                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6054                                                                 genSkip(ifx,'z');
6055                                         } // switch lit
6056
6057
6058                                         /* end of size == 1 */
6059                                         break;
6060               
6061                                 case 2:
6062                                         genc16bit2lit(left,lit,offset);
6063                                         genSkip(ifx,'z');
6064                                         break;
6065                                         /* end of size == 2 */
6066
6067                                 default:
6068                                         /* size is 4 */
6069                                         if(lit==0) {
6070                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6071                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6072                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6073                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6074                                                 genSkip(ifx,'z');
6075                                         } else {
6076                                                 /* search for patterns that can be optimized */
6077
6078                                                 genc16bit2lit(left,lit,0);
6079                                                 lit >>= 16;
6080                                                 if(lit) {
6081                                                                 if(IC_TRUE(ifx))
6082                                                                 emitSKPZ; // if hi word unequal
6083                                                                 else
6084                                                                 emitSKPNZ; // if hi word equal
6085                                                                 // fail early
6086                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6087                                                         genc16bit2lit(left,lit,2);
6088                                                         genSkip(ifx,'z');
6089                                                 } else {
6090                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6091                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6092                                                         genSkip(ifx,'z');
6093                                                 }
6094                                         }
6095                                                 pic16_emitpLabel(falselbl->key);
6096                                                 break;
6097
6098                         } // switch size
6099           
6100                         ifx->generated = 1;
6101                         goto release ;
6102             
6103
6104           } else if(AOP_TYPE(right) == AOP_CRY ) {
6105             /* we know the left is not a bit, but that the right is */
6106             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6107             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6108                       pic16_popGet(AOP(right),offset));
6109             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6110
6111             /* if the two are equal, then W will be 0 and the Z bit is set
6112              * we could test Z now, or go ahead and check the high order bytes if
6113              * the variable we're comparing is larger than a byte. */
6114
6115             while(--size)
6116               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6117
6118             if ( IC_TRUE(ifx) ) {
6119               emitSKPNZ;
6120               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6121               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6122             } else {
6123               emitSKPZ;
6124               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6125               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6126             }
6127
6128           } else {
6129             /* They're both variables that are larger than bits */
6130             int s = size;
6131
6132             tlbl = newiTempLabel(NULL);
6133
6134             while(size--) {
6135               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6136               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6137
6138               if ( IC_TRUE(ifx) ) {
6139                 if(size) {
6140                   emitSKPZ;
6141                 
6142                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6143
6144                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6145                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6146                 } else {
6147                   emitSKPNZ;
6148
6149                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6150
6151
6152                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6153                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6154                 }
6155               } else {
6156                 emitSKPZ;
6157
6158                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6159
6160                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6161                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6162               }
6163               offset++;
6164             }
6165             if(s>1 && IC_TRUE(ifx)) {
6166               pic16_emitpLabel(tlbl->key);
6167               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
6168             }
6169           }
6170         }
6171         /* mark the icode as generated */
6172         ifx->generated = 1;
6173         goto release ;
6174     }
6175
6176     /* if they are both bit variables */
6177     if (AOP_TYPE(left) == AOP_CRY &&
6178         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6179         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
6180         if(AOP_TYPE(right) == AOP_LIT){
6181             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6182             if(lit == 0L){
6183                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6184                 pic16_emitcode("cpl","c");
6185             } else if(lit == 1L) {
6186                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6187             } else {
6188                 pic16_emitcode("clr","c");
6189             }
6190             /* AOP_TYPE(right) == AOP_CRY */
6191         } else {
6192             symbol *lbl = newiTempLabel(NULL);
6193             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6194             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6195             pic16_emitcode("cpl","c");
6196             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6197         }
6198         /* c = 1 if egal */
6199         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
6200             pic16_outBitC(result);
6201             goto release ;
6202         }
6203         if (ifx) {
6204             genIfxJump (ifx,"c");
6205             goto release ;
6206         }
6207         /* if the result is used in an arithmetic operation
6208         then put the result in place */
6209         pic16_outBitC(result);
6210     } else {
6211       
6212       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
6213       gencjne(left,right,result,ifx);
6214 /*
6215       if(ifx) 
6216         gencjne(left,right,newiTempLabel(NULL));
6217       else {
6218         if(IC_TRUE(ifx)->key)
6219           gencjne(left,right,IC_TRUE(ifx)->key);
6220         else
6221           gencjne(left,right,IC_FALSE(ifx)->key);
6222         ifx->generated = 1;
6223         goto release ;
6224       }
6225       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
6226         pic16_aopPut(AOP(result),"a",0);
6227         goto release ;
6228       }
6229
6230       if (ifx) {
6231         genIfxJump (ifx,"a");
6232         goto release ;
6233       }
6234 */
6235       /* if the result is used in an arithmetic operation
6236          then put the result in place */
6237 /*
6238       if (AOP_TYPE(result) != AOP_CRY) 
6239         pic16_outAcc(result);
6240 */
6241       /* leave the result in acc */
6242     }
6243
6244 release:
6245     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6246     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6247     pic16_freeAsmop(result,NULL,ic,TRUE);
6248 }
6249 #endif
6250
6251 /*-----------------------------------------------------------------*/
6252 /* ifxForOp - returns the icode containing the ifx for operand     */
6253 /*-----------------------------------------------------------------*/
6254 static iCode *ifxForOp ( operand *op, iCode *ic )
6255 {
6256     /* if true symbol then needs to be assigned */
6257     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6258     if (IS_TRUE_SYMOP(op))
6259         return NULL ;
6260
6261     /* if this has register type condition and
6262     the next instruction is ifx with the same operand
6263     and live to of the operand is upto the ifx only then */
6264     if (ic->next
6265         && ic->next->op == IFX
6266         && IC_COND(ic->next)->key == op->key
6267         && OP_SYMBOL(op)->liveTo <= ic->next->seq
6268         ) {
6269                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
6270           return ic->next;
6271     }
6272
6273     if (ic->next &&
6274         ic->next->op == IFX &&
6275         IC_COND(ic->next)->key == op->key) {
6276       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6277       return ic->next;
6278     }
6279
6280     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
6281     if (ic->next &&
6282         ic->next->op == IFX)
6283       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
6284
6285     if (ic->next &&
6286         ic->next->op == IFX &&
6287         IC_COND(ic->next)->key == op->key) {
6288       DEBUGpic16_emitcode ("; "," key is okay");
6289       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
6290                            OP_SYMBOL(op)->liveTo,
6291                            ic->next->seq);
6292     }
6293
6294 #if 0
6295     /* the code below is completely untested
6296      * it just allows ulong2fs.c compile -- VR */
6297          
6298     ic = ic->next;
6299     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
6300                                         __FILE__, __FUNCTION__, __LINE__);
6301         
6302     /* if this has register type condition and
6303     the next instruction is ifx with the same operand
6304     and live to of the operand is upto the ifx only then */
6305     if (ic->next &&
6306         ic->next->op == IFX &&
6307         IC_COND(ic->next)->key == op->key &&
6308         OP_SYMBOL(op)->liveTo <= ic->next->seq )
6309         return ic->next;
6310
6311     if (ic->next &&
6312         ic->next->op == IFX &&
6313         IC_COND(ic->next)->key == op->key) {
6314       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6315       return ic->next;
6316     }
6317
6318     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
6319                                         __FILE__, __FUNCTION__, __LINE__);
6320
6321 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
6322 #endif
6323
6324     return NULL;
6325 }
6326 /*-----------------------------------------------------------------*/
6327 /* genAndOp - for && operation                                     */
6328 /*-----------------------------------------------------------------*/
6329 static void genAndOp (iCode *ic)
6330 {
6331     operand *left,*right, *result;
6332 /*     symbol *tlbl; */
6333
6334     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6335     /* note here that && operations that are in an
6336     if statement are taken away by backPatchLabels
6337     only those used in arthmetic operations remain */
6338     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6339     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6340     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6341
6342     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6343
6344     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6345     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
6346     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
6347
6348     /* if both are bit variables */
6349 /*     if (AOP_TYPE(left) == AOP_CRY && */
6350 /*         AOP_TYPE(right) == AOP_CRY ) { */
6351 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
6352 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
6353 /*         pic16_outBitC(result); */
6354 /*     } else { */
6355 /*         tlbl = newiTempLabel(NULL); */
6356 /*         pic16_toBoolean(left);     */
6357 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
6358 /*         pic16_toBoolean(right); */
6359 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
6360 /*         pic16_outBitAcc(result); */
6361 /*     } */
6362
6363     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6364     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6365     pic16_freeAsmop(result,NULL,ic,TRUE);
6366 }
6367
6368
6369 /*-----------------------------------------------------------------*/
6370 /* genOrOp - for || operation                                      */
6371 /*-----------------------------------------------------------------*/
6372 /*
6373   tsd pic port -
6374   modified this code, but it doesn't appear to ever get called
6375 */
6376
6377 static void genOrOp (iCode *ic)
6378 {
6379     operand *left,*right, *result;
6380     symbol *tlbl;
6381
6382     /* note here that || operations that are in an
6383     if statement are taken away by backPatchLabels
6384     only those used in arthmetic operations remain */
6385     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6386     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6387     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6388     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6389
6390     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6391
6392     /* if both are bit variables */
6393     if (AOP_TYPE(left) == AOP_CRY &&
6394         AOP_TYPE(right) == AOP_CRY ) {
6395       pic16_emitcode("clrc","");
6396       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6397                AOP(left)->aopu.aop_dir,
6398                AOP(left)->aopu.aop_dir);
6399       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6400                AOP(right)->aopu.aop_dir,
6401                AOP(right)->aopu.aop_dir);
6402       pic16_emitcode("setc","");
6403
6404     } else {
6405         tlbl = newiTempLabel(NULL);
6406         pic16_toBoolean(left);
6407         emitSKPZ;
6408         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
6409         pic16_toBoolean(right);
6410         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6411
6412         pic16_outBitAcc(result);
6413     }
6414
6415     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6416     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6417     pic16_freeAsmop(result,NULL,ic,TRUE);            
6418 }
6419
6420 /*-----------------------------------------------------------------*/
6421 /* isLiteralBit - test if lit == 2^n                               */
6422 /*-----------------------------------------------------------------*/
6423 static int isLiteralBit(unsigned long lit)
6424 {
6425     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
6426     0x100L,0x200L,0x400L,0x800L,
6427     0x1000L,0x2000L,0x4000L,0x8000L,
6428     0x10000L,0x20000L,0x40000L,0x80000L,
6429     0x100000L,0x200000L,0x400000L,0x800000L,
6430     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
6431     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
6432     int idx;
6433     
6434     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6435     for(idx = 0; idx < 32; idx++)
6436         if(lit == pw[idx])
6437             return idx+1;
6438     return 0;
6439 }
6440
6441 /*-----------------------------------------------------------------*/
6442 /* continueIfTrue -                                                */
6443 /*-----------------------------------------------------------------*/
6444 static void continueIfTrue (iCode *ic)
6445 {
6446     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6447     if(IC_TRUE(ic))
6448         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6449     ic->generated = 1;
6450 }
6451
6452 /*-----------------------------------------------------------------*/
6453 /* jmpIfTrue -                                                     */
6454 /*-----------------------------------------------------------------*/
6455 static void jumpIfTrue (iCode *ic)
6456 {
6457     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6458     if(!IC_TRUE(ic))
6459         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6460     ic->generated = 1;
6461 }
6462
6463 /*-----------------------------------------------------------------*/
6464 /* jmpTrueOrFalse -                                                */
6465 /*-----------------------------------------------------------------*/
6466 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
6467 {
6468     // ugly but optimized by peephole
6469     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6470     if(IC_TRUE(ic)){
6471         symbol *nlbl = newiTempLabel(NULL);
6472         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
6473         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6474         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6475         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
6476     }
6477     else{
6478         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6479         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6480     }
6481     ic->generated = 1;
6482 }
6483
6484 /*-----------------------------------------------------------------*/
6485 /* genAnd  - code for and                                          */
6486 /*-----------------------------------------------------------------*/
6487 static void genAnd (iCode *ic, iCode *ifx)
6488 {
6489   operand *left, *right, *result;
6490   int size, offset=0;  
6491   unsigned long lit = 0L;
6492   int bytelit = 0;
6493   resolvedIfx rIfx;
6494
6495
6496   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6497   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6498   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6499   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6500
6501   resolveIfx(&rIfx,ifx);
6502
6503   /* if left is a literal & right is not then exchange them */
6504   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6505       AOP_NEEDSACC(left)) {
6506     operand *tmp = right ;
6507     right = left;
6508     left = tmp;
6509   }
6510
6511   /* if result = right then exchange them */
6512   if(pic16_sameRegs(AOP(result),AOP(right))){
6513     operand *tmp = right ;
6514     right = left;
6515     left = tmp;
6516   }
6517
6518   /* if right is bit then exchange them */
6519   if (AOP_TYPE(right) == AOP_CRY &&
6520       AOP_TYPE(left) != AOP_CRY){
6521     operand *tmp = right ;
6522     right = left;
6523     left = tmp;
6524   }
6525   if(AOP_TYPE(right) == AOP_LIT)
6526     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6527
6528   size = AOP_SIZE(result);
6529
6530   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6531
6532   // if(bit & yy)
6533   // result = bit & yy;
6534   if (AOP_TYPE(left) == AOP_CRY){
6535     // c = bit & literal;
6536     if(AOP_TYPE(right) == AOP_LIT){
6537       if(lit & 1) {
6538         if(size && pic16_sameRegs(AOP(result),AOP(left)))
6539           // no change
6540           goto release;
6541         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6542       } else {
6543         // bit(result) = 0;
6544         if(size && (AOP_TYPE(result) == AOP_CRY)){
6545           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
6546           goto release;
6547         }
6548         if((AOP_TYPE(result) == AOP_CRY) && ifx){
6549           jumpIfTrue(ifx);
6550           goto release;
6551         }
6552         pic16_emitcode("clr","c");
6553       }
6554     } else {
6555       if (AOP_TYPE(right) == AOP_CRY){
6556         // c = bit & bit;
6557         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6558         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6559       } else {
6560         // c = bit & val;
6561         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
6562         // c = lsb
6563         pic16_emitcode("rrc","a");
6564         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6565       }
6566     }
6567     // bit = c
6568     // val = c
6569     if(size)
6570       pic16_outBitC(result);
6571     // if(bit & ...)
6572     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6573       genIfxJump(ifx, "c");           
6574     goto release ;
6575   }
6576
6577   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6578   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6579   if((AOP_TYPE(right) == AOP_LIT) &&
6580      (AOP_TYPE(result) == AOP_CRY) &&
6581      (AOP_TYPE(left) != AOP_CRY)){
6582     int posbit = isLiteralBit(lit);
6583     /* left &  2^n */
6584     if(posbit){
6585       posbit--;
6586       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6587       // bit = left & 2^n
6588       if(size)
6589         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6590       // if(left &  2^n)
6591       else{
6592         if(ifx){
6593 /*
6594           if(IC_TRUE(ifx)) {
6595             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6596             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
6597           } else {
6598             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6599             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
6600           }
6601 */
6602         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
6603         size = AOP_SIZE(left);
6604
6605         {
6606           int bp = posbit, ofs=0;
6607           
6608             while(bp > 7) {
6609               bp -= 8;
6610               ofs++;
6611             }
6612         
6613           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6614                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
6615
6616         }
6617 /*
6618           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6619                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6620 */
6621           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6622           
6623           ifx->generated = 1;
6624         }
6625         goto release;
6626       }
6627     } else {
6628       symbol *tlbl = newiTempLabel(NULL);
6629       int sizel = AOP_SIZE(left);
6630
6631       if(size)
6632         emitSETC;
6633
6634       while(sizel--) {
6635         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
6636
6637           /* patch provided by Aaron Colwell */
6638           if((posbit = isLiteralBit(bytelit)) != 0) {
6639               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
6640                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
6641                                                 (posbit-1),0, PO_GPR_REGISTER));
6642
6643               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
6644 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
6645           } else {
6646               if (bytelit == 0xff) {
6647                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
6648                    * a peephole could optimize it out -- VR */
6649                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
6650               } else {
6651                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
6652                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
6653               }
6654
6655               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
6656                             pic16_popGetLabel(tlbl->key));
6657           }
6658         
6659 #if 0
6660           /* old code, left here for reference -- VR 09/2004 */
6661           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6662           // byte ==  2^n ?
6663           if((posbit = isLiteralBit(bytelit)) != 0)
6664             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6665           else{
6666             if(bytelit != 0x0FFL)
6667               pic16_emitcode("anl","a,%s",
6668                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6669             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6670           }
6671 #endif
6672         }
6673         offset++;
6674       }
6675       // bit = left & literal
6676       if(size) {
6677         emitCLRC;
6678         pic16_emitpLabel(tlbl->key);
6679       }
6680       // if(left & literal)
6681       else {
6682         if(ifx) {
6683           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
6684           pic16_emitpLabel(tlbl->key);
6685           ifx->generated = 1;
6686         }
6687         goto release;
6688       }
6689     }
6690
6691     pic16_outBitC(result);
6692     goto release ;
6693   }
6694
6695   /* if left is same as result */
6696   if(pic16_sameRegs(AOP(result),AOP(left))){
6697     int know_W = -1;
6698     for(;size--; offset++,lit>>=8) {
6699       if(AOP_TYPE(right) == AOP_LIT){
6700         switch(lit & 0xff) {
6701         case 0x00:
6702           /*  and'ing with 0 has clears the result */
6703 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6704           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6705           break;
6706         case 0xff:
6707           /* and'ing with 0xff is a nop when the result and left are the same */
6708           break;
6709
6710         default:
6711           {
6712             int p = my_powof2( (~lit) & 0xff );
6713             if(p>=0) {
6714               /* only one bit is set in the literal, so use a bcf instruction */
6715 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6716               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
6717
6718             } else {
6719               pic16_emitcode("movlw","0x%x", (lit & 0xff));
6720               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6721               if(know_W != (lit&0xff))
6722                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6723               know_W = lit &0xff;
6724               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6725             }
6726           }    
6727         }
6728       } else {
6729         if (AOP_TYPE(left) == AOP_ACC) {
6730           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6731         } else {                    
6732           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6733           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6734
6735         }
6736       }
6737     }
6738
6739   } else {
6740     // left & result in different registers
6741     if(AOP_TYPE(result) == AOP_CRY){
6742       // result = bit
6743       // if(size), result in bit
6744       // if(!size && ifx), conditional oper: if(left & right)
6745       symbol *tlbl = newiTempLabel(NULL);
6746       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6747       if(size)
6748         pic16_emitcode("setb","c");
6749       while(sizer--){
6750         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6751         pic16_emitcode("anl","a,%s",
6752                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6753         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6754         offset++;
6755       }
6756       if(size){
6757         CLRC;
6758         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6759         pic16_outBitC(result);
6760       } else if(ifx)
6761         jmpTrueOrFalse(ifx, tlbl);
6762     } else {
6763       for(;(size--);offset++) {
6764         // normal case
6765         // result = left & right
6766         if(AOP_TYPE(right) == AOP_LIT){
6767           int t = (lit >> (offset*8)) & 0x0FFL;
6768           switch(t) { 
6769           case 0x00:
6770             pic16_emitcode("clrf","%s",
6771                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6772             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6773             break;
6774           case 0xff:
6775             pic16_emitcode("movf","%s,w",
6776                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6777             pic16_emitcode("movwf","%s",
6778                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6779             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6780             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6781             break;
6782           default:
6783             pic16_emitcode("movlw","0x%x",t);
6784             pic16_emitcode("andwf","%s,w",
6785                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6786             pic16_emitcode("movwf","%s",
6787                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6788               
6789             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6790             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6791             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6792           }
6793           continue;
6794         }
6795
6796         if (AOP_TYPE(left) == AOP_ACC) {
6797           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6798           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6799         } else {
6800           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6801           pic16_emitcode("andwf","%s,w",
6802                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6803           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6804           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6805         }
6806         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6807         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6808       }
6809     }
6810   }
6811
6812   release :
6813     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6814   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6815   pic16_freeAsmop(result,NULL,ic,TRUE);     
6816 }
6817
6818 /*-----------------------------------------------------------------*/
6819 /* genOr  - code for or                                            */
6820 /*-----------------------------------------------------------------*/
6821 static void genOr (iCode *ic, iCode *ifx)
6822 {
6823     operand *left, *right, *result;
6824     int size, offset=0;
6825     unsigned long lit = 0L;
6826
6827     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6828
6829     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6830     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6831     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6832
6833     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6834
6835     /* if left is a literal & right is not then exchange them */
6836     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6837         AOP_NEEDSACC(left)) {
6838         operand *tmp = right ;
6839         right = left;
6840         left = tmp;
6841     }
6842
6843     /* if result = right then exchange them */
6844     if(pic16_sameRegs(AOP(result),AOP(right))){
6845         operand *tmp = right ;
6846         right = left;
6847         left = tmp;
6848     }
6849
6850     /* if right is bit then exchange them */
6851     if (AOP_TYPE(right) == AOP_CRY &&
6852         AOP_TYPE(left) != AOP_CRY){
6853         operand *tmp = right ;
6854         right = left;
6855         left = tmp;
6856     }
6857
6858     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6859
6860     if(AOP_TYPE(right) == AOP_LIT)
6861         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6862
6863     size = AOP_SIZE(result);
6864
6865     // if(bit | yy)
6866     // xx = bit | yy;
6867     if (AOP_TYPE(left) == AOP_CRY){
6868         if(AOP_TYPE(right) == AOP_LIT){
6869             // c = bit & literal;
6870             if(lit){
6871                 // lit != 0 => result = 1
6872                 if(AOP_TYPE(result) == AOP_CRY){
6873                   if(size)
6874                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6875                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6876                   //     AOP(result)->aopu.aop_dir,
6877                   //     AOP(result)->aopu.aop_dir);
6878                     else if(ifx)
6879                         continueIfTrue(ifx);
6880                     goto release;
6881                 }
6882             } else {
6883                 // lit == 0 => result = left
6884                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6885                     goto release;
6886                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6887             }
6888         } else {
6889             if (AOP_TYPE(right) == AOP_CRY){
6890               if(pic16_sameRegs(AOP(result),AOP(left))){
6891                 // c = bit | bit;
6892                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6893                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6894                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6895
6896                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6897                          AOP(result)->aopu.aop_dir,
6898                          AOP(result)->aopu.aop_dir);
6899                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6900                          AOP(right)->aopu.aop_dir,
6901                          AOP(right)->aopu.aop_dir);
6902                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6903                          AOP(result)->aopu.aop_dir,
6904                          AOP(result)->aopu.aop_dir);
6905               } else {
6906                 if( AOP_TYPE(result) == AOP_ACC) {
6907                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6908                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6909                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6910                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6911
6912                 } else {
6913
6914                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6915                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6916                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6917                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6918
6919                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6920                                  AOP(result)->aopu.aop_dir,
6921                                  AOP(result)->aopu.aop_dir);
6922                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6923                                  AOP(right)->aopu.aop_dir,
6924                                  AOP(right)->aopu.aop_dir);
6925                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6926                                  AOP(left)->aopu.aop_dir,
6927                                  AOP(left)->aopu.aop_dir);
6928                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6929                                  AOP(result)->aopu.aop_dir,
6930                                  AOP(result)->aopu.aop_dir);
6931                 }
6932               }
6933             } else {
6934                 // c = bit | val;
6935                 symbol *tlbl = newiTempLabel(NULL);
6936                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6937
6938
6939                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6940                 if( AOP_TYPE(right) == AOP_ACC) {
6941                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6942                   emitSKPNZ;
6943                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6944                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6945                 }
6946
6947
6948
6949                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6950                     pic16_emitcode(";XXX setb","c");
6951                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6952                          AOP(left)->aopu.aop_dir,tlbl->key+100);
6953                 pic16_toBoolean(right);
6954                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6955                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6956                     jmpTrueOrFalse(ifx, tlbl);
6957                     goto release;
6958                 } else {
6959                     CLRC;
6960                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6961                 }
6962             }
6963         }
6964         // bit = c
6965         // val = c
6966         if(size)
6967             pic16_outBitC(result);
6968         // if(bit | ...)
6969         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6970             genIfxJump(ifx, "c");           
6971         goto release ;
6972     }
6973
6974     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6975     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6976     if((AOP_TYPE(right) == AOP_LIT) &&
6977        (AOP_TYPE(result) == AOP_CRY) &&
6978        (AOP_TYPE(left) != AOP_CRY)){
6979         if(lit){
6980           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6981             // result = 1
6982             if(size)
6983                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6984             else 
6985                 continueIfTrue(ifx);
6986             goto release;
6987         } else {
6988           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6989             // lit = 0, result = boolean(left)
6990             if(size)
6991                 pic16_emitcode(";XXX setb","c");
6992             pic16_toBoolean(right);
6993             if(size){
6994                 symbol *tlbl = newiTempLabel(NULL);
6995                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6996                 CLRC;
6997                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6998             } else {
6999                 genIfxJump (ifx,"a");
7000                 goto release;
7001             }
7002         }
7003         pic16_outBitC(result);
7004         goto release ;
7005     }
7006
7007     /* if left is same as result */
7008     if(pic16_sameRegs(AOP(result),AOP(left))){
7009       int know_W = -1;
7010       for(;size--; offset++,lit>>=8) {
7011         if(AOP_TYPE(right) == AOP_LIT){
7012           if((lit & 0xff) == 0)
7013             /*  or'ing with 0 has no effect */
7014             continue;
7015           else {
7016             int p = my_powof2(lit & 0xff);
7017             if(p>=0) {
7018               /* only one bit is set in the literal, so use a bsf instruction */
7019               pic16_emitpcode(POC_BSF,
7020                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7021             } else {
7022               if(know_W != (lit & 0xff))
7023                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7024               know_W = lit & 0xff;
7025               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7026             }
7027                     
7028           }
7029         } else {
7030           if (AOP_TYPE(left) == AOP_ACC) {
7031             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7032             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7033           } else {                  
7034             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7035             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7036
7037             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7038             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7039
7040           }
7041         }
7042       }
7043     } else {
7044         // left & result in different registers
7045         if(AOP_TYPE(result) == AOP_CRY){
7046             // result = bit
7047             // if(size), result in bit
7048             // if(!size && ifx), conditional oper: if(left | right)
7049             symbol *tlbl = newiTempLabel(NULL);
7050             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7051             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7052
7053
7054             if(size)
7055                 pic16_emitcode(";XXX setb","c");
7056             while(sizer--){
7057                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7058                 pic16_emitcode(";XXX orl","a,%s",
7059                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7060                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7061                 offset++;
7062             }
7063             if(size){
7064                 CLRC;
7065                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7066                 pic16_outBitC(result);
7067             } else if(ifx)
7068                 jmpTrueOrFalse(ifx, tlbl);
7069         } else for(;(size--);offset++){
7070           // normal case
7071           // result = left & right
7072           if(AOP_TYPE(right) == AOP_LIT){
7073             int t = (lit >> (offset*8)) & 0x0FFL;
7074             switch(t) { 
7075             case 0x00:
7076               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7077               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7078
7079               pic16_emitcode("movf","%s,w",
7080                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7081               pic16_emitcode("movwf","%s",
7082                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7083               break;
7084             default:
7085               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7086               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7087               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7088
7089               pic16_emitcode("movlw","0x%x",t);
7090               pic16_emitcode("iorwf","%s,w",
7091                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7092               pic16_emitcode("movwf","%s",
7093                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7094               
7095             }
7096             continue;
7097           }
7098
7099           // faster than result <- left, anl result,right
7100           // and better if result is SFR
7101           if (AOP_TYPE(left) == AOP_ACC) {
7102             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7103             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7104           } else {
7105             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7106             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7107
7108             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7109             pic16_emitcode("iorwf","%s,w",
7110                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7111           }
7112           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7113           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7114         }
7115     }
7116
7117 release :
7118     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7119     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7120     pic16_freeAsmop(result,NULL,ic,TRUE);     
7121 }
7122
7123 /*-----------------------------------------------------------------*/
7124 /* genXor - code for xclusive or                                   */
7125 /*-----------------------------------------------------------------*/
7126 static void genXor (iCode *ic, iCode *ifx)
7127 {
7128   operand *left, *right, *result;
7129   int size, offset=0;
7130   unsigned long lit = 0L;
7131
7132   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7133
7134   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7135   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7136   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7137
7138   /* if left is a literal & right is not ||
7139      if left needs acc & right does not */
7140   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7141       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7142     operand *tmp = right ;
7143     right = left;
7144     left = tmp;
7145   }
7146
7147   /* if result = right then exchange them */
7148   if(pic16_sameRegs(AOP(result),AOP(right))){
7149     operand *tmp = right ;
7150     right = left;
7151     left = tmp;
7152   }
7153
7154   /* if right is bit then exchange them */
7155   if (AOP_TYPE(right) == AOP_CRY &&
7156       AOP_TYPE(left) != AOP_CRY){
7157     operand *tmp = right ;
7158     right = left;
7159     left = tmp;
7160   }
7161   if(AOP_TYPE(right) == AOP_LIT)
7162     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7163
7164   size = AOP_SIZE(result);
7165
7166   // if(bit ^ yy)
7167   // xx = bit ^ yy;
7168   if (AOP_TYPE(left) == AOP_CRY){
7169     if(AOP_TYPE(right) == AOP_LIT){
7170       // c = bit & literal;
7171       if(lit>>1){
7172         // lit>>1  != 0 => result = 1
7173         if(AOP_TYPE(result) == AOP_CRY){
7174           if(size)
7175             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
7176             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7177           else if(ifx)
7178             continueIfTrue(ifx);
7179           goto release;
7180         }
7181         pic16_emitcode("setb","c");
7182       } else{
7183         // lit == (0 or 1)
7184         if(lit == 0){
7185           // lit == 0, result = left
7186           if(size && pic16_sameRegs(AOP(result),AOP(left)))
7187             goto release;
7188           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7189         } else{
7190           // lit == 1, result = not(left)
7191           if(size && pic16_sameRegs(AOP(result),AOP(left))){
7192             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
7193             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
7194             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
7195             goto release;
7196           } else {
7197             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7198             pic16_emitcode("cpl","c");
7199           }
7200         }
7201       }
7202
7203     } else {
7204       // right != literal
7205       symbol *tlbl = newiTempLabel(NULL);
7206       if (AOP_TYPE(right) == AOP_CRY){
7207         // c = bit ^ bit;
7208         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7209       }
7210       else{
7211         int sizer = AOP_SIZE(right);
7212         // c = bit ^ val
7213         // if val>>1 != 0, result = 1
7214         pic16_emitcode("setb","c");
7215         while(sizer){
7216           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
7217           if(sizer == 1)
7218             // test the msb of the lsb
7219             pic16_emitcode("anl","a,#0xfe");
7220           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7221           sizer--;
7222         }
7223         // val = (0,1)
7224         pic16_emitcode("rrc","a");
7225       }
7226       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
7227       pic16_emitcode("cpl","c");
7228       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
7229     }
7230     // bit = c
7231     // val = c
7232     if(size)
7233       pic16_outBitC(result);
7234     // if(bit | ...)
7235     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7236       genIfxJump(ifx, "c");           
7237     goto release ;
7238   }
7239
7240   if(pic16_sameRegs(AOP(result),AOP(left))){
7241     /* if left is same as result */
7242     for(;size--; offset++) {
7243       if(AOP_TYPE(right) == AOP_LIT){
7244         int t  = (lit >> (offset*8)) & 0x0FFL;
7245         if(t == 0x00L)
7246           continue;
7247         else
7248           if (IS_AOP_PREG(left)) {
7249             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7250             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7251             pic16_aopPut(AOP(result),"a",offset);
7252           } else {
7253             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7254             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7255             pic16_emitcode("xrl","%s,%s",
7256                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
7257                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7258           }
7259       } else {
7260         if (AOP_TYPE(left) == AOP_ACC)
7261           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7262         else {
7263           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7264           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7265 /*
7266           if (IS_AOP_PREG(left)) {
7267             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7268             pic16_aopPut(AOP(result),"a",offset);
7269           } else
7270             pic16_emitcode("xrl","%s,a",
7271                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7272 */
7273         }
7274       }
7275     }
7276   } else {
7277     // left & result in different registers
7278     if(AOP_TYPE(result) == AOP_CRY){
7279       // result = bit
7280       // if(size), result in bit
7281       // if(!size && ifx), conditional oper: if(left ^ right)
7282       symbol *tlbl = newiTempLabel(NULL);
7283       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7284       if(size)
7285         pic16_emitcode("setb","c");
7286       while(sizer--){
7287         if((AOP_TYPE(right) == AOP_LIT) &&
7288            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
7289           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7290         } else {
7291           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7292           pic16_emitcode("xrl","a,%s",
7293                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7294         }
7295         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7296         offset++;
7297       }
7298       if(size){
7299         CLRC;
7300         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7301         pic16_outBitC(result);
7302       } else if(ifx)
7303         jmpTrueOrFalse(ifx, tlbl);
7304     } else for(;(size--);offset++){
7305       // normal case
7306       // result = left & right
7307       if(AOP_TYPE(right) == AOP_LIT){
7308         int t = (lit >> (offset*8)) & 0x0FFL;
7309         switch(t) { 
7310         case 0x00:
7311           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7312           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7313           pic16_emitcode("movf","%s,w",
7314                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7315           pic16_emitcode("movwf","%s",
7316                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7317           break;
7318         case 0xff:
7319           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
7320           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7321           pic16_emitcode("comf","%s,w",
7322                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7323           pic16_emitcode("movwf","%s",
7324                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7325           break;
7326         default:
7327           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7328           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7329           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7330           pic16_emitcode("movlw","0x%x",t);
7331           pic16_emitcode("xorwf","%s,w",
7332                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7333           pic16_emitcode("movwf","%s",
7334                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7335
7336         }
7337         continue;
7338       }
7339
7340       // faster than result <- left, anl result,right
7341       // and better if result is SFR
7342       if (AOP_TYPE(left) == AOP_ACC) {
7343         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7344         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7345       } else {
7346         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7347         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7348         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7349         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7350       }
7351       if ( AOP_TYPE(result) != AOP_ACC){
7352         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7353         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7354       }
7355     }
7356   }
7357
7358   release :
7359     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7360   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7361   pic16_freeAsmop(result,NULL,ic,TRUE);     
7362 }
7363
7364 /*-----------------------------------------------------------------*/
7365 /* genInline - write the inline code out                           */
7366 /*-----------------------------------------------------------------*/
7367 static void genInline (iCode *ic)
7368 {
7369   char *buffer, *bp, *bp1;
7370     
7371         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7372
7373         _G.inLine += (!options.asmpeep);
7374
7375         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7376         strcpy(buffer,IC_INLINE(ic));
7377
7378 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
7379
7380         /* emit each line as a code */
7381         while (*bp) {
7382                 if (*bp == '\n') {
7383                         *bp++ = '\0';
7384
7385                         if(*bp1)
7386                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7387                         bp1 = bp;
7388                 } else {
7389                         if (*bp == ':') {
7390                                 bp++;
7391                                 *bp = '\0';
7392                                 bp++;
7393
7394                                 /* print label, use this special format with NULL directive
7395                                  * to denote that the argument should not be indented with tab */
7396                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
7397                                 bp1 = bp;
7398                         } else
7399                                 bp++;
7400                 }
7401         }
7402
7403         if ((bp1 != bp) && *bp1)
7404                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7405
7406
7407     Safe_free(buffer);
7408
7409     _G.inLine -= (!options.asmpeep);
7410 }
7411
7412 /*-----------------------------------------------------------------*/
7413 /* genRRC - rotate right with carry                                */
7414 /*-----------------------------------------------------------------*/
7415 static void genRRC (iCode *ic)
7416 {
7417   operand *left , *result ;
7418   int size, offset = 0, same;
7419
7420   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7421
7422   /* rotate right with carry */
7423   left = IC_LEFT(ic);
7424   result=IC_RESULT(ic);
7425   pic16_aopOp (left,ic,FALSE);
7426   pic16_aopOp (result,ic,FALSE);
7427
7428   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7429
7430   same = pic16_sameRegs(AOP(result),AOP(left));
7431
7432   size = AOP_SIZE(result);    
7433
7434   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
7435
7436   /* get the lsb and put it into the carry */
7437   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
7438
7439   offset = 0 ;
7440
7441   while(size--) {
7442
7443     if(same) {
7444       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
7445     } else {
7446       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
7447       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7448     }
7449
7450     offset++;
7451   }
7452
7453   pic16_freeAsmop(left,NULL,ic,TRUE);
7454   pic16_freeAsmop(result,NULL,ic,TRUE);
7455 }
7456
7457 /*-----------------------------------------------------------------*/
7458 /* genRLC - generate code for rotate left with carry               */
7459 /*-----------------------------------------------------------------*/
7460 static void genRLC (iCode *ic)
7461 {    
7462   operand *left , *result ;
7463   int size, offset = 0;
7464   int same;
7465
7466   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7467   /* rotate right with carry */
7468   left = IC_LEFT(ic);
7469   result=IC_RESULT(ic);
7470   pic16_aopOp (left,ic,FALSE);
7471   pic16_aopOp (result,ic,FALSE);
7472
7473   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7474
7475   same = pic16_sameRegs(AOP(result),AOP(left));
7476
7477   /* move it to the result */
7478   size = AOP_SIZE(result);    
7479
7480   /* get the msb and put it into the carry */
7481   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7482
7483   offset = 0 ;
7484
7485   while(size--) {
7486
7487     if(same) {
7488       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7489     } else {
7490       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7491       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7492     }
7493
7494     offset++;
7495   }
7496
7497
7498   pic16_freeAsmop(left,NULL,ic,TRUE);
7499   pic16_freeAsmop(result,NULL,ic,TRUE);
7500 }
7501
7502
7503 /* gpasm can get the highest order bit with HIGH/UPPER
7504  * so the following probably is not needed -- VR */
7505  
7506 /*-----------------------------------------------------------------*/
7507 /* genGetHbit - generates code get highest order bit               */
7508 /*-----------------------------------------------------------------*/
7509 static void genGetHbit (iCode *ic)
7510 {
7511     operand *left, *result;
7512     left = IC_LEFT(ic);
7513     result=IC_RESULT(ic);
7514     pic16_aopOp (left,ic,FALSE);
7515     pic16_aopOp (result,ic,FALSE);
7516
7517     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7518     /* get the highest order byte into a */
7519     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7520     if(AOP_TYPE(result) == AOP_CRY){
7521         pic16_emitcode("rlc","a");
7522         pic16_outBitC(result);
7523     }
7524     else{
7525         pic16_emitcode("rl","a");
7526         pic16_emitcode("anl","a,#0x01");
7527         pic16_outAcc(result);
7528     }
7529
7530
7531     pic16_freeAsmop(left,NULL,ic,TRUE);
7532     pic16_freeAsmop(result,NULL,ic,TRUE);
7533 }
7534
7535 #if 0
7536 /*-----------------------------------------------------------------*/
7537 /* AccRol - rotate left accumulator by known count                 */
7538 /*-----------------------------------------------------------------*/
7539 static void AccRol (int shCount)
7540 {
7541     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7542     shCount &= 0x0007;              // shCount : 0..7
7543     switch(shCount){
7544         case 0 :
7545             break;
7546         case 1 :
7547             pic16_emitcode("rl","a");
7548             break;
7549         case 2 :
7550             pic16_emitcode("rl","a");
7551             pic16_emitcode("rl","a");
7552             break;
7553         case 3 :
7554             pic16_emitcode("swap","a");
7555             pic16_emitcode("rr","a");
7556             break;
7557         case 4 :
7558             pic16_emitcode("swap","a");
7559             break;
7560         case 5 :
7561             pic16_emitcode("swap","a");
7562             pic16_emitcode("rl","a");
7563             break;
7564         case 6 :
7565             pic16_emitcode("rr","a");
7566             pic16_emitcode("rr","a");
7567             break;
7568         case 7 :
7569             pic16_emitcode("rr","a");
7570             break;
7571     }
7572 }
7573 #endif
7574
7575 /*-----------------------------------------------------------------*/
7576 /* AccLsh - left shift accumulator by known count                  */
7577 /*-----------------------------------------------------------------*/
7578 static void AccLsh (int shCount)
7579 {
7580         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7581         switch(shCount){
7582                 case 0 :
7583                         return;
7584                         break;
7585                 case 1 :
7586                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7587                         break;
7588                 case 2 :
7589                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7590                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7591                         break;
7592                 case 3 :
7593                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7594                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7595                         break;
7596                 case 4 :
7597                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7598                         break;
7599                 case 5 :
7600                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7601                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7602                         break;
7603                 case 6 :
7604                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7605                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7606                         break;
7607                 case 7 :
7608                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7609                         break;
7610         }
7611
7612         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
7613 }
7614
7615 /*-----------------------------------------------------------------*/
7616 /* AccRsh - right shift accumulator by known count                 */
7617 /*-----------------------------------------------------------------*/
7618 static void AccRsh (int shCount, int andmask)
7619 {
7620         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7621         switch(shCount){
7622                 case 0 :
7623                         return; break;
7624                 case 1 :
7625                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7626                         break;
7627                 case 2 :
7628                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7629                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7630                         break;
7631                 case 3 :
7632                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7633                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7634                         break;
7635                 case 4 :
7636                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7637                         break;
7638                 case 5 :
7639                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7640                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7641                         break;
7642                 case 6 :
7643                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7644                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7645                         break;
7646                 case 7 :
7647                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7648                         break;
7649         }
7650         
7651         if(andmask)
7652                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7653         else
7654                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7655 }
7656
7657 #if 0
7658 /*-----------------------------------------------------------------*/
7659 /* AccSRsh - signed right shift accumulator by known count                 */
7660 /*-----------------------------------------------------------------*/
7661 static void AccSRsh (int shCount)
7662 {
7663     symbol *tlbl ;
7664     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7665     if(shCount != 0){
7666         if(shCount == 1){
7667             pic16_emitcode("mov","c,acc.7");
7668             pic16_emitcode("rrc","a");
7669         } else if(shCount == 2){
7670             pic16_emitcode("mov","c,acc.7");
7671             pic16_emitcode("rrc","a");
7672             pic16_emitcode("mov","c,acc.7");
7673             pic16_emitcode("rrc","a");
7674         } else {
7675             tlbl = newiTempLabel(NULL);
7676             /* rotate right accumulator */
7677             AccRol(8 - shCount);
7678             /* and kill the higher order bits */
7679             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7680             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7681             pic16_emitcode("orl","a,#0x%02x",
7682                      (unsigned char)~SRMask[shCount]);
7683             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7684         }
7685     }
7686 }
7687 #endif
7688
7689 /*-----------------------------------------------------------------*/
7690 /* shiftR1Left2Result - shift right one byte from left to result   */
7691 /*-----------------------------------------------------------------*/
7692 static void shiftR1Left2ResultSigned (operand *left, int offl,
7693                                 operand *result, int offr,
7694                                 int shCount)
7695 {
7696   int same;
7697
7698   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7699
7700   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7701
7702   switch(shCount) {
7703   case 1:
7704     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7705     if(same) 
7706       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7707     else {
7708       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7709       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7710     }
7711
7712     break;
7713   case 2:
7714
7715     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7716     if(same) 
7717       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7718     else {
7719       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7720       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7721     }
7722     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7723     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7724
7725     break;
7726
7727   case 3:
7728     if(same)
7729       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7730     else {
7731       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7732       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7733     }
7734
7735     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
7736     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7737     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7738
7739     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7740     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7741
7742     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7743     break;
7744
7745   case 4:
7746     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7747     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
7748     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7749     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
7750     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7751     break;
7752   case 5:
7753     if(same) {
7754       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
7755     } else {
7756       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
7757       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7758     }
7759     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
7760     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
7761     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7762     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
7763     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7764     break;
7765
7766   case 6:
7767     if(same) {
7768       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7769       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7770       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7771       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7772       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7773       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7774     } else {
7775       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7776       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7777       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7778       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7779       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7780     }
7781     break;
7782
7783   case 7:
7784     if(same) {
7785       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7786       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7787       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7788       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7789     } else {
7790       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7791       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7792       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7793     }
7794
7795   default:
7796     break;
7797   }
7798 }
7799
7800 /*-----------------------------------------------------------------*/
7801 /* shiftR1Left2Result - shift right one byte from left to result   */
7802 /*-----------------------------------------------------------------*/
7803 static void shiftR1Left2Result (operand *left, int offl,
7804                                 operand *result, int offr,
7805                                 int shCount, int sign)
7806 {
7807   int same;
7808
7809   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7810
7811   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7812
7813   /* Copy the msb into the carry if signed. */
7814   if(sign) {
7815     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7816     return;
7817   }
7818
7819
7820
7821   switch(shCount) {
7822   case 1:
7823     emitCLRC;
7824     if(same) 
7825       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7826     else {
7827       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7828       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7829     }
7830     break;
7831   case 2:
7832     emitCLRC;
7833     if(same) {
7834       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7835     } else {
7836       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7837       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7838     }
7839     emitCLRC;
7840     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7841
7842     break;
7843   case 3:
7844     if(same)
7845       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7846     else {
7847       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7848       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7849     }
7850
7851     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
7852     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7853     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7854     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7855     break;
7856       
7857   case 4:
7858     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7859     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7860     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7861     break;
7862
7863   case 5:
7864     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7865     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
7866     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7867     //emitCLRC;
7868     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
7869
7870     break;
7871   case 6:
7872
7873     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
7874     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
7875     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7876     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7877     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
7878     break;
7879
7880   case 7:
7881
7882     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7883     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7884     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7885
7886     break;
7887
7888   default:
7889     break;
7890   }
7891 }
7892
7893 /*-----------------------------------------------------------------*/
7894 /* shiftL1Left2Result - shift left one byte from left to result    */
7895 /*-----------------------------------------------------------------*/
7896 static void shiftL1Left2Result (operand *left, int offl,
7897                                 operand *result, int offr, int shCount)
7898 {
7899   int same;
7900
7901   //    char *l;
7902   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7903
7904   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7905   DEBUGpic16_emitcode ("; ***","same =  %d",same);
7906     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7907     //    MOVA(l);
7908     /* shift left accumulator */
7909     //AccLsh(shCount); // don't comment out just yet...
7910   //    pic16_aopPut(AOP(result),"a",offr);
7911
7912   switch(shCount) {
7913   case 1:
7914     /* Shift left 1 bit position */
7915     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7916     if(same) {
7917       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7918     } else {
7919       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7920       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7921     }
7922     break;
7923   case 2:
7924     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7925     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7926     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7927     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7928     break;
7929   case 3:
7930     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7931     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7932     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7933     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7934     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7935     break;
7936   case 4:
7937     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7938     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7939     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7940     break;
7941   case 5:
7942     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7943     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7944     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7945     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7946     break;
7947   case 6:
7948     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7949     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7950     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7951     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7952     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7953     break;
7954   case 7:
7955     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7956     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7957     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7958     break;
7959
7960   default:
7961     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7962   }
7963
7964 }
7965
7966 /*-----------------------------------------------------------------*/
7967 /* movLeft2Result - move byte from left to result                  */
7968 /*-----------------------------------------------------------------*/
7969 static void movLeft2Result (operand *left, int offl,
7970                             operand *result, int offr)
7971 {
7972   char *l;
7973   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7974   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7975     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7976
7977     if (*l == '@' && (IS_AOP_PREG(result))) {
7978       pic16_emitcode("mov","a,%s",l);
7979       pic16_aopPut(AOP(result),"a",offr);
7980     } else {
7981       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7982       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7983     }
7984   }
7985 }
7986
7987 /*-----------------------------------------------------------------*/
7988 /* shiftL2Left2Result - shift left two bytes from left to result   */
7989 /*-----------------------------------------------------------------*/
7990 static void shiftL2Left2Result (operand *left, int offl,
7991                                 operand *result, int offr, int shCount)
7992 {
7993   int same = pic16_sameRegs(AOP(result), AOP(left));
7994   int i;
7995
7996   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7997
7998   if (same && (offl != offr)) { // shift bytes
7999     if (offr > offl) {
8000        for(i=1;i>-1;i--) {
8001          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8002          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8003        }
8004     } else { // just treat as different later on
8005                 same = 0;
8006     }
8007   }
8008
8009   if(same) {
8010     switch(shCount) {
8011     case 0:
8012       break;
8013     case 1:
8014     case 2:
8015     case 3:
8016
8017       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8018       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8019       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8020
8021       while(--shCount) {
8022                 emitCLRC;
8023                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8024                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8025       }
8026
8027       break;
8028     case 4:
8029     case 5:
8030       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8031       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8032       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8033       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8034       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8035       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8036       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8037       if(shCount >=5) {
8038                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8039                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8040       }
8041       break;
8042     case 6:
8043       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8044       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8045       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8046       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8047       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8048       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8049       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8050       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8051       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8052       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8053       break;
8054     case 7:
8055       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8056       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8057       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8058       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8059       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8060     }
8061
8062   } else {
8063     switch(shCount) {
8064     case 0:
8065       break;
8066     case 1:
8067     case 2:
8068     case 3:
8069       /* note, use a mov/add for the shift since the mov has a
8070          chance of getting optimized out */
8071       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8072       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8073       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8074       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8075       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8076
8077       while(--shCount) {
8078                 emitCLRC;
8079                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8080                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8081       }
8082       break;
8083
8084     case 4:
8085     case 5:
8086       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8087       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8088       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8089       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8090       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8091       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
8092       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8093       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8094
8095
8096       if(shCount == 5) {
8097                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8098                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8099       }
8100       break;
8101     case 6:
8102       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8103       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8104       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8105       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8106
8107       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8108       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8109       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8110       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8111       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8112       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8113       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8114       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8115       break;
8116     case 7:
8117       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8118       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8119       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8120       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8121       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8122     }
8123   }
8124
8125 }
8126 /*-----------------------------------------------------------------*/
8127 /* shiftR2Left2Result - shift right two bytes from left to result  */
8128 /*-----------------------------------------------------------------*/
8129 static void shiftR2Left2Result (operand *left, int offl,
8130                                 operand *result, int offr,
8131                                 int shCount, int sign)
8132 {
8133   int same = pic16_sameRegs(AOP(result), AOP(left));
8134   int i;
8135   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8136
8137   if (same && (offl != offr)) { // shift right bytes
8138     if (offr < offl) {
8139        for(i=0;i<2;i++) {
8140          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8141          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8142        }
8143     } else { // just treat as different later on
8144                 same = 0;
8145     }
8146   }
8147
8148   switch(shCount) {
8149   case 0:
8150     break;
8151   case 1:
8152   case 2:
8153   case 3:
8154     if(sign)
8155       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8156     else
8157       emitCLRC;
8158
8159     if(same) {
8160       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8161       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8162     } else {
8163       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8164       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8165       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8166       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8167     }
8168
8169     while(--shCount) {
8170       if(sign)
8171                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8172       else
8173                 emitCLRC;
8174       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8175       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8176     }
8177     break;
8178   case 4:
8179   case 5:
8180     if(same) {
8181
8182       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
8183       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
8184       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8185
8186       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8187       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
8188       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8189       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8190     } else {
8191       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8192       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8193       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8194
8195       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8196       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8197       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8198       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8199       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8200     }
8201
8202     if(shCount >=5) {
8203       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8204       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8205     }
8206
8207     if(sign) {
8208       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
8209       pic16_emitpcode(POC_BTFSC, 
8210                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
8211       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8212     }
8213
8214     break;
8215
8216   case 6:
8217     if(same) {
8218
8219       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8220       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8221
8222       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8223       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8224       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8225       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8226       if(sign) {
8227         pic16_emitpcode(POC_BTFSC, 
8228                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8229         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8230       }
8231       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8232       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
8233       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8234       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8235     } else {
8236       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8237       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8238       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8239       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8240       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8241       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8242       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
8243       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8244       if(sign) {
8245         pic16_emitpcode(POC_BTFSC, 
8246                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8247         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8248       }
8249       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8250       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8251
8252         
8253     }
8254
8255     break;
8256   case 7:
8257     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8258     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8259     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8260     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
8261     if(sign) {
8262       emitSKPNC;
8263       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
8264     } else 
8265       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8266   }
8267 }
8268
8269
8270 /*-----------------------------------------------------------------*/
8271 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
8272 /*-----------------------------------------------------------------*/
8273 static void shiftLLeftOrResult (operand *left, int offl,
8274                                 operand *result, int offr, int shCount)
8275 {
8276     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8277
8278     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8279     /* shift left accumulator */
8280     AccLsh(shCount);
8281     /* or with result */
8282     /* back to result */
8283     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8284 }
8285
8286 /*-----------------------------------------------------------------*/
8287 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
8288 /*-----------------------------------------------------------------*/
8289 static void shiftRLeftOrResult (operand *left, int offl,
8290                                 operand *result, int offr, int shCount)
8291 {
8292     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8293     
8294     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8295     /* shift right accumulator */
8296     AccRsh(shCount, 1);
8297     /* or with result */
8298     /* back to result */
8299     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8300 }
8301
8302 /*-----------------------------------------------------------------*/
8303 /* genlshOne - left shift a one byte quantity by known count       */
8304 /*-----------------------------------------------------------------*/
8305 static void genlshOne (operand *result, operand *left, int shCount)
8306 {       
8307     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8308     shiftL1Left2Result(left, LSB, result, LSB, shCount);
8309 }
8310
8311 /*-----------------------------------------------------------------*/
8312 /* genlshTwo - left shift two bytes by known amount != 0           */
8313 /*-----------------------------------------------------------------*/
8314 static void genlshTwo (operand *result,operand *left, int shCount)
8315 {
8316     int size;
8317     
8318     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8319     size = pic16_getDataSize(result);
8320
8321     /* if shCount >= 8 */
8322     if (shCount >= 8) {
8323         shCount -= 8 ;
8324
8325         if (size > 1){
8326             if (shCount)
8327                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8328             else 
8329                 movLeft2Result(left, LSB, result, MSB16);
8330         }
8331         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8332     }
8333
8334     /*  1 <= shCount <= 7 */
8335     else {  
8336         if(size == 1)
8337             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
8338         else 
8339             shiftL2Left2Result(left, LSB, result, LSB, shCount);
8340     }
8341 }
8342
8343 /*-----------------------------------------------------------------*/
8344 /* shiftLLong - shift left one long from left to result            */
8345 /* offr = LSB or MSB16                                             */
8346 /*-----------------------------------------------------------------*/
8347 static void shiftLLong (operand *left, operand *result, int offr )
8348 {
8349     int size = AOP_SIZE(result);
8350     int same = pic16_sameRegs(AOP(left),AOP(result));
8351         int i;
8352
8353     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
8354
8355         if (same && (offr == MSB16)) { //shift one byte
8356                 for(i=size-1;i>=MSB16;i--) {
8357                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
8358                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
8359                 }
8360         } else {
8361                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
8362         }
8363         
8364     if (size > LSB+offr ){
8365                 if (same) {
8366                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
8367                 } else {
8368                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
8369                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
8370                 }
8371          }
8372
8373     if(size > MSB16+offr){
8374                 if (same) {
8375                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
8376                 } else {
8377                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
8378                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
8379                 }
8380     }
8381
8382     if(size > MSB24+offr){
8383                 if (same) {
8384                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
8385                 } else {
8386                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
8387                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
8388                 }
8389     }
8390
8391     if(size > MSB32+offr){
8392                 if (same) {
8393                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
8394                 } else {
8395                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
8396                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
8397                 }
8398     }
8399     if(offr != LSB)
8400                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8401
8402 }
8403
8404 /*-----------------------------------------------------------------*/
8405 /* genlshFour - shift four byte by a known amount != 0             */
8406 /*-----------------------------------------------------------------*/
8407 static void genlshFour (operand *result, operand *left, int shCount)
8408 {
8409     int size;
8410
8411     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8412     size = AOP_SIZE(result);
8413
8414     /* if shifting more that 3 bytes */
8415     if (shCount >= 24 ) {
8416         shCount -= 24;
8417         if (shCount)
8418             /* lowest order of left goes to the highest
8419             order of the destination */
8420             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
8421         else
8422             movLeft2Result(left, LSB, result, MSB32);
8423
8424                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8425                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8426                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
8427
8428         return;
8429     }
8430
8431     /* more than two bytes */
8432     else if ( shCount >= 16 ) {
8433         /* lower order two bytes goes to higher order two bytes */
8434         shCount -= 16;
8435         /* if some more remaining */
8436         if (shCount)
8437             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
8438         else {
8439             movLeft2Result(left, MSB16, result, MSB32);
8440             movLeft2Result(left, LSB, result, MSB24);
8441         }
8442                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8443                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8444         return;
8445     }    
8446
8447     /* if more than 1 byte */
8448     else if ( shCount >= 8 ) {
8449         /* lower order three bytes goes to higher order  three bytes */
8450         shCount -= 8;
8451         if(size == 2){
8452             if(shCount)
8453                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8454             else
8455                 movLeft2Result(left, LSB, result, MSB16);
8456         }
8457         else{   /* size = 4 */
8458             if(shCount == 0){
8459                 movLeft2Result(left, MSB24, result, MSB32);
8460                 movLeft2Result(left, MSB16, result, MSB24);
8461                 movLeft2Result(left, LSB, result, MSB16);
8462                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8463             }
8464             else if(shCount == 1)
8465                 shiftLLong(left, result, MSB16);
8466             else{
8467                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8468                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8469                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8470                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8471             }
8472         }
8473     }
8474
8475     /* 1 <= shCount <= 7 */
8476     else if(shCount <= 3)
8477     { 
8478         shiftLLong(left, result, LSB);
8479         while(--shCount >= 1)
8480             shiftLLong(result, result, LSB);
8481     }
8482     /* 3 <= shCount <= 7, optimize */
8483     else{
8484         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8485         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8486         shiftL2Left2Result(left, LSB, result, LSB, shCount);
8487     }
8488 }
8489
8490 /*-----------------------------------------------------------------*/
8491 /* genLeftShiftLiteral - left shifting by known count              */
8492 /*-----------------------------------------------------------------*/
8493 static void genLeftShiftLiteral (operand *left,
8494                                  operand *right,
8495                                  operand *result,
8496                                  iCode *ic)
8497 {    
8498     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8499     int size;
8500
8501     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8502     pic16_freeAsmop(right,NULL,ic,TRUE);
8503
8504     pic16_aopOp(left,ic,FALSE);
8505     pic16_aopOp(result,ic,FALSE);
8506
8507     size = getSize(operandType(result));
8508
8509 #if VIEW_SIZE
8510     pic16_emitcode("; shift left ","result %d, left %d",size,
8511              AOP_SIZE(left));
8512 #endif
8513
8514     /* I suppose that the left size >= result size */
8515     if(shCount == 0){
8516         while(size--){
8517             movLeft2Result(left, size, result, size);
8518         }
8519     }
8520
8521     else if(shCount >= (size * 8))
8522         while(size--)
8523             pic16_aopPut(AOP(result),zero,size);
8524     else{
8525         switch (size) {
8526             case 1:
8527                 genlshOne (result,left,shCount);
8528                 break;
8529
8530             case 2:
8531             case 3:
8532                 genlshTwo (result,left,shCount);
8533                 break;
8534
8535             case 4:
8536                 genlshFour (result,left,shCount);
8537                 break;
8538         }
8539     }
8540     pic16_freeAsmop(left,NULL,ic,TRUE);
8541     pic16_freeAsmop(result,NULL,ic,TRUE);
8542 }
8543
8544 /*-----------------------------------------------------------------*
8545  * genMultiAsm - repeat assembly instruction for size of register.
8546  * if endian == 1, then the high byte (i.e base address + size of 
8547  * register) is used first else the low byte is used first;
8548  *-----------------------------------------------------------------*/
8549 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8550 {
8551
8552   int offset = 0;
8553
8554   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8555
8556   if(!reg)
8557     return;
8558
8559   if(!endian) {
8560     endian = 1;
8561   } else {
8562     endian = -1;
8563     offset = size-1;
8564   }
8565
8566   while(size--) {
8567     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
8568     offset += endian;
8569   }
8570
8571 }
8572 /*-----------------------------------------------------------------*/
8573 /* genLeftShift - generates code for left shifting                 */
8574 /*-----------------------------------------------------------------*/
8575 static void genLeftShift (iCode *ic)
8576 {
8577   operand *left,*right, *result;
8578   int size, offset;
8579 //  char *l;
8580   symbol *tlbl , *tlbl1;
8581   pCodeOp *pctemp;
8582
8583   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8584
8585   right = IC_RIGHT(ic);
8586   left  = IC_LEFT(ic);
8587   result = IC_RESULT(ic);
8588
8589   pic16_aopOp(right,ic,FALSE);
8590
8591   /* if the shift count is known then do it 
8592      as efficiently as possible */
8593   if (AOP_TYPE(right) == AOP_LIT) {
8594     genLeftShiftLiteral (left,right,result,ic);
8595     return ;
8596   }
8597
8598   /* shift count is unknown then we have to form
8599    * a loop. Get the loop count in WREG : Note: we take
8600    * only the lower order byte since shifting
8601    * more than 32 bits make no sense anyway, ( the
8602    * largest size of an object can be only 32 bits ) */
8603   
8604   pic16_aopOp(left,ic,FALSE);
8605   pic16_aopOp(result,ic,FALSE);
8606
8607   /* now move the left to the result if they are not the
8608    * same, and if size > 1,
8609    * and if right is not same to result (!!!) -- VR */
8610   if (!pic16_sameRegs(AOP(left),AOP(result))
8611       && (AOP_SIZE(result) > 1)) {
8612
8613     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8614
8615     size = AOP_SIZE(result);
8616     offset=0;
8617     while (size--) {
8618
8619 #if 0
8620       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8621       if (*l == '@' && (IS_AOP_PREG(result))) {
8622
8623           pic16_emitcode("mov","a,%s",l);
8624           pic16_aopPut(AOP(result),"a",offset);
8625       } else
8626 #endif
8627       {
8628         /* we don't know if left is a literal or a register, take care -- VR */
8629         mov2f(AOP(result), AOP(left), offset);
8630       }
8631       offset++;
8632     }
8633   }
8634
8635   size = AOP_SIZE(result);
8636
8637   /* if it is only one byte then */
8638   if (size == 1) {
8639     if(optimized_for_speed) {
8640       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8641       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
8642       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
8643       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8644       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8645       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8646       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8647       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
8648       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
8649       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
8650       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
8651       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8652     } else {
8653
8654       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8655
8656       tlbl = newiTempLabel(NULL);
8657
8658 #if 1
8659       /* this is already done, why change it? */
8660       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8661                 mov2f(AOP(result), AOP(left), 0);
8662       }
8663 #endif
8664
8665       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8666       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8667       pic16_emitpLabel(tlbl->key);
8668       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8669       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8670       emitSKPC;
8671       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8672     }
8673     goto release ;
8674   }
8675     
8676   if (pic16_sameRegs(AOP(left),AOP(result))) {
8677
8678     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8679     
8680     tlbl = newiTempLabel(NULL);
8681     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8682     genMultiAsm(POC_RRCF, result, size,1);
8683     pic16_emitpLabel(tlbl->key);
8684     genMultiAsm(POC_RLCF, result, size,0);
8685     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8686     emitSKPC;
8687     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8688     goto release;
8689   }
8690
8691   //tlbl = newiTempLabel(NULL);
8692   //offset = 0 ;   
8693   //tlbl1 = newiTempLabel(NULL);
8694
8695   //reAdjustPreg(AOP(result));    
8696     
8697   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
8698   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8699   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8700   //MOVA(l);
8701   //pic16_emitcode("add","a,acc");         
8702   //pic16_aopPut(AOP(result),"a",offset++);
8703   //while (--size) {
8704   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8705   //  MOVA(l);
8706   //  pic16_emitcode("rlc","a");         
8707   //  pic16_aopPut(AOP(result),"a",offset++);
8708   //}
8709   //reAdjustPreg(AOP(result));
8710
8711   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8712   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8713
8714
8715   tlbl = newiTempLabel(NULL);
8716   tlbl1= newiTempLabel(NULL);
8717
8718   size = AOP_SIZE(result);
8719   offset = 1;
8720
8721   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
8722
8723   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8724
8725   /* offset should be 0, 1 or 3 */
8726   
8727   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8728   emitSKPNZ;
8729   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8730
8731   pic16_emitpcode(POC_MOVWF, pctemp);
8732
8733
8734   pic16_emitpLabel(tlbl->key);
8735
8736   emitCLRC;
8737   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
8738   while(--size)
8739     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
8740
8741   pic16_emitpcode(POC_DECFSZ,  pctemp);
8742   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8743   pic16_emitpLabel(tlbl1->key);
8744
8745   pic16_popReleaseTempReg(pctemp,1);
8746
8747
8748  release:
8749   pic16_freeAsmop (right,NULL,ic,TRUE);
8750   pic16_freeAsmop(left,NULL,ic,TRUE);
8751   pic16_freeAsmop(result,NULL,ic,TRUE);
8752 }
8753
8754
8755
8756 #if 0
8757 #error old code (left here for reference)
8758 /*-----------------------------------------------------------------*/
8759 /* genLeftShift - generates code for left shifting                 */
8760 /*-----------------------------------------------------------------*/
8761 static void genLeftShift (iCode *ic)
8762 {
8763   operand *left,*right, *result;
8764   int size, offset;
8765   char *l;
8766   symbol *tlbl , *tlbl1;
8767   pCodeOp *pctemp;
8768
8769   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8770
8771   right = IC_RIGHT(ic);
8772   left  = IC_LEFT(ic);
8773   result = IC_RESULT(ic);
8774
8775   pic16_aopOp(right,ic,FALSE);
8776
8777   /* if the shift count is known then do it 
8778      as efficiently as possible */
8779   if (AOP_TYPE(right) == AOP_LIT) {
8780     genLeftShiftLiteral (left,right,result,ic);
8781     return ;
8782   }
8783
8784   /* shift count is unknown then we have to form 
8785      a loop get the loop count in B : Note: we take
8786      only the lower order byte since shifting
8787      more that 32 bits make no sense anyway, ( the
8788      largest size of an object can be only 32 bits ) */  
8789
8790     
8791   pic16_aopOp(left,ic,FALSE);
8792   pic16_aopOp(result,ic,FALSE);
8793
8794   /* now move the left to the result if they are not the
8795      same */
8796   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8797       AOP_SIZE(result) > 1) {
8798
8799     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8800
8801     size = AOP_SIZE(result);
8802     offset=0;
8803     while (size--) {
8804       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8805       if (*l == '@' && (IS_AOP_PREG(result))) {
8806
8807         pic16_emitcode("mov","a,%s",l);
8808         pic16_aopPut(AOP(result),"a",offset);
8809       } else {
8810
8811         /* we don't know if left is a literal or a register, take care -- VR */
8812         mov2f(AOP(result), AOP(left), offset);
8813       }
8814       offset++;
8815     }
8816   }
8817
8818   size = AOP_SIZE(result);
8819
8820   /* if it is only one byte then */
8821   if (size == 1) {
8822     if(optimized_for_speed) {
8823       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8824       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
8825       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
8826       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8827       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8828       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8829       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8830       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
8831       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
8832       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
8833       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
8834       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8835     } else {
8836
8837       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8838
8839       tlbl = newiTempLabel(NULL);
8840       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8841                 mov2f(AOP(result), AOP(left), 0);
8842                 
8843 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8844 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8845       }
8846
8847       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8848       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8849       pic16_emitpLabel(tlbl->key);
8850       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8851       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8852       emitSKPC;
8853       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8854     }
8855     goto release ;
8856   }
8857     
8858   if (pic16_sameRegs(AOP(left),AOP(result))) {
8859
8860     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8861     
8862     tlbl = newiTempLabel(NULL);
8863     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8864     genMultiAsm(POC_RRCF, result, size,1);
8865     pic16_emitpLabel(tlbl->key);
8866     genMultiAsm(POC_RLCF, result, size,0);
8867     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8868     emitSKPC;
8869     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8870     goto release;
8871   }
8872
8873   //tlbl = newiTempLabel(NULL);
8874   //offset = 0 ;   
8875   //tlbl1 = newiTempLabel(NULL);
8876
8877   //reAdjustPreg(AOP(result));    
8878     
8879   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
8880   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8881   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8882   //MOVA(l);
8883   //pic16_emitcode("add","a,acc");         
8884   //pic16_aopPut(AOP(result),"a",offset++);
8885   //while (--size) {
8886   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8887   //  MOVA(l);
8888   //  pic16_emitcode("rlc","a");         
8889   //  pic16_aopPut(AOP(result),"a",offset++);
8890   //}
8891   //reAdjustPreg(AOP(result));
8892
8893   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8894   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8895
8896
8897   tlbl = newiTempLabel(NULL);
8898   tlbl1= newiTempLabel(NULL);
8899
8900   size = AOP_SIZE(result);
8901   offset = 1;
8902
8903   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
8904
8905   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8906
8907   /* offset should be 0, 1 or 3 */
8908   
8909   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8910   emitSKPNZ;
8911   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8912
8913   pic16_emitpcode(POC_MOVWF, pctemp);
8914
8915
8916   pic16_emitpLabel(tlbl->key);
8917
8918   emitCLRC;
8919   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
8920   while(--size)
8921     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
8922
8923   pic16_emitpcode(POC_DECFSZ,  pctemp);
8924   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8925   pic16_emitpLabel(tlbl1->key);
8926
8927   pic16_popReleaseTempReg(pctemp,1);
8928
8929
8930  release:
8931   pic16_freeAsmop (right,NULL,ic,TRUE);
8932   pic16_freeAsmop(left,NULL,ic,TRUE);
8933   pic16_freeAsmop(result,NULL,ic,TRUE);
8934 }
8935 #endif
8936
8937 /*-----------------------------------------------------------------*/
8938 /* genrshOne - right shift a one byte quantity by known count      */
8939 /*-----------------------------------------------------------------*/
8940 static void genrshOne (operand *result, operand *left,
8941                        int shCount, int sign)
8942 {
8943     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8944     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8945 }
8946
8947 /*-----------------------------------------------------------------*/
8948 /* genrshTwo - right shift two bytes by known amount != 0          */
8949 /*-----------------------------------------------------------------*/
8950 static void genrshTwo (operand *result,operand *left,
8951                        int shCount, int sign)
8952 {
8953   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8954   /* if shCount >= 8 */
8955   if (shCount >= 8) {
8956     shCount -= 8 ;
8957     if (shCount)
8958       shiftR1Left2Result(left, MSB16, result, LSB,
8959                          shCount, sign);
8960     else
8961       movLeft2Result(left, MSB16, result, LSB);
8962
8963     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8964
8965     if(sign) {
8966       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8967       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8968     }
8969   }
8970
8971   /*  1 <= shCount <= 7 */
8972   else
8973     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
8974 }
8975
8976 /*-----------------------------------------------------------------*/
8977 /* shiftRLong - shift right one long from left to result           */
8978 /* offl = LSB or MSB16                                             */
8979 /*-----------------------------------------------------------------*/
8980 static void shiftRLong (operand *left, int offl,
8981                         operand *result, int sign)
8982 {
8983     int size = AOP_SIZE(result);
8984     int same = pic16_sameRegs(AOP(left),AOP(result));
8985     int i;
8986     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8987
8988         if (same && (offl == MSB16)) { //shift one byte right
8989                 for(i=MSB16;i<size;i++) {
8990                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8991                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8992                 }
8993         }
8994
8995     if(sign)
8996                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8997         else
8998                 emitCLRC;
8999
9000         if (same) {
9001                 if (offl == LSB)
9002                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9003         } else {
9004         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9005         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9006         }
9007
9008     if(offl == MSB16) {
9009         /* add sign of "a" */
9010         pic16_addSign(result, MSB32, sign);
9011         }
9012
9013         if (same) {
9014         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9015         } else {
9016         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9017         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9018         }
9019         
9020         if (same) {
9021         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9022         } else {
9023         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9024         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9025         }
9026
9027         if (same) {
9028         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9029         } else {
9030         if(offl == LSB){
9031                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9032                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9033         }
9034         }
9035 }
9036
9037 /*-----------------------------------------------------------------*/
9038 /* genrshFour - shift four byte by a known amount != 0             */
9039 /*-----------------------------------------------------------------*/
9040 static void genrshFour (operand *result, operand *left,
9041                         int shCount, int sign)
9042 {
9043   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9044   /* if shifting more that 3 bytes */
9045   if(shCount >= 24 ) {
9046     shCount -= 24;
9047     if(shCount)
9048       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9049     else
9050       movLeft2Result(left, MSB32, result, LSB);
9051
9052     pic16_addSign(result, MSB16, sign);
9053   }
9054   else if(shCount >= 16){
9055     shCount -= 16;
9056     if(shCount)
9057       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9058     else{
9059       movLeft2Result(left, MSB24, result, LSB);
9060       movLeft2Result(left, MSB32, result, MSB16);
9061     }
9062     pic16_addSign(result, MSB24, sign);
9063   }
9064   else if(shCount >= 8){
9065     shCount -= 8;
9066     if(shCount == 1)
9067       shiftRLong(left, MSB16, result, sign);
9068     else if(shCount == 0){
9069       movLeft2Result(left, MSB16, result, LSB);
9070       movLeft2Result(left, MSB24, result, MSB16);
9071       movLeft2Result(left, MSB32, result, MSB24);
9072       pic16_addSign(result, MSB32, sign);
9073     }
9074     else{ //shcount >= 2
9075       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9076       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9077       /* the last shift is signed */
9078       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9079       pic16_addSign(result, MSB32, sign);
9080     }
9081   }
9082   else{   /* 1 <= shCount <= 7 */
9083     if(shCount <= 2){
9084       shiftRLong(left, LSB, result, sign);
9085       if(shCount == 2)
9086         shiftRLong(result, LSB, result, sign);
9087     }
9088     else{
9089       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
9090       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
9091       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
9092     }
9093   }
9094 }
9095
9096 /*-----------------------------------------------------------------*/
9097 /* genRightShiftLiteral - right shifting by known count            */
9098 /*-----------------------------------------------------------------*/
9099 static void genRightShiftLiteral (operand *left,
9100                                   operand *right,
9101                                   operand *result,
9102                                   iCode *ic,
9103                                   int sign)
9104 {    
9105   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
9106   int lsize,res_size;
9107
9108   pic16_freeAsmop(right,NULL,ic,TRUE);
9109
9110   pic16_aopOp(left,ic,FALSE);
9111   pic16_aopOp(result,ic,FALSE);
9112
9113   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
9114
9115 #if VIEW_SIZE
9116   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
9117                  AOP_SIZE(left));
9118 #endif
9119
9120   lsize = pic16_getDataSize(left);
9121   res_size = pic16_getDataSize(result);
9122   /* test the LEFT size !!! */
9123
9124   /* I suppose that the left size >= result size */
9125   if(shCount == 0){
9126     while(res_size--)
9127       movLeft2Result(left, lsize, result, res_size);
9128   }
9129
9130   else if(shCount >= (lsize * 8)){
9131
9132     if(res_size == 1) {
9133       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
9134       if(sign) {
9135         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9136         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
9137       }
9138     } else {
9139
9140       if(sign) {
9141         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
9142         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9143         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9144         while(res_size--)
9145           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
9146
9147       } else {
9148
9149         while(res_size--)
9150           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
9151       }
9152     }
9153   } else {
9154
9155     switch (res_size) {
9156     case 1:
9157       genrshOne (result,left,shCount,sign);
9158       break;
9159
9160     case 2:
9161       genrshTwo (result,left,shCount,sign);
9162       break;
9163
9164     case 4:
9165       genrshFour (result,left,shCount,sign);
9166       break;
9167     default :
9168       break;
9169     }
9170
9171   }
9172
9173   pic16_freeAsmop(left,NULL,ic,TRUE);
9174   pic16_freeAsmop(result,NULL,ic,TRUE);
9175 }
9176
9177 /*-----------------------------------------------------------------*/
9178 /* genSignedRightShift - right shift of signed number              */
9179 /*-----------------------------------------------------------------*/
9180 static void genSignedRightShift (iCode *ic)
9181 {
9182   operand *right, *left, *result;
9183   int size, offset;
9184   //  char *l;
9185   symbol *tlbl, *tlbl1 ;
9186   pCodeOp *pctemp;
9187
9188   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
9189
9190   /* we do it the hard way put the shift count in b
9191      and loop thru preserving the sign */
9192   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9193
9194   right = IC_RIGHT(ic);
9195   left  = IC_LEFT(ic);
9196   result = IC_RESULT(ic);
9197
9198   pic16_aopOp(right,ic,FALSE);  
9199   pic16_aopOp(left,ic,FALSE);
9200   pic16_aopOp(result,ic,FALSE);
9201
9202
9203   if ( AOP_TYPE(right) == AOP_LIT) {
9204     genRightShiftLiteral (left,right,result,ic,1);
9205     return ;
9206   }
9207   /* shift count is unknown then we have to form 
9208      a loop get the loop count in B : Note: we take
9209      only the lower order byte since shifting
9210      more that 32 bits make no sense anyway, ( the
9211      largest size of an object can be only 32 bits ) */  
9212
9213   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
9214   //pic16_emitcode("inc","b");
9215   //pic16_freeAsmop (right,NULL,ic,TRUE);
9216   //pic16_aopOp(left,ic,FALSE);
9217   //pic16_aopOp(result,ic,FALSE);
9218
9219   /* now move the left to the result if they are not the
9220      same */
9221   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9222       AOP_SIZE(result) > 1) {
9223
9224     size = AOP_SIZE(result);
9225     offset=0;
9226     while (size--) { 
9227       /*
9228         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9229         if (*l == '@' && IS_AOP_PREG(result)) {
9230
9231         pic16_emitcode("mov","a,%s",l);
9232         pic16_aopPut(AOP(result),"a",offset);
9233         } else
9234         pic16_aopPut(AOP(result),l,offset);
9235       */
9236       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
9237       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
9238
9239       offset++;
9240     }
9241   }
9242
9243   /* mov the highest order bit to OVR */    
9244   tlbl = newiTempLabel(NULL);
9245   tlbl1= newiTempLabel(NULL);
9246
9247   size = AOP_SIZE(result);
9248   offset = size - 1;
9249
9250   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9251
9252   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9253
9254   /* offset should be 0, 1 or 3 */
9255   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
9256   emitSKPNZ;
9257   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9258
9259   pic16_emitpcode(POC_MOVWF, pctemp);
9260
9261
9262   pic16_emitpLabel(tlbl->key);
9263
9264   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
9265   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
9266
9267   while(--size) {
9268     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
9269   }
9270
9271   pic16_emitpcode(POC_DECFSZ,  pctemp);
9272   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9273   pic16_emitpLabel(tlbl1->key);
9274
9275   pic16_popReleaseTempReg(pctemp,1);
9276 #if 0
9277   size = AOP_SIZE(result);
9278   offset = size - 1;
9279   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
9280   pic16_emitcode("rlc","a");
9281   pic16_emitcode("mov","ov,c");
9282   /* if it is only one byte then */
9283   if (size == 1) {
9284     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9285     MOVA(l);
9286     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9287     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9288     pic16_emitcode("mov","c,ov");
9289     pic16_emitcode("rrc","a");
9290     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9291     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9292     pic16_aopPut(AOP(result),"a",0);
9293     goto release ;
9294   }
9295
9296   reAdjustPreg(AOP(result));
9297   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9298   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9299   pic16_emitcode("mov","c,ov");
9300   while (size--) {
9301     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9302     MOVA(l);
9303     pic16_emitcode("rrc","a");         
9304     pic16_aopPut(AOP(result),"a",offset--);
9305   }
9306   reAdjustPreg(AOP(result));
9307   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9308   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9309
9310  release:
9311 #endif
9312
9313   pic16_freeAsmop(left,NULL,ic,TRUE);
9314   pic16_freeAsmop(result,NULL,ic,TRUE);
9315   pic16_freeAsmop(right,NULL,ic,TRUE);
9316 }
9317
9318 /*-----------------------------------------------------------------*/
9319 /* genRightShift - generate code for right shifting                */
9320 /*-----------------------------------------------------------------*/
9321 static void genRightShift (iCode *ic)
9322 {
9323     operand *right, *left, *result;
9324     sym_link *letype ;
9325     int size, offset;
9326     char *l;
9327     symbol *tlbl, *tlbl1 ;
9328
9329     /* if signed then we do it the hard way preserve the
9330     sign bit moving it inwards */
9331     letype = getSpec(operandType(IC_LEFT(ic)));
9332     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9333
9334     if (!SPEC_USIGN(letype)) {
9335         genSignedRightShift (ic);
9336         return ;
9337     }
9338
9339     /* signed & unsigned types are treated the same : i.e. the
9340     signed is NOT propagated inwards : quoting from the
9341     ANSI - standard : "for E1 >> E2, is equivalent to division
9342     by 2**E2 if unsigned or if it has a non-negative value,
9343     otherwise the result is implementation defined ", MY definition
9344     is that the sign does not get propagated */
9345
9346     right = IC_RIGHT(ic);
9347     left  = IC_LEFT(ic);
9348     result = IC_RESULT(ic);
9349
9350     pic16_aopOp(right,ic,FALSE);
9351
9352     /* if the shift count is known then do it 
9353     as efficiently as possible */
9354     if (AOP_TYPE(right) == AOP_LIT) {
9355         genRightShiftLiteral (left,right,result,ic, 0);
9356         return ;
9357     }
9358
9359     /* shift count is unknown then we have to form 
9360     a loop get the loop count in B : Note: we take
9361     only the lower order byte since shifting
9362     more that 32 bits make no sense anyway, ( the
9363     largest size of an object can be only 32 bits ) */  
9364
9365     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
9366     pic16_emitcode("inc","b");
9367     pic16_aopOp(left,ic,FALSE);
9368     pic16_aopOp(result,ic,FALSE);
9369
9370     /* now move the left to the result if they are not the
9371     same */
9372     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9373         AOP_SIZE(result) > 1) {
9374
9375         size = AOP_SIZE(result);
9376         offset=0;
9377         while (size--) {
9378             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9379             if (*l == '@' && IS_AOP_PREG(result)) {
9380
9381                 pic16_emitcode("mov","a,%s",l);
9382                 pic16_aopPut(AOP(result),"a",offset);
9383             } else
9384                 pic16_aopPut(AOP(result),l,offset);
9385             offset++;
9386         }
9387     }
9388
9389     tlbl = newiTempLabel(NULL);
9390     tlbl1= newiTempLabel(NULL);
9391     size = AOP_SIZE(result);
9392     offset = size - 1;
9393
9394     /* if it is only one byte then */
9395     if (size == 1) {
9396
9397       tlbl = newiTempLabel(NULL);
9398       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9399         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9400         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9401       }
9402
9403       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9404       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9405       pic16_emitpLabel(tlbl->key);
9406       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9407       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9408       emitSKPC;
9409       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9410
9411       goto release ;
9412     }
9413
9414     reAdjustPreg(AOP(result));
9415     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9416     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9417     CLRC;
9418     while (size--) {
9419         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9420         MOVA(l);
9421         pic16_emitcode("rrc","a");         
9422         pic16_aopPut(AOP(result),"a",offset--);
9423     }
9424     reAdjustPreg(AOP(result));
9425
9426     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9427     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9428
9429 release:
9430     pic16_freeAsmop(left,NULL,ic,TRUE);
9431     pic16_freeAsmop (right,NULL,ic,TRUE);
9432     pic16_freeAsmop(result,NULL,ic,TRUE);
9433 }
9434
9435
9436 void pic16_loadFSR0(operand *op)
9437 {
9438         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
9439 }
9440
9441 /*-----------------------------------------------------------------*/
9442 /* genUnpackBits - generates code for unpacking bits               */
9443 /*-----------------------------------------------------------------*/
9444 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
9445 {    
9446     int shCnt ;
9447     int rlen = 0 ;
9448     sym_link *etype;
9449     int offset = 0 ;
9450
9451         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9452         etype = getSpec(operandType(result));
9453
9454         /* the following call to pic16_loadFSR0 is temporary until
9455          * optimization to handle single bit assignments is added
9456          * to the function. Until then use the old safe way! -- VR */
9457         pic16_loadFSR0( left );
9458  
9459         /* read the first byte  */
9460         switch (ptype) {
9461                 case POINTER:
9462                 case IPOINTER:
9463                 case PPOINTER:
9464                 case FPOINTER:
9465                 case GPOINTER:
9466                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9467                         break;
9468                 case CPOINTER:
9469                         pic16_emitcode("clr","a");
9470                         pic16_emitcode("movc","a","@a+dptr");
9471                         break;
9472         }
9473         
9474
9475         /* if we have bitdisplacement then it fits   */
9476         /* into this byte completely or if length is */
9477         /* less than a byte                          */
9478         if ((shCnt = SPEC_BSTR(etype)) || 
9479                 (SPEC_BLEN(etype) <= 8))  {
9480
9481                 /* shift right acc */
9482                 AccRsh(shCnt, 0);
9483
9484                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9485                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
9486
9487 /* VR -- normally I would use the following, but since we use the hack,
9488  * to avoid the masking from AccRsh, why not mask it right now? */
9489
9490 /*
9491                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
9492 */
9493
9494                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9495           return ;
9496         }
9497
9498
9499
9500         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9501         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9502         exit(-1);
9503
9504     /* bit field did not fit in a byte  */
9505     rlen = SPEC_BLEN(etype) - 8;
9506     pic16_aopPut(AOP(result),"a",offset++);
9507
9508     while (1)  {
9509
9510         switch (ptype) {
9511         case POINTER:
9512         case IPOINTER:
9513             pic16_emitcode("inc","%s",rname);
9514             pic16_emitcode("mov","a,@%s",rname);
9515             break;
9516             
9517         case PPOINTER:
9518             pic16_emitcode("inc","%s",rname);
9519             pic16_emitcode("movx","a,@%s",rname);
9520             break;
9521
9522         case FPOINTER:
9523             pic16_emitcode("inc","dptr");
9524             pic16_emitcode("movx","a,@dptr");
9525             break;
9526             
9527         case CPOINTER:
9528             pic16_emitcode("clr","a");
9529             pic16_emitcode("inc","dptr");
9530             pic16_emitcode("movc","a","@a+dptr");
9531             break;
9532             
9533         case GPOINTER:
9534             pic16_emitcode("inc","dptr");
9535             pic16_emitcode("lcall","__gptrget");
9536             break;
9537         }
9538
9539         rlen -= 8;            
9540         /* if we are done */
9541         if ( rlen <= 0 )
9542             break ;
9543         
9544         pic16_aopPut(AOP(result),"a",offset++);
9545                               
9546     }
9547     
9548     if (rlen) {
9549         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
9550         pic16_aopPut(AOP(result),"a",offset);          
9551     }
9552     
9553     return ;
9554 }
9555
9556
9557 static void genDataPointerGet(operand *left,
9558                               operand *result,
9559                               iCode *ic)
9560 {
9561   int size, offset = 0, leoffset=0 ;
9562
9563         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9564         pic16_aopOp(result, ic, FALSE);
9565
9566         size = AOP_SIZE(result);
9567 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9568
9569
9570 #if 0
9571         /* The following tests may save a redudant movff instruction when
9572          * accessing unions */
9573          
9574         /* if they are the same */
9575         if (operandsEqu (left, result)) {
9576                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
9577                 goto release;
9578         }
9579 #endif
9580
9581 #if 0
9582         /* if they are the same registers */
9583         if (pic16_sameRegs(AOP(left),AOP(result))) {
9584                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
9585                 goto release;
9586         }
9587 #endif
9588
9589 #if 1
9590         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
9591                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
9592                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
9593                 goto release;
9594         }
9595 #endif
9596
9597
9598 #if 0
9599         if ( AOP_TYPE(left) == AOP_PCODE) {
9600                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
9601                                 AOP(left)->aopu.pcop->name,
9602                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
9603                                 PCOR(AOP(left)->aopu.pcop)->instance:
9604                                 PCOI(AOP(left)->aopu.pcop)->offset);
9605         }
9606 #endif
9607
9608         if(AOP(left)->aopu.pcop->type == PO_DIR)
9609                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
9610
9611         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9612
9613         while (size--) {
9614                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
9615                 
9616                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
9617                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
9618                         mov2w(AOP(left), offset); // patch 8
9619                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9620                 } else {
9621                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
9622                                 pic16_popGet(AOP(left), offset), //patch 8
9623                                 pic16_popGet(AOP(result), offset)));
9624                 }
9625
9626                 offset++;
9627                 leoffset++;
9628         }
9629
9630 release:
9631     pic16_freeAsmop(result,NULL,ic,TRUE);
9632 }
9633
9634
9635
9636 /*-----------------------------------------------------------------*/
9637 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
9638 /*-----------------------------------------------------------------*/
9639 static void genNearPointerGet (operand *left, 
9640                                operand *result, 
9641                                iCode *ic)
9642 {
9643     asmop *aop = NULL;
9644     //regs *preg = NULL ;
9645     sym_link *rtype, *retype;
9646     sym_link *ltype = operandType(left);    
9647
9648         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9649         rtype = operandType(result);
9650         retype= getSpec(rtype);
9651     
9652         pic16_aopOp(left,ic,FALSE);
9653
9654 //      pic16_DumpOp("(left)",left);
9655 //      pic16_DumpOp("(result)",result);
9656
9657         /* if left is rematerialisable and
9658          * result is not bit variable type and
9659          * the left is pointer to data space i.e
9660          * lower 128 bytes of space */
9661         if (AOP_TYPE(left) == AOP_PCODE
9662                 && !IS_BITFIELD(retype)
9663                 && DCL_TYPE(ltype) == POINTER) {
9664
9665                 genDataPointerGet (left,result,ic);
9666                 pic16_freeAsmop(left, NULL, ic, TRUE);
9667           return ;
9668         }
9669     
9670         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9671
9672         /* if the value is already in a pointer register
9673          * then don't need anything more */
9674         if (!AOP_INPREG(AOP(left))) {
9675                 /* otherwise get a free pointer register */
9676                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9677                 
9678                 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
9679                 if( (AOP_TYPE(left) == AOP_PCODE) 
9680                         && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9681                                 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
9682                 {
9683                         if(!IS_BITFIELD(retype))
9684                                 pic16_loadFSR0( left );  // patch 10
9685                 } else {
9686                         // set up FSR0 with address from left
9687                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9688                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9689                 }
9690         }
9691 //       else
9692 //      rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9693     
9694         pic16_aopOp (result,ic,FALSE);
9695     
9696       /* if bitfield then unpack the bits */
9697     if (IS_BITFIELD(retype)) 
9698         genUnpackBits (result, left, NULL, POINTER);
9699     else {
9700         /* we have can just get the values */
9701       int size = AOP_SIZE(result);
9702       int offset = 0;   
9703         
9704       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9705
9706
9707         /* fsr0 is loaded already -- VR */
9708 //      pic16_loadFSR0( left );
9709
9710 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
9711 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9712       while(size--) {
9713
9714         if(size) {
9715                 pic16_emitpcode(POC_MOVFF,
9716                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
9717                                 pic16_popGet(AOP(result), offset++)));
9718         } else {
9719                 pic16_emitpcode(POC_MOVFF,
9720                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
9721                                 pic16_popGet(AOP(result), offset++)));
9722         }
9723       }
9724 #if 0
9725 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
9726 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
9727         if(size)
9728           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9729 #endif
9730 /*
9731         while (size--) {
9732             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
9733
9734                 pic16_emitcode("mov","a,@%s",rname);
9735                 pic16_aopPut(AOP(result),"a",offset);
9736             } else {
9737                 sprintf(buffer,"@%s",rname);
9738                 pic16_aopPut(AOP(result),buffer,offset);
9739             }
9740             offset++ ;
9741             if (size)
9742                 pic16_emitcode("inc","%s",rname);
9743         }
9744 */
9745     }
9746
9747     /* now some housekeeping stuff */
9748     if (aop) {
9749         /* we had to allocate for this iCode */
9750     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9751         pic16_freeAsmop(NULL,aop,ic,TRUE);
9752     } else { 
9753         /* we did not allocate which means left
9754            already in a pointer register, then
9755            if size > 0 && this could be used again
9756            we have to point it back to where it 
9757            belongs */
9758     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9759         if (AOP_SIZE(result) > 1 &&
9760             !OP_SYMBOL(left)->remat &&
9761             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9762               ic->depth )) {
9763 //          int size = AOP_SIZE(result) - 1;
9764 //          while (size--)
9765 //              pic16_emitcode("dec","%s",rname);
9766         }
9767     }
9768
9769     /* done */
9770     pic16_freeAsmop(left,NULL,ic,TRUE);
9771     pic16_freeAsmop(result,NULL,ic,TRUE);
9772      
9773 }
9774
9775 /*-----------------------------------------------------------------*/
9776 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
9777 /*-----------------------------------------------------------------*/
9778 static void genPagedPointerGet (operand *left, 
9779                                operand *result, 
9780                                iCode *ic)
9781 {
9782     asmop *aop = NULL;
9783     regs *preg = NULL ;
9784     char *rname ;
9785     sym_link *rtype, *retype;    
9786
9787     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9788
9789     rtype = operandType(result);
9790     retype= getSpec(rtype);
9791     
9792     pic16_aopOp(left,ic,FALSE);
9793
9794   /* if the value is already in a pointer register
9795        then don't need anything more */
9796     if (!AOP_INPREG(AOP(left))) {
9797         /* otherwise get a free pointer register */
9798         aop = newAsmop(0);
9799         preg = getFreePtr(ic,&aop,FALSE);
9800         pic16_emitcode("mov","%s,%s",
9801                 preg->name,
9802                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
9803         rname = preg->name ;
9804     } else
9805         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9806     
9807     pic16_freeAsmop(left,NULL,ic,TRUE);
9808     pic16_aopOp (result,ic,FALSE);
9809
9810     /* if bitfield then unpack the bits */
9811     if (IS_BITFIELD(retype)) 
9812         genUnpackBits (result,left,rname,PPOINTER);
9813     else {
9814         /* we have can just get the values */
9815         int size = AOP_SIZE(result);
9816         int offset = 0 ;        
9817         
9818         while (size--) {
9819             
9820             pic16_emitcode("movx","a,@%s",rname);
9821             pic16_aopPut(AOP(result),"a",offset);
9822             
9823             offset++ ;
9824             
9825             if (size)
9826                 pic16_emitcode("inc","%s",rname);
9827         }
9828     }
9829
9830     /* now some housekeeping stuff */
9831     if (aop) {
9832         /* we had to allocate for this iCode */
9833         pic16_freeAsmop(NULL,aop,ic,TRUE);
9834     } else { 
9835         /* we did not allocate which means left
9836            already in a pointer register, then
9837            if size > 0 && this could be used again
9838            we have to point it back to where it 
9839            belongs */
9840         if (AOP_SIZE(result) > 1 &&
9841             !OP_SYMBOL(left)->remat &&
9842             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9843               ic->depth )) {
9844             int size = AOP_SIZE(result) - 1;
9845             while (size--)
9846                 pic16_emitcode("dec","%s",rname);
9847         }
9848     }
9849
9850     /* done */
9851     pic16_freeAsmop(result,NULL,ic,TRUE);
9852     
9853         
9854 }
9855
9856 /*-----------------------------------------------------------------*/
9857 /* genFarPointerGet - gget value from far space                    */
9858 /*-----------------------------------------------------------------*/
9859 static void genFarPointerGet (operand *left,
9860                               operand *result, iCode *ic)
9861 {
9862     int size, offset ;
9863     sym_link *retype = getSpec(operandType(result));
9864
9865     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9866
9867     pic16_aopOp(left,ic,FALSE);
9868
9869     /* if the operand is already in dptr 
9870     then we do nothing else we move the value to dptr */
9871     if (AOP_TYPE(left) != AOP_STR) {
9872         /* if this is remateriazable */
9873         if (AOP_TYPE(left) == AOP_IMMD)
9874             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9875         else { /* we need to get it byte by byte */
9876             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9877             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9878             if (options.model == MODEL_FLAT24)
9879             {
9880                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9881             }
9882         }
9883     }
9884     /* so dptr know contains the address */
9885     pic16_freeAsmop(left,NULL,ic,TRUE);
9886     pic16_aopOp(result,ic,FALSE);
9887
9888     /* if bit then unpack */
9889     if (IS_BITFIELD(retype)) 
9890         genUnpackBits(result,left,"dptr",FPOINTER);
9891     else {
9892         size = AOP_SIZE(result);
9893         offset = 0 ;
9894
9895         while (size--) {
9896             pic16_emitcode("movx","a,@dptr");
9897             pic16_aopPut(AOP(result),"a",offset++);
9898             if (size)
9899                 pic16_emitcode("inc","dptr");
9900         }
9901     }
9902
9903     pic16_freeAsmop(result,NULL,ic,TRUE);
9904 }
9905 #if 0
9906 /*-----------------------------------------------------------------*/
9907 /* genCodePointerGet - get value from code space                  */
9908 /*-----------------------------------------------------------------*/
9909 static void genCodePointerGet (operand *left,
9910                                 operand *result, iCode *ic)
9911 {
9912     int size, offset ;
9913     sym_link *retype = getSpec(operandType(result));
9914
9915     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9916
9917     pic16_aopOp(left,ic,FALSE);
9918
9919     /* if the operand is already in dptr 
9920     then we do nothing else we move the value to dptr */
9921     if (AOP_TYPE(left) != AOP_STR) {
9922         /* if this is remateriazable */
9923         if (AOP_TYPE(left) == AOP_IMMD)
9924             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9925         else { /* we need to get it byte by byte */
9926             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9927             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9928             if (options.model == MODEL_FLAT24)
9929             {
9930                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9931             }
9932         }
9933     }
9934     /* so dptr know contains the address */
9935     pic16_freeAsmop(left,NULL,ic,TRUE);
9936     pic16_aopOp(result,ic,FALSE);
9937
9938     /* if bit then unpack */
9939     if (IS_BITFIELD(retype)) 
9940         genUnpackBits(result,left,"dptr",CPOINTER);
9941     else {
9942         size = AOP_SIZE(result);
9943         offset = 0 ;
9944
9945         while (size--) {
9946             pic16_emitcode("clr","a");
9947             pic16_emitcode("movc","a,@a+dptr");
9948             pic16_aopPut(AOP(result),"a",offset++);
9949             if (size)
9950                 pic16_emitcode("inc","dptr");
9951         }
9952     }
9953
9954     pic16_freeAsmop(result,NULL,ic,TRUE);
9955 }
9956 #endif
9957 #if 0
9958 /*-----------------------------------------------------------------*/
9959 /* genGenPointerGet - gget value from generic pointer space        */
9960 /*-----------------------------------------------------------------*/
9961 static void genGenPointerGet (operand *left,
9962                               operand *result, iCode *ic)
9963 {
9964   int size, offset, lit;
9965   sym_link *retype = getSpec(operandType(result));
9966
9967         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9968         pic16_aopOp(left,ic,FALSE);
9969         pic16_aopOp(result,ic,FALSE);
9970         size = AOP_SIZE(result);
9971
9972         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9973
9974         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9975
9976                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9977                 // load FSR0 from immediate
9978                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9979
9980 //              pic16_loadFSR0( left );
9981
9982                 offset = 0;
9983                 while(size--) {
9984                         if(size) {
9985                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9986                         } else {
9987                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9988                         }
9989                         offset++;
9990                 }
9991                 goto release;
9992
9993         }
9994         else { /* we need to get it byte by byte */
9995                 // set up FSR0 with address from left
9996                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9997                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9998
9999                 offset = 0 ;
10000
10001                 while(size--) {
10002                         if(size) {
10003                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10004                         } else {
10005                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10006                         }
10007                         offset++;
10008                 }
10009                 goto release;
10010         }
10011
10012   /* if bit then unpack */
10013         if (IS_BITFIELD(retype)) 
10014                 genUnpackBits(result,left,"BAD",GPOINTER);
10015
10016         release:
10017         pic16_freeAsmop(left,NULL,ic,TRUE);
10018         pic16_freeAsmop(result,NULL,ic,TRUE);
10019
10020 }
10021 #endif
10022
10023 extern set *externs;
10024
10025 /*-----------------------------------------------------------------*/
10026 /* genGenPointerGet - gget value from generic pointer space        */
10027 /*-----------------------------------------------------------------*/
10028 static void genGenPointerGet (operand *left,
10029                               operand *result, iCode *ic)
10030 {
10031   int size, offset, lit;
10032   sym_link *retype = getSpec(operandType(result));
10033   char fgptrget[32];
10034
10035     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10036     pic16_aopOp(left,ic,FALSE);
10037     pic16_aopOp(result,ic,FALSE);
10038     size = AOP_SIZE(result);
10039
10040     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10041
10042     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
10043
10044       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
10045       // load FSR0 from immediate
10046       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10047
10048       werror(W_POSSBUG2, __FILE__, __LINE__);
10049
10050       offset = 0;
10051       while(size--) {
10052         if(size) {
10053           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10054         } else {
10055           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10056         }
10057         offset++;
10058       }
10059
10060       goto release;
10061
10062     } else { /* we need to get it byte by byte */
10063
10064       /* set up WREG:PRODL:FSR0L with address from left */
10065       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10066       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
10067       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
10068       
10069       switch( size ) {
10070         case 1: strcpy(fgptrget, "__gptrget1"); break;
10071         case 2: strcpy(fgptrget, "__gptrget2"); break;
10072         case 3: strcpy(fgptrget, "__gptrget3"); break;
10073         case 4: strcpy(fgptrget, "__gptrget4"); break;
10074         default:
10075           werror(W_POSSBUG2, __FILE__, __LINE__);
10076           abort();
10077       }
10078       
10079       pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
10080       
10081       assignResultValue(result, 1);
10082       
10083       {
10084         symbol *sym;
10085
10086           sym = newSymbol( fgptrget, 0 );
10087           strcpy(sym->rname, fgptrget);
10088           checkAddSym(&externs, sym);
10089
10090 //          fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
10091       }
10092               
10093       goto release;
10094     }
10095
10096   /* if bit then unpack */
10097     if (IS_BITFIELD(retype)) 
10098       genUnpackBits(result,left,"BAD",GPOINTER);
10099
10100 release:
10101   pic16_freeAsmop(left,NULL,ic,TRUE);
10102   pic16_freeAsmop(result,NULL,ic,TRUE);
10103 }
10104
10105 /*-----------------------------------------------------------------*/
10106 /* genConstPointerGet - get value from const generic pointer space */
10107 /*-----------------------------------------------------------------*/
10108 static void genConstPointerGet (operand *left,
10109                                 operand *result, iCode *ic)
10110 {
10111   //sym_link *retype = getSpec(operandType(result));
10112   // symbol *albl = newiTempLabel(NULL);        // patch 15
10113   // symbol *blbl = newiTempLabel(NULL);        //
10114   // PIC_OPCODE poc;                            // patch 15
10115   int size;
10116   int offset = 0;
10117
10118   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10119   pic16_aopOp(left,ic,FALSE);
10120   pic16_aopOp(result,ic,TRUE);
10121   size = AOP_SIZE(result);
10122
10123   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10124
10125   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
10126 #if 0                                                                   // patch 15
10127   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
10128   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
10129   pic16_emitpLabel(albl->key);
10130
10131   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
10132   
10133   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
10134   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
10135   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
10136   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
10137   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
10138
10139   pic16_emitpLabel(blbl->key);
10140
10141   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
10142 #endif                                                                  // patch 15
10143
10144
10145   // set up table pointer
10146   if( (AOP_TYPE(left) == AOP_PCODE) 
10147       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
10148           || (AOP(left)->aopu.pcop->type == PO_DIR)))                   // patch 15 ......
10149     {
10150       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
10151       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
10152       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
10153       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
10154       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
10155       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
10156     }
10157   else
10158     {
10159       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
10160       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
10161       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
10162     }
10163
10164
10165   while(size--)
10166     {
10167       pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
10168       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
10169       offset++;
10170     }
10171     
10172   pic16_freeAsmop(left,NULL,ic,TRUE);
10173   pic16_freeAsmop(result,NULL,ic,TRUE);
10174
10175 }
10176
10177
10178 /*-----------------------------------------------------------------*/
10179 /* genPointerGet - generate code for pointer get                   */
10180 /*-----------------------------------------------------------------*/
10181 static void genPointerGet (iCode *ic)
10182 {
10183     operand *left, *result ;
10184     sym_link *type, *etype;
10185     int p_type;
10186
10187     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10188
10189     left = IC_LEFT(ic);
10190     result = IC_RESULT(ic) ;
10191
10192     /* depending on the type of pointer we need to
10193     move it to the correct pointer register */
10194     type = operandType(left);
10195     etype = getSpec(type);
10196
10197 #if 0
10198     if (IS_PTR_CONST(type))
10199 #else
10200     if (IS_CODEPTR(type))
10201 #endif
10202       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
10203
10204     /* if left is of type of pointer then it is simple */
10205     if (IS_PTR(type) && !IS_FUNC(type->next)) 
10206         p_type = DCL_TYPE(type);
10207     else {
10208         /* we have to go by the storage class */
10209         p_type = PTR_TYPE(SPEC_OCLS(etype));
10210
10211         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
10212
10213         if (SPEC_OCLS(etype)->codesp ) {
10214           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
10215           //p_type = CPOINTER ; 
10216         }
10217         else
10218             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
10219               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
10220                /*p_type = FPOINTER ;*/ 
10221             else
10222                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
10223                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
10224 /*                  p_type = PPOINTER; */
10225                 else
10226                     if (SPEC_OCLS(etype) == idata )
10227                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
10228 /*                      p_type = IPOINTER; */
10229                     else
10230                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
10231 /*                      p_type = POINTER ; */
10232     }
10233
10234     /* now that we have the pointer type we assign
10235     the pointer values */
10236     switch (p_type) {
10237
10238     case POINTER:       
10239     case IPOINTER:
10240         genNearPointerGet (left,result,ic);
10241         break;
10242
10243     case PPOINTER:
10244         genPagedPointerGet(left,result,ic);
10245         break;
10246
10247     case FPOINTER:
10248         genFarPointerGet (left,result,ic);
10249         break;
10250
10251     case CPOINTER:
10252         genConstPointerGet (left,result,ic);
10253         //pic16_emitcodePointerGet (left,result,ic);
10254         break;
10255
10256     case GPOINTER:
10257 #if 0
10258       if (IS_PTR_CONST(type))
10259         genConstPointerGet (left,result,ic);
10260       else
10261 #endif
10262         genGenPointerGet (left,result,ic);
10263       break;
10264
10265     default:
10266       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10267               "genPointerGet: illegal pointer type");
10268     
10269     }
10270
10271 }
10272
10273 /*-----------------------------------------------------------------*/
10274 /* genPackBits - generates code for packed bit storage             */
10275 /*-----------------------------------------------------------------*/
10276 static void genPackBits (sym_link    *etype , operand *result,
10277                          operand *right ,
10278                          char *rname, int p_type)
10279 {
10280   int shCnt = 0 ;
10281   int offset = 0  ;
10282   int rLen = 0 ;
10283   int blen, bstr ;   
10284   char *l ;
10285
10286         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10287         blen = SPEC_BLEN(etype);
10288         bstr = SPEC_BSTR(etype);
10289
10290         if(AOP_TYPE(right) == AOP_LIT) {
10291                 if((blen == 1) && (bstr < 8)) {
10292                   unsigned long lit;
10293                         /* it is a single bit, so use the appropriate bit instructions */
10294
10295                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
10296
10297                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10298 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10299                         if((p_type == POINTER) && (result)) {
10300                                 /* workaround to reduce the extra lfsr instruction */
10301                                 if(lit) {
10302                                         pic16_emitpcode(POC_BSF,
10303                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
10304                                 } else {
10305                                         pic16_emitpcode(POC_BCF,
10306                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
10307                                 }
10308                         } else {
10309
10310                                 if(lit) {
10311                                         pic16_emitpcode(POC_BSF,
10312                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10313                                 } else {
10314                                         pic16_emitpcode(POC_BCF,
10315                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10316                                 }
10317                         }
10318         
10319                   return;
10320                 }
10321
10322                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
10323                 offset++;
10324         } else
10325                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
10326
10327         /* if the bit lenth is less than or    */
10328         /* it exactly fits a byte then         */
10329         if((shCnt=SPEC_BSTR(etype))
10330                 || SPEC_BLEN(etype) <= 8 )  {
10331
10332                 /* shift left acc */
10333                 AccLsh(shCnt);
10334
10335                 /* using PRODL as a temporary register here */
10336                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
10337
10338                 switch (p_type) {
10339                         case FPOINTER:
10340                         case POINTER:
10341                         case GPOINTER:
10342                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10343 //                              pic16_emitcode ("mov","b,a");
10344 //                              pic16_emitcode("mov","a,@%s",rname);
10345                                 break;
10346                 }
10347 #if 1
10348                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10349                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
10350                                         (unsigned char)(0xff >> (8-bstr))) ));
10351                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
10352                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10353 #endif
10354
10355           return;
10356         }
10357
10358
10359         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10360         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10361         exit(-1);
10362
10363
10364     /* if we r done */
10365     if ( SPEC_BLEN(etype) <= 8 )
10366         return ;
10367
10368     pic16_emitcode("inc","%s",rname);
10369     rLen = SPEC_BLEN(etype) ;     
10370
10371
10372
10373     /* now generate for lengths greater than one byte */
10374     while (1) {
10375
10376         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
10377
10378         rLen -= 8 ;
10379         if (rLen <= 0 )
10380             break ;
10381
10382         switch (p_type) {
10383             case POINTER:
10384                 if (*l == '@') {
10385                     MOVA(l);
10386                     pic16_emitcode("mov","@%s,a",rname);
10387                 } else
10388                     pic16_emitcode("mov","@%s,%s",rname,l);
10389                 break;
10390
10391             case FPOINTER:
10392                 MOVA(l);
10393                 pic16_emitcode("movx","@dptr,a");
10394                 break;
10395
10396             case GPOINTER:
10397                 MOVA(l);
10398                 DEBUGpic16_emitcode(";lcall","__gptrput");
10399                 break;  
10400         }   
10401         pic16_emitcode ("inc","%s",rname);
10402     }
10403
10404     MOVA(l);
10405
10406     /* last last was not complete */
10407     if (rLen)   {
10408         /* save the byte & read byte */
10409         switch (p_type) {
10410             case POINTER:
10411                 pic16_emitcode ("mov","b,a");
10412                 pic16_emitcode("mov","a,@%s",rname);
10413                 break;
10414
10415             case FPOINTER:
10416                 pic16_emitcode ("mov","b,a");
10417                 pic16_emitcode("movx","a,@dptr");
10418                 break;
10419
10420             case GPOINTER:
10421                 pic16_emitcode ("push","b");
10422                 pic16_emitcode ("push","acc");
10423                 pic16_emitcode ("lcall","__gptrget");
10424                 pic16_emitcode ("pop","b");
10425                 break;
10426         }
10427
10428         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
10429         pic16_emitcode ("orl","a,b");
10430     }
10431
10432     if (p_type == GPOINTER)
10433         pic16_emitcode("pop","b");
10434
10435     switch (p_type) {
10436
10437     case POINTER:
10438         pic16_emitcode("mov","@%s,a",rname);
10439         break;
10440         
10441     case FPOINTER:
10442         pic16_emitcode("movx","@dptr,a");
10443         break;
10444         
10445     case GPOINTER:
10446         DEBUGpic16_emitcode(";lcall","__gptrput");
10447         break;                  
10448     }
10449 }
10450 /*-----------------------------------------------------------------*/
10451 /* genDataPointerSet - remat pointer to data space                 */
10452 /*-----------------------------------------------------------------*/
10453 static void genDataPointerSet(operand *right,
10454                               operand *result,
10455                               iCode *ic)
10456 {
10457     int size, offset = 0, resoffset=0 ;
10458
10459     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10460     pic16_aopOp(right,ic,FALSE);
10461
10462     size = AOP_SIZE(right);
10463
10464 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10465
10466 #if 0
10467     if ( AOP_TYPE(result) == AOP_PCODE) {
10468       fprintf(stderr,"genDataPointerSet   %s, %d\n",
10469               AOP(result)->aopu.pcop->name,
10470                 (AOP(result)->aopu.pcop->type == PO_DIR)?
10471               PCOR(AOP(result)->aopu.pcop)->instance:
10472               PCOI(AOP(result)->aopu.pcop)->offset);
10473     }
10474 #endif
10475
10476         if(AOP(result)->aopu.pcop->type == PO_DIR)
10477                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
10478
10479         while (size--) {
10480                 if (AOP_TYPE(right) == AOP_LIT) {
10481                   unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
10482
10483                         lit = lit >> (8*offset);
10484                         if(lit&0xff) {
10485                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
10486                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
10487                         } else {
10488                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
10489                         }
10490                 } else {
10491                         mov2w(AOP(right), offset);
10492                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
10493                 }
10494                 offset++;
10495                 resoffset++;
10496         }
10497
10498     pic16_freeAsmop(right,NULL,ic,TRUE);
10499 }
10500
10501
10502
10503 /*-----------------------------------------------------------------*/
10504 /* genNearPointerSet - pic16_emitcode for near pointer put         */
10505 /*-----------------------------------------------------------------*/
10506 static void genNearPointerSet (operand *right,
10507                                operand *result, 
10508                                iCode *ic)
10509 {
10510   asmop *aop = NULL;
10511   char *l;
10512   sym_link *retype;
10513   sym_link *ptype = operandType(result);
10514   sym_link *resetype;
10515     
10516         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10517         retype= getSpec(operandType(right));
10518         resetype = getSpec(operandType(result));
10519   
10520         pic16_aopOp(result,ic,FALSE);
10521     
10522         /* if the result is rematerializable &
10523          * in data space & not a bit variable */
10524         
10525         /* and result is not a bit variable */
10526         if (AOP_TYPE(result) == AOP_PCODE
10527 //              && AOP_TYPE(result) == AOP_IMMD
10528                 && DCL_TYPE(ptype) == POINTER
10529                 && !IS_BITFIELD(retype)
10530                 && !IS_BITFIELD(resetype)) {
10531
10532                 genDataPointerSet (right,result,ic);
10533                 pic16_freeAsmop(result,NULL,ic,TRUE);
10534           return;
10535         }
10536
10537         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10538         pic16_aopOp(right,ic,FALSE);
10539         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10540
10541         /* if the value is already in a pointer register
10542          * then don't need anything more */
10543         if (!AOP_INPREG(AOP(result))) {
10544                 /* otherwise get a free pointer register */
10545                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10546
10547                 if( (AOP_TYPE(result) == AOP_PCODE) 
10548                         && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
10549                                 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
10550                 {
10551                   if(!IS_BITFIELD(resetype))
10552                         pic16_loadFSR0( result );  // patch 10
10553                 } else {
10554                         // set up FSR0 with address of result
10555                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10556                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10557                 }
10558
10559         }
10560 //      else
10561 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10562
10563         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10564
10565         /* if bitfield then unpack the bits */
10566         if (IS_BITFIELD(resetype)) {
10567                 genPackBits (resetype, result, right, NULL, POINTER);
10568         } else {
10569                 /* we have can just get the values */
10570           int size = AOP_SIZE(right);
10571           int offset = 0 ;    
10572
10573                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10574                 while (size--) {
10575                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10576                         if (*l == '@' ) {
10577                                 //MOVA(l);
10578                                 //pic16_emitcode("mov","@%s,a",rname);
10579                                 pic16_emitcode("movf","indf0,w ;1");
10580                         } else {
10581
10582                                 if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
10583                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
10584                                         if (size) {                                                                     // 
10585                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
10586                                         } else {                                                                        // 
10587                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
10588                                         }                                                                               // 
10589                                 } else { // no literal                                                                  // 
10590                                         if(size) {                                                                      // 
10591                                                 pic16_emitpcode(POC_MOVFF,                                              // 
10592                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
10593                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));         // 
10594                                         } else {                                                                        // 
10595                                                 pic16_emitpcode(POC_MOVFF,                                              // 
10596                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
10597                                                                         pic16_popCopyReg(&pic16_pc_indf0)));            //
10598                                         }                                                                               //
10599                                 }                                                                                       // patch 10
10600                         }
10601                         offset++;
10602                 }
10603         }
10604
10605         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10606         /* now some housekeeping stuff */
10607         if (aop) {
10608                 /* we had to allocate for this iCode */
10609                 pic16_freeAsmop(NULL,aop,ic,TRUE);
10610         } else { 
10611                 /* we did not allocate which means left
10612                  * already in a pointer register, then
10613                  * if size > 0 && this could be used again
10614                  * we have to point it back to where it 
10615                  * belongs */
10616                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10617                 if (AOP_SIZE(right) > 1
10618                         && !OP_SYMBOL(result)->remat
10619                         && ( OP_SYMBOL(result)->liveTo > ic->seq
10620                                 || ic->depth )) {
10621
10622                   int size = AOP_SIZE(right) - 1;
10623
10624                         while (size--)
10625                                 pic16_emitcode("decf","fsr0,f");
10626                         //pic16_emitcode("dec","%s",rname);
10627                 }
10628         }
10629
10630         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10631         /* done */
10632 //release:
10633         pic16_freeAsmop(right,NULL,ic,TRUE);
10634         pic16_freeAsmop(result,NULL,ic,TRUE);
10635 }
10636
10637 /*-----------------------------------------------------------------*/
10638 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
10639 /*-----------------------------------------------------------------*/
10640 static void genPagedPointerSet (operand *right,
10641                                operand *result, 
10642                                iCode *ic)
10643 {
10644     asmop *aop = NULL;
10645     regs *preg = NULL ;
10646     char *rname , *l;
10647     sym_link *retype;
10648        
10649     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10650
10651     retype= getSpec(operandType(right));
10652     
10653     pic16_aopOp(result,ic,FALSE);
10654     
10655     /* if the value is already in a pointer register
10656        then don't need anything more */
10657     if (!AOP_INPREG(AOP(result))) {
10658         /* otherwise get a free pointer register */
10659         aop = newAsmop(0);
10660         preg = getFreePtr(ic,&aop,FALSE);
10661         pic16_emitcode("mov","%s,%s",
10662                 preg->name,
10663                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
10664         rname = preg->name ;
10665     } else
10666         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10667     
10668     pic16_freeAsmop(result,NULL,ic,TRUE);
10669     pic16_aopOp (right,ic,FALSE);
10670
10671     /* if bitfield then unpack the bits */
10672     if (IS_BITFIELD(retype)) 
10673         genPackBits (retype,result,right,rname,PPOINTER);
10674     else {
10675         /* we have can just get the values */
10676         int size = AOP_SIZE(right);
10677         int offset = 0 ;        
10678         
10679         while (size--) {
10680             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10681             
10682             MOVA(l);
10683             pic16_emitcode("movx","@%s,a",rname);
10684
10685             if (size)
10686                 pic16_emitcode("inc","%s",rname);
10687
10688             offset++;
10689         }
10690     }
10691     
10692     /* now some housekeeping stuff */
10693     if (aop) {
10694         /* we had to allocate for this iCode */
10695         pic16_freeAsmop(NULL,aop,ic,TRUE);
10696     } else { 
10697         /* we did not allocate which means left
10698            already in a pointer register, then
10699            if size > 0 && this could be used again
10700            we have to point it back to where it 
10701            belongs */
10702         if (AOP_SIZE(right) > 1 &&
10703             !OP_SYMBOL(result)->remat &&
10704             ( OP_SYMBOL(result)->liveTo > ic->seq ||
10705               ic->depth )) {
10706             int size = AOP_SIZE(right) - 1;
10707             while (size--)
10708                 pic16_emitcode("dec","%s",rname);
10709         }
10710     }
10711
10712     /* done */
10713     pic16_freeAsmop(right,NULL,ic,TRUE);
10714     
10715         
10716 }
10717
10718 /*-----------------------------------------------------------------*/
10719 /* genFarPointerSet - set value from far space                     */
10720 /*-----------------------------------------------------------------*/
10721 static void genFarPointerSet (operand *right,
10722                               operand *result, iCode *ic)
10723 {
10724     int size, offset ;
10725     sym_link *retype = getSpec(operandType(right));
10726
10727     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10728     pic16_aopOp(result,ic,FALSE);
10729
10730     /* if the operand is already in dptr 
10731     then we do nothing else we move the value to dptr */
10732     if (AOP_TYPE(result) != AOP_STR) {
10733         /* if this is remateriazable */
10734         if (AOP_TYPE(result) == AOP_IMMD)
10735             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
10736         else { /* we need to get it byte by byte */
10737             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
10738             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
10739             if (options.model == MODEL_FLAT24)
10740             {
10741                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
10742             }
10743         }
10744     }
10745     /* so dptr know contains the address */
10746     pic16_freeAsmop(result,NULL,ic,TRUE);
10747     pic16_aopOp(right,ic,FALSE);
10748
10749     /* if bit then unpack */
10750     if (IS_BITFIELD(retype)) 
10751         genPackBits(retype,result,right,"dptr",FPOINTER);
10752     else {
10753         size = AOP_SIZE(right);
10754         offset = 0 ;
10755
10756         while (size--) {
10757             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10758             MOVA(l);
10759             pic16_emitcode("movx","@dptr,a");
10760             if (size)
10761                 pic16_emitcode("inc","dptr");
10762         }
10763     }
10764
10765     pic16_freeAsmop(right,NULL,ic,TRUE);
10766 }
10767
10768 /*-----------------------------------------------------------------*/
10769 /* genGenPointerSet - set value from generic pointer space         */
10770 /*-----------------------------------------------------------------*/
10771 #if 0
10772 static void genGenPointerSet (operand *right,
10773                               operand *result, iCode *ic)
10774 {
10775         int i, size, offset, lit;
10776         sym_link *retype = getSpec(operandType(right));
10777
10778         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10779
10780         pic16_aopOp(result,ic,FALSE);
10781         pic16_aopOp(right,ic,FALSE);
10782         size = AOP_SIZE(right);
10783         offset = 0;
10784
10785         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10786
10787         /* if the operand is already in dptr 
10788                 then we do nothing else we move the value to dptr */
10789         if (AOP_TYPE(result) != AOP_STR) {
10790                 /* if this is remateriazable */
10791                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10792                 // WARNING: anythig until "else" is untested!
10793                 if (AOP_TYPE(result) == AOP_IMMD) {
10794                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10795                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
10796                         // load FSR0 from immediate
10797                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10798                         offset = 0;
10799                         while(size--) {
10800                                 if(size) {
10801                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10802                                 } else {
10803                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10804                                 }
10805                                 offset++;
10806                         }
10807                         goto release;
10808                 }
10809                 else { /* we need to get it byte by byte */
10810                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10811                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10812
10813                         // set up FSR0 with address of result
10814                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10815                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10816
10817                         /* hack hack! see if this the FSR. If so don't load W */
10818                         if(AOP_TYPE(right) != AOP_ACC) {
10819
10820                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10821
10822                                 if(AOP_TYPE(right) == AOP_LIT)
10823                                 {
10824                                         // copy literal
10825                                         // note: pic16_popGet handles sign extension
10826                                         for(i=0;i<size;i++) {
10827                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
10828                                                 if(i < size-1)
10829                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
10830                                                 else
10831                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10832                                         }
10833                                 } else {
10834                                         // copy regs
10835
10836                                         for(i=0;i<size;i++) {
10837                                                 if(i < size-1)
10838                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10839                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
10840                                                 else
10841                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10842                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
10843                                         }
10844                                 }
10845                                 goto release;
10846                         } 
10847                         // right = ACC
10848                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10849                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10850                         goto release;
10851         } // if (AOP_TYPE(result) != AOP_IMMD)
10852
10853         } // if (AOP_TYPE(result) != AOP_STR)
10854         /* so dptr know contains the address */
10855
10856
10857         /* if bit then unpack */
10858         if (IS_BITFIELD(retype)) 
10859                 genPackBits(retype,result,right,"dptr",GPOINTER);
10860         else {
10861                 size = AOP_SIZE(right);
10862                 offset = 0 ;
10863
10864                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
10865
10866                 // set up FSR0 with address of result
10867                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10868                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10869         
10870                 while (size--) {
10871                         if (AOP_TYPE(right) == AOP_LIT) {
10872                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10873                                 if (size) {
10874                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
10875                                 } else {
10876                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10877                                 }
10878                         } else { // no literal
10879                                 if(size) {
10880                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10881                                 } else {
10882                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10883                                 }
10884                         }
10885                         offset++;
10886                 }
10887         }
10888
10889         release:
10890         pic16_freeAsmop(right,NULL,ic,TRUE);
10891         pic16_freeAsmop(result,NULL,ic,TRUE);
10892 }
10893 #endif
10894
10895 static void genGenPointerSet (operand *right,
10896                               operand *result, iCode *ic)
10897 {
10898   int size;
10899   sym_link *retype = getSpec(operandType(right));
10900   char fgptrput[32];
10901
10902     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10903
10904     pic16_aopOp(result,ic,FALSE);
10905     pic16_aopOp(right,ic,FALSE);
10906     size = AOP_SIZE(right);
10907
10908     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10909
10910
10911     /* if bit then unpack */
10912     if (IS_BITFIELD(retype)) {
10913 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10914       genPackBits(retype,result,right,"dptr",GPOINTER);
10915       goto release;
10916     }
10917
10918     size = AOP_SIZE(right);
10919
10920     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
10921
10922
10923
10924     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
10925
10926     /* value of right+0 is placed on stack, which will be retrieved
10927      * by the support function this restoring the stack. The important
10928      * thing is that there is no need to manually restore stack pointer
10929      * here */
10930     mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
10931     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
10932     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
10933     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
10934     
10935     /* load address to write to in WREG:FSR0H:FSR0L */
10936     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
10937                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
10938     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
10939                                 pic16_popCopyReg(&pic16_pc_prodl)));
10940     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
10941     
10942
10943     /* put code here */
10944     switch (size) {
10945       case 1: strcpy(fgptrput, "__gptrput1"); break;
10946       case 2: strcpy(fgptrput, "__gptrput2"); break;
10947       case 3: strcpy(fgptrput, "__gptrput3"); break;
10948       case 4: strcpy(fgptrput, "__gptrput4"); break;
10949       default:
10950         werror(W_POSSBUG2, __FILE__, __LINE__);
10951         abort();
10952     }
10953     
10954     pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
10955     
10956     {
10957       symbol *sym;
10958                   
10959         sym = newSymbol( fgptrput, 0 );
10960         strcpy(sym->rname, fgptrput);
10961         checkAddSym(&externs, sym);
10962
10963 #if 0
10964         sym = newSymbol("__GPTRREG", 0);
10965         strcpy(sym->rname, "__GPTRREG");
10966         checkAddSym(&externs, sym);
10967 #endif
10968
10969 //          fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
10970     }
10971
10972 release:
10973     pic16_freeAsmop(right,NULL,ic,TRUE);
10974     pic16_freeAsmop(result,NULL,ic,TRUE);
10975 }
10976
10977 /*-----------------------------------------------------------------*/
10978 /* genPointerSet - stores the value into a pointer location        */
10979 /*-----------------------------------------------------------------*/
10980 static void genPointerSet (iCode *ic)
10981 {    
10982     operand *right, *result ;
10983     sym_link *type, *etype;
10984     int p_type;
10985
10986     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10987
10988     right = IC_RIGHT(ic);
10989     result = IC_RESULT(ic) ;
10990
10991     /* depending on the type of pointer we need to
10992     move it to the correct pointer register */
10993     type = operandType(result);
10994     etype = getSpec(type);
10995     /* if left is of type of pointer then it is simple */
10996     if (IS_PTR(type) && !IS_FUNC(type->next)) {
10997         p_type = DCL_TYPE(type);
10998     }
10999     else {
11000         /* we have to go by the storage class */
11001         p_type = PTR_TYPE(SPEC_OCLS(etype));
11002
11003 /*      if (SPEC_OCLS(etype)->codesp ) { */
11004 /*          p_type = CPOINTER ;  */
11005 /*      } */
11006 /*      else */
11007 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11008 /*              p_type = FPOINTER ; */
11009 /*          else */
11010 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11011 /*                  p_type = PPOINTER ; */
11012 /*              else */
11013 /*                  if (SPEC_OCLS(etype) == idata ) */
11014 /*                      p_type = IPOINTER ; */
11015 /*                  else */
11016 /*                      p_type = POINTER ; */
11017     }
11018
11019     /* now that we have the pointer type we assign
11020     the pointer values */
11021     switch (p_type) {
11022
11023     case POINTER:
11024     case IPOINTER:
11025         genNearPointerSet (right,result,ic);
11026         break;
11027
11028     case PPOINTER:
11029         genPagedPointerSet (right,result,ic);
11030         break;
11031
11032     case FPOINTER:
11033         genFarPointerSet (right,result,ic);
11034         break;
11035
11036     case GPOINTER:
11037         genGenPointerSet (right,result,ic);
11038         break;
11039
11040     default:
11041       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11042               "genPointerSet: illegal pointer type");
11043     }
11044 }
11045
11046 /*-----------------------------------------------------------------*/
11047 /* genIfx - generate code for Ifx statement                        */
11048 /*-----------------------------------------------------------------*/
11049 static void genIfx (iCode *ic, iCode *popIc)
11050 {
11051   operand *cond = IC_COND(ic);
11052   int isbit =0;
11053
11054   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11055
11056   pic16_aopOp(cond,ic,FALSE);
11057
11058   /* get the value into acc */
11059   if (AOP_TYPE(cond) != AOP_CRY)
11060     pic16_toBoolean(cond);
11061   else
11062     isbit = 1;
11063   /* the result is now in the accumulator */
11064   pic16_freeAsmop(cond,NULL,ic,TRUE);
11065
11066   /* if there was something to be popped then do it */
11067   if (popIc)
11068     genIpop(popIc);
11069
11070   /* if the condition is  a bit variable */
11071   if (isbit && IS_ITEMP(cond) && 
11072       SPIL_LOC(cond)) {
11073     genIfxJump(ic,SPIL_LOC(cond)->rname);
11074     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
11075   }
11076   else {
11077     if (isbit && !IS_ITEMP(cond))
11078       genIfxJump(ic,OP_SYMBOL(cond)->rname);
11079     else
11080       genIfxJump(ic,"a");
11081   }
11082   ic->generated = 1;
11083
11084 }
11085
11086 /*-----------------------------------------------------------------*/
11087 /* genAddrOf - generates code for address of                       */
11088 /*-----------------------------------------------------------------*/
11089 static void genAddrOf (iCode *ic)
11090 {
11091   operand *result, *left;
11092   int size;
11093   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
11094   pCodeOp *pcop0, *pcop1, *pcop2;
11095
11096     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11097
11098     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
11099
11100     sym = OP_SYMBOL( IC_LEFT(ic) );
11101     
11102     if(sym->onStack) {
11103       /* get address of symbol on stack */
11104       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
11105 #if 0
11106       fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
11107                   OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
11108 #endif
11109
11110       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11111                       pic16_popCopyReg(&pic16_pc_fsr2l),
11112                       pic16_popGet(AOP(result), 0)));
11113       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11114                       pic16_popCopyReg(&pic16_pc_fsr2h),
11115                       pic16_popGet(AOP(result), 1)));
11116       
11117       pic16_emitpcode(POC_MOVLW, pic16_popGetLit( OP_SYMBOL( IC_LEFT(ic))->stack ) /*+ _G.stack_lat*/);
11118       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 0));
11119       emitSKPNC;
11120       pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 1));
11121
11122       goto release;
11123     }
11124         
11125 //      if(pic16_debug_verbose) {
11126 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
11127 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
11128 //      }
11129         
11130     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
11131     size = AOP_SIZE(IC_RESULT(ic));
11132
11133
11134     /* Assume that what we want the address of is in data space
11135      * since there is no stack on the PIC, yet! -- VR */
11136   
11137     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11138     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11139     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11140         
11141     if (size == 3) {
11142       pic16_emitpcode(POC_MOVLW, pcop0);
11143       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11144       pic16_emitpcode(POC_MOVLW, pcop1);
11145       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
11146       pic16_emitpcode(POC_MOVLW, pcop2);
11147       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
11148     } else
11149     if (size == 2) {
11150       pic16_emitpcode(POC_MOVLW, pcop0);
11151       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11152       pic16_emitpcode(POC_MOVLW, pcop1);
11153     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11154     } else {
11155       pic16_emitpcode(POC_MOVLW, pcop0);
11156       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11157     }
11158
11159     pic16_freeAsmop(left, NULL, ic, FALSE);
11160 release:
11161     pic16_freeAsmop(result,NULL,ic,TRUE);
11162 }
11163
11164
11165 #if 0
11166 /*-----------------------------------------------------------------*/
11167 /* genFarFarAssign - assignment when both are in far space         */
11168 /*-----------------------------------------------------------------*/
11169 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
11170 {
11171     int size = AOP_SIZE(right);
11172     int offset = 0;
11173     char *l ;
11174     /* first push the right side on to the stack */
11175     while (size--) {
11176         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11177         MOVA(l);
11178         pic16_emitcode ("push","acc");
11179     }
11180     
11181     pic16_freeAsmop(right,NULL,ic,FALSE);
11182     /* now assign DPTR to result */
11183     pic16_aopOp(result,ic,FALSE);
11184     size = AOP_SIZE(result);
11185     while (size--) {
11186         pic16_emitcode ("pop","acc");
11187         pic16_aopPut(AOP(result),"a",--offset);
11188     }
11189     pic16_freeAsmop(result,NULL,ic,FALSE);
11190         
11191 }
11192 #endif
11193
11194 /*-----------------------------------------------------------------*/
11195 /* genAssign - generate code for assignment                        */
11196 /*-----------------------------------------------------------------*/
11197 static void genAssign (iCode *ic)
11198 {
11199   operand *result, *right;
11200   int size, offset,know_W;
11201   unsigned long lit = 0L;
11202
11203   result = IC_RESULT(ic);
11204   right  = IC_RIGHT(ic) ;
11205
11206   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11207   
11208   /* if they are the same */
11209   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
11210     return ;
11211
11212   /* reversed order operands are aopOp'ed so that result operand
11213    * is effective in case right is a stack symbol. This maneauver
11214    * allows to use the _G.resDirect flag later */
11215   pic16_aopOp(result,ic,TRUE);
11216   pic16_aopOp(right,ic,FALSE);
11217
11218   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11219
11220   /* if they are the same registers */
11221   if (pic16_sameRegs(AOP(right),AOP(result)))
11222     goto release;
11223
11224   /* if the result is a bit */
11225   if (AOP_TYPE(result) == AOP_CRY) {
11226     /* if the right size is a literal then
11227        we know what the value is */
11228     if (AOP_TYPE(right) == AOP_LIT) {
11229           
11230       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
11231                   pic16_popGet(AOP(result),0));
11232
11233       if (((int) operandLitValue(right))) 
11234         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
11235                        AOP(result)->aopu.aop_dir,
11236                        AOP(result)->aopu.aop_dir);
11237       else
11238         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
11239                        AOP(result)->aopu.aop_dir,
11240                        AOP(result)->aopu.aop_dir);
11241       goto release;
11242     }
11243
11244     /* the right is also a bit variable */
11245     if (AOP_TYPE(right) == AOP_CRY) {
11246       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
11247       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
11248       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
11249
11250       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
11251                      AOP(result)->aopu.aop_dir,
11252                      AOP(result)->aopu.aop_dir);
11253       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
11254                      AOP(right)->aopu.aop_dir,
11255                      AOP(right)->aopu.aop_dir);
11256       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
11257                      AOP(result)->aopu.aop_dir,
11258                      AOP(result)->aopu.aop_dir);
11259       goto release ;
11260     }
11261
11262     /* we need to or */
11263     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
11264     pic16_toBoolean(right);
11265     emitSKPZ;
11266     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
11267     //pic16_aopPut(AOP(result),"a",0);
11268     goto release ;
11269   }
11270
11271   /* bit variables done */
11272   /* general case */
11273   size = AOP_SIZE(result);
11274   offset = 0 ;
11275
11276   if(AOP_TYPE(right) == AOP_LIT) {
11277         if(!IS_FLOAT(operandType( right )))
11278                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11279         else {
11280            union {
11281               unsigned long lit_int;
11282               float lit_float;
11283             } info;
11284         
11285                 /* take care if literal is a float */
11286                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
11287                 lit = info.lit_int;
11288         }
11289   }
11290
11291 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
11292 //                      sizeof(unsigned long int), sizeof(float));
11293
11294   if(AOP_TYPE(right) != AOP_LIT
11295         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))) {
11296         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
11297         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
11298
11299         // set up table pointer
11300         if( (AOP_TYPE(right) == AOP_PCODE)
11301                 && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE)
11302                 || (AOP(right)->aopu.pcop->type == PO_DIR)))
11303         {
11304                 fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
11305                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
11306                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11307                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
11308                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11309                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
11310                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11311         } else {
11312                 fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
11313                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
11314                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
11315                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
11316                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
11317                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
11318                                 pic16_popCopyReg(&pic16_pc_tblptru)));
11319         }
11320
11321         size = min(AOP_SIZE(right), AOP_SIZE(result));
11322         while(size--) {
11323                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11324                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
11325                         pic16_popGet(AOP(result),offset)));
11326                 offset++;
11327         }
11328
11329         if(AOP_SIZE(result) > AOP_SIZE(right)) {
11330                 size = AOP_SIZE(result) - AOP_SIZE(right);
11331                 while(size--) {
11332                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
11333                         offset++;
11334                 }
11335         }
11336         goto release;
11337   }
11338
11339
11340
11341 #if 0
11342 /* VR - What is this?! */
11343   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
11344     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11345     if(aopIdx(AOP(result),0) == 4) {
11346
11347       /* this is a workaround to save value of right into wreg too,
11348        * value of wreg is going to be used later */
11349       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11350       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11351       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11352       goto release;
11353     } else
11354 //      assert(0);
11355       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
11356   }
11357 #endif
11358
11359   know_W=-1;
11360   while (size--) {
11361   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
11362     if(AOP_TYPE(right) == AOP_LIT) {
11363       if(lit&0xff) {
11364         if(know_W != (lit&0xff))
11365           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
11366         know_W = lit&0xff;
11367         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11368       } else
11369         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
11370
11371       lit >>= 8;
11372
11373     } else if (AOP_TYPE(right) == AOP_CRY) {
11374       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
11375       if(offset == 0) {
11376         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
11377         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
11378       }
11379     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
11380         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11381         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11382     } else {
11383       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11384
11385       if(!_G.resDirect)         /* use this aopForSym feature */
11386         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
11387     }
11388             
11389     offset++;
11390   }
11391   
11392  release:
11393   pic16_freeAsmop (right,NULL,ic,FALSE);
11394   pic16_freeAsmop (result,NULL,ic,TRUE);
11395 }   
11396
11397 /*-----------------------------------------------------------------*/
11398 /* genJumpTab - generates code for jump table                       */
11399 /*-----------------------------------------------------------------*/
11400 static void genJumpTab (iCode *ic)
11401 {
11402     symbol *jtab;
11403     char *l;
11404
11405     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11406
11407     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
11408     /* get the condition into accumulator */
11409     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
11410     MOVA(l);
11411     /* multiply by three */
11412     pic16_emitcode("add","a,acc");
11413     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
11414
11415     jtab = newiTempLabel(NULL);
11416     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
11417     pic16_emitcode("jmp","@a+dptr");
11418     pic16_emitcode("","%05d_DS_:",jtab->key+100);
11419
11420     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
11421     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
11422     emitSKPNC;
11423     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
11424     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
11425     pic16_emitpLabel(jtab->key);
11426
11427     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
11428
11429     /* now generate the jump labels */
11430     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
11431          jtab = setNextItem(IC_JTLABELS(ic))) {
11432         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
11433         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
11434         
11435     }
11436
11437 }
11438
11439 /*-----------------------------------------------------------------*/
11440 /* genMixedOperation - gen code for operators between mixed types  */
11441 /*-----------------------------------------------------------------*/
11442 /*
11443   TSD - Written for the PIC port - but this unfortunately is buggy.
11444   This routine is good in that it is able to efficiently promote 
11445   types to different (larger) sizes. Unfortunately, the temporary
11446   variables that are optimized out by this routine are sometimes
11447   used in other places. So until I know how to really parse the 
11448   iCode tree, I'm going to not be using this routine :(.
11449 */
11450 static int genMixedOperation (iCode *ic)
11451 {
11452 #if 0
11453   operand *result = IC_RESULT(ic);
11454   sym_link *ctype = operandType(IC_LEFT(ic));
11455   operand *right = IC_RIGHT(ic);
11456   int ret = 0;
11457   int big,small;
11458   int offset;
11459
11460   iCode *nextic;
11461   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
11462
11463   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11464
11465   nextic = ic->next;
11466   if(!nextic)
11467     return 0;
11468
11469   nextright = IC_RIGHT(nextic);
11470   nextleft  = IC_LEFT(nextic);
11471   nextresult = IC_RESULT(nextic);
11472
11473   pic16_aopOp(right,ic,FALSE);
11474   pic16_aopOp(result,ic,FALSE);
11475   pic16_aopOp(nextright,  nextic, FALSE);
11476   pic16_aopOp(nextleft,   nextic, FALSE);
11477   pic16_aopOp(nextresult, nextic, FALSE);
11478
11479   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
11480
11481     operand *t = right;
11482     right = nextright;
11483     nextright = t; 
11484
11485     pic16_emitcode(";remove right +","");
11486
11487   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
11488 /*
11489     operand *t = right;
11490     right = nextleft;
11491     nextleft = t; 
11492 */
11493     pic16_emitcode(";remove left +","");
11494   } else
11495     return 0;
11496
11497   big = AOP_SIZE(nextleft);
11498   small = AOP_SIZE(nextright);
11499
11500   switch(nextic->op) {
11501
11502   case '+':
11503     pic16_emitcode(";optimize a +","");
11504     /* if unsigned or not an integral type */
11505     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
11506       pic16_emitcode(";add a bit to something","");
11507     } else {
11508
11509       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
11510
11511       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
11512         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
11513         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
11514       } else
11515         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
11516
11517       offset = 0;
11518       while(--big) {
11519
11520         offset++;
11521
11522         if(--small) {
11523           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
11524             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11525             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11526           }
11527
11528           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11529           emitSKPNC;
11530           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
11531                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
11532                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
11533           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11534           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
11535
11536         } else {
11537           pic16_emitcode("rlf","known_zero,w");
11538
11539           /*
11540             if right is signed
11541               btfsc  right,7
11542                addlw ff
11543           */
11544           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
11545             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11546             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11547           } else {
11548             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11549           }
11550         }
11551       }
11552       ret = 1;
11553     }
11554   }
11555   ret = 1;
11556
11557 release:
11558   pic16_freeAsmop(right,NULL,ic,TRUE);
11559   pic16_freeAsmop(result,NULL,ic,TRUE);
11560   pic16_freeAsmop(nextright,NULL,ic,TRUE);
11561   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
11562   if(ret)
11563     nextic->generated = 1;
11564
11565   return ret;
11566 #else
11567   return 0;
11568 #endif
11569 }
11570 /*-----------------------------------------------------------------*/
11571 /* genCast - gen code for casting                                  */
11572 /*-----------------------------------------------------------------*/
11573 static void genCast (iCode *ic)
11574 {
11575   operand *result = IC_RESULT(ic);
11576   sym_link *ctype = operandType(IC_LEFT(ic));
11577   sym_link *rtype = operandType(IC_RIGHT(ic));
11578   operand *right = IC_RIGHT(ic);
11579   int size, offset ;
11580
11581         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11582         /* if they are equivalent then do nothing */
11583         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
11584                 return ;
11585
11586         pic16_aopOp(right,ic,FALSE) ;
11587         pic16_aopOp(result,ic,FALSE);
11588
11589         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11590
11591         /* if the result is a bit */
11592         if (AOP_TYPE(result) == AOP_CRY) {
11593         
11594                 /* if the right size is a literal then
11595                  * we know what the value is */
11596                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11597
11598                 if (AOP_TYPE(right) == AOP_LIT) {
11599                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
11600                                 pic16_popGet(AOP(result),0));
11601
11602                         if (((int) operandLitValue(right))) 
11603                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
11604                                         AOP(result)->aopu.aop_dir,
11605                                         AOP(result)->aopu.aop_dir);
11606                         else
11607                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
11608                                         AOP(result)->aopu.aop_dir,
11609                                         AOP(result)->aopu.aop_dir);
11610                         goto release;
11611                 }
11612
11613                 /* the right is also a bit variable */
11614                 if (AOP_TYPE(right) == AOP_CRY) {
11615                         emitCLRC;
11616                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
11617
11618                         pic16_emitcode("clrc","");
11619                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
11620                                 AOP(right)->aopu.aop_dir,
11621                                 AOP(right)->aopu.aop_dir);
11622                         pic16_aopPut(AOP(result),"c",0);
11623                         goto release ;
11624                 }
11625
11626                 /* we need to or */
11627                 if (AOP_TYPE(right) == AOP_REG) {
11628                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
11629                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
11630                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
11631                 }
11632                 pic16_toBoolean(right);
11633                 pic16_aopPut(AOP(result),"a",0);
11634                 goto release ;
11635         }
11636
11637         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
11638           int offset = 1;
11639
11640                 size = AOP_SIZE(result);
11641
11642                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11643
11644                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
11645                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
11646                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
11647
11648                 while (size--)
11649                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
11650
11651                 goto release;
11652         }
11653
11654         /* if they are the same size : or less */
11655         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
11656
11657                 /* if they are in the same place */
11658                 if (pic16_sameRegs(AOP(right),AOP(result)))
11659                         goto release;
11660
11661                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11662 #if 0
11663                 if (IS_PTR_CONST(rtype))
11664 #else
11665                 if (IS_CODEPTR(rtype))
11666 #endif
11667                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
11668
11669 #if 0
11670                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
11671 #else
11672                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
11673 #endif
11674                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
11675
11676 #if 0
11677                 if(AOP_TYPE(right) == AOP_IMMD) {
11678                   pCodeOp *pcop0, *pcop1, *pcop2;
11679                   symbol *sym = OP_SYMBOL( right );
11680
11681                         size = AOP_SIZE(result);
11682                         /* low */
11683                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11684                         /* high */
11685                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11686                         /* upper */
11687                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11688         
11689                         if (size == 3) {
11690                                 pic16_emitpcode(POC_MOVLW, pcop0);
11691                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11692                                 pic16_emitpcode(POC_MOVLW, pcop1);
11693                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
11694                                 pic16_emitpcode(POC_MOVLW, pcop2);
11695                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
11696                         } else
11697                         if (size == 2) {
11698                                 pic16_emitpcode(POC_MOVLW, pcop0);
11699                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11700                                 pic16_emitpcode(POC_MOVLW, pcop1);
11701                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11702                         } else {
11703                                 pic16_emitpcode(POC_MOVLW, pcop0);
11704                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11705                         }
11706                 } else
11707 #endif
11708                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11709                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
11710                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11711                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
11712                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11713                         if(AOP_SIZE(result) <2)
11714                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
11715                 } else {
11716                         /* if they in different places then copy */
11717                         size = AOP_SIZE(result);
11718                         offset = 0 ;
11719                         while (size--) {
11720                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11721                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11722                                 offset++;
11723                         }
11724                 }
11725                 goto release;
11726         }
11727
11728         /* if the result is of type pointer */
11729         if (IS_PTR(ctype)) {
11730           int p_type;
11731           sym_link *type = operandType(right);
11732           sym_link *etype = getSpec(type);
11733
11734                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
11735
11736                 /* pointer to generic pointer */
11737                 if (IS_GENPTR(ctype)) {
11738                   char *l = zero;
11739             
11740                         if (IS_PTR(type)) 
11741                                 p_type = DCL_TYPE(type);
11742                         else {
11743                 /* we have to go by the storage class */
11744                 p_type = PTR_TYPE(SPEC_OCLS(etype));
11745
11746 /*              if (SPEC_OCLS(etype)->codesp )  */
11747 /*                  p_type = CPOINTER ;  */
11748 /*              else */
11749 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11750 /*                      p_type = FPOINTER ; */
11751 /*                  else */
11752 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11753 /*                          p_type = PPOINTER; */
11754 /*                      else */
11755 /*                          if (SPEC_OCLS(etype) == idata ) */
11756 /*                              p_type = IPOINTER ; */
11757 /*                          else */
11758 /*                              p_type = POINTER ; */
11759             }
11760                 
11761             /* the first two bytes are known */
11762       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
11763             size = GPTRSIZE - 1; 
11764             offset = 0 ;
11765             while (size--) {
11766               if(offset < AOP_SIZE(right)) {
11767                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
11768                 mov2f(AOP(result), AOP(right), offset);
11769 /*
11770                 if ((AOP_TYPE(right) == AOP_PCODE) && 
11771                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11772                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11773                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11774                 } else { 
11775                   
11776                   pic16_aopPut(AOP(result),
11777                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11778                          offset);
11779                 }
11780 */
11781               } else 
11782                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
11783               offset++;
11784             }
11785             /* the last byte depending on type */
11786             switch (p_type) {
11787             case IPOINTER:
11788             case POINTER:
11789                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
11790                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
11791 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
11792                 break;
11793
11794             case CPOINTER:
11795                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
11796                 break;
11797
11798             case FPOINTER:
11799               pic16_emitcode(";BUG!? ","%d",__LINE__);
11800                 l = one;
11801                 break;
11802             case PPOINTER:
11803               pic16_emitcode(";BUG!? ","%d",__LINE__);
11804                 l = "#0x03";
11805                 break;
11806
11807             case GPOINTER:
11808               pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
11809               break;
11810               
11811             default:
11812                 /* this should never happen */
11813                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11814                        "got unknown pointer type");
11815                 exit(1);
11816             }
11817             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
11818             goto release ;
11819         }
11820         
11821         /* just copy the pointers */
11822         size = AOP_SIZE(result);
11823         offset = 0 ;
11824         while (size--) {
11825             pic16_aopPut(AOP(result),
11826                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11827                    offset);
11828             offset++;
11829         }
11830         goto release ;
11831     }
11832     
11833
11834
11835     /* so we now know that the size of destination is greater
11836     than the size of the source.
11837     Now, if the next iCode is an operator then we might be
11838     able to optimize the operation without performing a cast.
11839     */
11840     if(genMixedOperation(ic))
11841       goto release;
11842
11843     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11844     
11845     /* we move to result for the size of source */
11846     size = AOP_SIZE(right);
11847     offset = 0 ;
11848     while (size--) {
11849       mov2f(AOP(result), AOP(right), offset);
11850       offset++;
11851     }
11852
11853     /* now depending on the sign of the destination */
11854     size = AOP_SIZE(result) - AOP_SIZE(right);
11855     /* if unsigned or not an integral type */
11856     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
11857       while (size--)
11858         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
11859     } else {
11860       /* we need to extend the sign :( */
11861
11862       if(size == 1) {
11863         /* Save one instruction of casting char to int */
11864         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
11865         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11866         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
11867       } else {
11868         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
11869
11870         if(offset)
11871           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11872         else
11873           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11874         
11875         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
11876
11877         while (size--)
11878           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
11879       }
11880     }
11881
11882 release:
11883     pic16_freeAsmop(right,NULL,ic,TRUE);
11884     pic16_freeAsmop(result,NULL,ic,TRUE);
11885
11886 }
11887
11888 /*-----------------------------------------------------------------*/
11889 /* genDjnz - generate decrement & jump if not zero instrucion      */
11890 /*-----------------------------------------------------------------*/
11891 static int genDjnz (iCode *ic, iCode *ifx)
11892 {
11893     symbol *lbl, *lbl1;
11894     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11895
11896     if (!ifx)
11897         return 0;
11898     
11899     /* if the if condition has a false label
11900        then we cannot save */
11901     if (IC_FALSE(ifx))
11902         return 0;
11903
11904     /* if the minus is not of the form 
11905        a = a - 1 */
11906     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
11907         !IS_OP_LITERAL(IC_RIGHT(ic)))
11908         return 0;
11909
11910     if (operandLitValue(IC_RIGHT(ic)) != 1)
11911         return 0;
11912
11913     /* if the size of this greater than one then no
11914        saving */
11915     if (getSize(operandType(IC_RESULT(ic))) > 1)
11916         return 0;
11917
11918     /* otherwise we can save BIG */
11919     lbl = newiTempLabel(NULL);
11920     lbl1= newiTempLabel(NULL);
11921
11922     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11923     
11924     if (IS_AOP_PREG(IC_RESULT(ic))) {
11925         pic16_emitcode("dec","%s",
11926                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11927         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11928         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
11929     } else {    
11930
11931
11932       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
11933       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
11934
11935       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11936       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
11937
11938     }
11939     
11940     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11941     ifx->generated = 1;
11942     return 1;
11943 }
11944
11945 /*-----------------------------------------------------------------*/
11946 /* genReceive - generate code for a receive iCode                  */
11947 /*-----------------------------------------------------------------*/
11948 static void genReceive (iCode *ic)
11949 {    
11950   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11951
11952 #if 0
11953   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
11954         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
11955 #endif
11956 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
11957
11958   if (isOperandInFarSpace(IC_RESULT(ic))
11959       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
11960           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
11961
11962     int size = getSize(operandType(IC_RESULT(ic)));
11963     int offset =  pic16_fReturnSizePic - size;
11964
11965       assert( 0 );
11966       while (size--) {
11967         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
11968                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
11969                       offset++;
11970         }
11971
11972       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
11973
11974       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11975       size = AOP_SIZE(IC_RESULT(ic));
11976       offset = 0;
11977       while (size--) {
11978         pic16_emitcode ("pop","acc");
11979         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
11980       }
11981   } else {
11982     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
11983
11984     _G.accInUse++;
11985     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11986     _G.accInUse--;
11987     assignResultValue(IC_RESULT(ic), 0);
11988   }
11989
11990   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11991 }
11992
11993 /*-----------------------------------------------------------------*/
11994 /* genDummyRead - generate code for dummy read of volatiles        */
11995 /*-----------------------------------------------------------------*/
11996 static void
11997 genDummyRead (iCode * ic)
11998 {
11999   pic16_emitcode ("; genDummyRead","");
12000   pic16_emitcode ("; not implemented","");
12001
12002   ic = ic;
12003 }
12004
12005 /*-----------------------------------------------------------------*/
12006 /* genpic16Code - generate code for pic16 based controllers        */
12007 /*-----------------------------------------------------------------*/
12008 /*
12009  * At this point, ralloc.c has gone through the iCode and attempted
12010  * to optimize in a way suitable for a PIC. Now we've got to generate
12011  * PIC instructions that correspond to the iCode.
12012  *
12013  * Once the instructions are generated, we'll pass through both the
12014  * peep hole optimizer and the pCode optimizer.
12015  *-----------------------------------------------------------------*/
12016
12017 void genpic16Code (iCode *lic)
12018 {
12019     iCode *ic;
12020     int cln = 0;
12021
12022     lineHead = lineCurr = NULL;
12023
12024     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
12025     pic16_addpBlock(pb);
12026
12027 #if 0
12028     /* if debug information required */
12029     if (options.debug && currFunc) {
12030       if (currFunc) {
12031         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
12032       }
12033     }
12034 #endif
12035
12036     for (ic = lic ; ic ; ic = ic->next ) {
12037
12038       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
12039         if ( cln != ic->lineno ) {
12040             if ( options.debug ) {
12041               debugFile->writeCLine (ic);
12042             }
12043             
12044             if(!options.noCcodeInAsm) {
12045                 pic16_addpCode2pBlock(pb,
12046                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
12047                                 printCLine(ic->filename, ic->lineno)));
12048             }
12049
12050             cln = ic->lineno ;
12051         }
12052         
12053         if(options.iCodeInAsm) {
12054                 char *l;
12055                 /* insert here code to print iCode as comment */
12056                 l = Safe_strdup(printILine(ic));
12057                 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
12058         }
12059         
12060         /* if the result is marked as
12061            spilt and rematerializable or code for
12062            this has already been generated then
12063            do nothing */
12064         if (resultRemat(ic) || ic->generated ) 
12065             continue ;
12066         
12067         /* depending on the operation */
12068         switch (ic->op) {
12069         case '!' :
12070             pic16_genNot(ic);
12071             break;
12072             
12073         case '~' :
12074             pic16_genCpl(ic);
12075             break;
12076             
12077         case UNARYMINUS:
12078             genUminus (ic);
12079             break;
12080             
12081         case IPUSH:
12082             genIpush (ic);
12083             break;
12084             
12085         case IPOP:
12086             /* IPOP happens only when trying to restore a 
12087                spilt live range, if there is an ifx statement
12088                following this pop then the if statement might
12089                be using some of the registers being popped which
12090                would destroy the contents of the register so
12091                we need to check for this condition and handle it */
12092             if (ic->next            && 
12093                 ic->next->op == IFX &&
12094                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
12095                 genIfx (ic->next,ic);
12096             else
12097                 genIpop (ic);
12098             break; 
12099             
12100         case CALL:
12101             genCall (ic);
12102             break;
12103             
12104         case PCALL:
12105             genPcall (ic);
12106             break;
12107             
12108         case FUNCTION:
12109             genFunction (ic);
12110             break;
12111             
12112         case ENDFUNCTION:
12113             genEndFunction (ic);
12114             break;
12115             
12116         case RETURN:
12117             genRet (ic);
12118             break;
12119             
12120         case LABEL:
12121             genLabel (ic);
12122             break;
12123             
12124         case GOTO:
12125             genGoto (ic);
12126             break;
12127             
12128         case '+' :
12129             pic16_genPlus (ic) ;
12130             break;
12131             
12132         case '-' :
12133             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
12134                 pic16_genMinus (ic);
12135             break;
12136             
12137         case '*' :
12138             genMult (ic);
12139             break;
12140             
12141         case '/' :
12142             genDiv (ic) ;
12143             break;
12144             
12145         case '%' :
12146             genMod (ic);
12147             break;
12148             
12149         case '>' :
12150             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
12151             break;
12152             
12153         case '<' :
12154             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
12155             break;
12156             
12157         case LE_OP:
12158         case GE_OP:
12159         case NE_OP:
12160             
12161             /* note these two are xlated by algebraic equivalence
12162                during parsing SDCC.y */
12163             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
12164                    "got '>=' or '<=' shouldn't have come here");
12165             break;      
12166             
12167         case EQ_OP:
12168             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
12169             break;          
12170             
12171         case AND_OP:
12172             genAndOp (ic);
12173             break;
12174             
12175         case OR_OP:
12176             genOrOp (ic);
12177             break;
12178             
12179         case '^' :
12180             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
12181             break;
12182             
12183         case '|' :
12184                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
12185             break;
12186             
12187         case BITWISEAND:
12188             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
12189             break;
12190             
12191         case INLINEASM:
12192             genInline (ic);
12193             break;
12194             
12195         case RRC:
12196             genRRC (ic);
12197             break;
12198             
12199         case RLC:
12200             genRLC (ic);
12201             break;
12202             
12203         case GETHBIT:
12204             genGetHbit (ic);
12205             break;
12206             
12207         case LEFT_OP:
12208             genLeftShift (ic);
12209             break;
12210             
12211         case RIGHT_OP:
12212             genRightShift (ic);
12213             break;
12214             
12215         case GET_VALUE_AT_ADDRESS:
12216             genPointerGet(ic);
12217             break;
12218             
12219         case '=' :
12220             if (POINTER_SET(ic))
12221                 genPointerSet(ic);
12222             else
12223                 genAssign(ic);
12224             break;
12225             
12226         case IFX:
12227             genIfx (ic,NULL);
12228             break;
12229             
12230         case ADDRESS_OF:
12231             genAddrOf (ic);
12232             break;
12233             
12234         case JUMPTABLE:
12235             genJumpTab (ic);
12236             break;
12237             
12238         case CAST:
12239             genCast (ic);
12240             break;
12241             
12242         case RECEIVE:
12243             genReceive(ic);
12244             break;
12245             
12246         case SEND:
12247             addSet(&_G.sendSet,ic);
12248             /* create a reversed list of SEND iCodes */
12249 //            addSetHead(&_G.sendSet, ic);
12250             break;
12251
12252         case DUMMY_READ_VOLATILE:
12253           genDummyRead (ic);
12254           break;
12255
12256         default :
12257             ic = ic;
12258         }
12259     }
12260
12261
12262     /* now we are ready to call the
12263        peep hole optimizer */
12264     if (!options.nopeep) {
12265       peepHole (&lineHead);
12266     }
12267     /* now do the actual printing */
12268     printLine (lineHead, codeOutFile);
12269
12270 #ifdef PCODE_DEBUG
12271     DFPRINTF((stderr,"printing pBlock\n\n"));
12272     pic16_printpBlock(stdout,pb);
12273 #endif
12274
12275     return;
12276 }
12277