* src/pic16/gen.c (mov2f): New function to move an operand to
[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 *dsr, asmop *src, int offset);
62 //static int aopIdx (asmop *aop, int offset);
63
64 int pic16_labelOffset=0;
65 extern int pic16_debug_verbose;
66 static int optimized_for_speed = 0;
67 /*
68   hack hack
69
70 */
71
72 /* max_key keeps track of the largest label number used in 
73    a function. This is then used to adjust the label offset
74    for the next function.
75 */
76 static int max_key=0;
77 static int GpsuedoStkPtr=0;
78
79 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
80 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst);
81
82 unsigned int pic16aopLiteral (value *val, int offset);
83 const char *pic16_AopType(short type);
84 static iCode *ifxForOp ( operand *op, iCode *ic );
85
86 void pic16_pushpCodeOp(pCodeOp *pcop);
87 void pic16_poppCodeOp(pCodeOp *pcop);
88
89 static bool is_LitOp(operand *op);
90 static bool is_LitAOp(asmop *aop);
91
92
93 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
94
95 /* this is the down and dirty file with all kinds of 
96    kludgy & hacky stuff. This is what it is all about
97    CODE GENERATION for a specific MCU . some of the
98    routines may be reusable, will have to see */
99
100 static char *zero = "#0x00";
101 static char *one  = "#0x01";
102 static char *spname = "sp";
103
104
105 /*
106  * Function return value policy (MSB-->LSB):
107  *  8 bits      -> WREG
108  * 16 bits      -> PRODL:WREG
109  * 24 bits      -> PRODH:PRODL:WREG
110  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
111  * >32 bits     -> on stack, and FSR0 points to the beginning
112  *
113  */
114  
115
116 char *fReturnpic16[] = {"temp1","temp2","temp3","temp4" };
117 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
118 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
119 static char **fReturn = fReturnpic16;
120
121 static char *accUse[] = {"WREG"};
122
123 //static short rbank = -1;
124
125 static struct {
126     short r0Pushed;
127     short r1Pushed;
128     short fsr0Pushed;
129     short accInUse;
130     short inLine;
131     short debugLine;
132     short nRegsSaved;
133     short ipushRegs;
134     set *sendSet;
135     int interruptvector;
136     int usefastretfie;
137 } _G;
138
139 /* Resolved ifx structure. This structure stores information
140    about an iCode ifx that makes it easier to generate code.
141 */
142 typedef struct resolvedIfx {
143   symbol *lbl;     /* pointer to a label */
144   int condition;   /* true or false ifx */
145   int generated;   /* set true when the code associated with the ifx
146                     * is generated */
147 } resolvedIfx;
148
149 extern int pic16_ptrRegReq ;
150 extern int pic16_nRegs;
151 extern FILE *codeOutFile;
152 static void saverbank (int, iCode *,bool);
153
154 static lineNode *lineHead = NULL;
155 static lineNode *lineCurr = NULL;
156
157 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
158 0xE0, 0xC0, 0x80, 0x00};
159 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
160 0x07, 0x03, 0x01, 0x00};
161
162 static  pBlock *pb;
163
164 /*-----------------------------------------------------------------*/
165 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
166 /*                 exponent of 2 is returned, otherwise -1 is      */
167 /*                 returned.                                       */
168 /* note that this is similar to the function `powof2' in SDCCsymt  */
169 /* if(n == 2^y)                                                    */
170 /*   return y;                                                     */
171 /* return -1;                                                      */
172 /*-----------------------------------------------------------------*/
173 static int my_powof2 (unsigned long num)
174 {
175   if(num) {
176     if( (num & (num-1)) == 0) {
177       int nshifts = -1;
178       while(num) {
179         num>>=1;
180         nshifts++;
181       }
182       return nshifts;
183     }
184   }
185
186   return -1;
187 }
188
189 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
190 {
191   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
192                        line_no,
193                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
194                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
195                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
196                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
197                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
198                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
199                        ((result) ? AOP_SIZE(result) : 0));
200 }
201
202 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
203 {
204
205   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
206                        line_no,
207                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
208                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
209                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
210                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
211                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
212                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
213
214 }
215
216 void pic16_emitpcomment (char *fmt, ...)
217 {
218     va_list ap;
219     char lb[INITIAL_INLINEASM];  
220     char *lbp = lb;
221
222     va_start(ap,fmt);   
223
224     lb[0] = ';';
225     vsprintf(lb+1,fmt,ap);
226
227     while (isspace(*lbp)) lbp++;
228
229     if (lbp && *lbp) 
230         lineCurr = (lineCurr ?
231                     connectLine(lineCurr,newLineNode(lb)) :
232                     (lineHead = newLineNode(lb)));
233     lineCurr->isInline = _G.inLine;
234     lineCurr->isDebug  = _G.debugLine;
235
236     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
237     va_end(ap);
238
239 //      fprintf(stderr, "%s\n", lb);
240 }
241
242 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
243 {
244     va_list ap;
245     char lb[INITIAL_INLINEASM];  
246     char *lbp = lb;
247
248     if(!pic16_debug_verbose)
249       return;
250
251     va_start(ap,fmt);   
252
253     if (inst && *inst) {
254         if (fmt && *fmt)
255             sprintf(lb,"%s\t",inst);
256         else
257             sprintf(lb,"%s",inst);
258         vsprintf(lb+(strlen(lb)),fmt,ap);
259     }  else
260         vsprintf(lb,fmt,ap);
261
262     while (isspace(*lbp)) lbp++;
263
264     if (lbp && *lbp) 
265         lineCurr = (lineCurr ?
266                     connectLine(lineCurr,newLineNode(lb)) :
267                     (lineHead = newLineNode(lb)));
268     lineCurr->isInline = _G.inLine;
269     lineCurr->isDebug  = _G.debugLine;
270
271     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
272     va_end(ap);
273
274 //      fprintf(stderr, "%s\n", lb);
275 }
276
277 void pic16_emitpLabel(int key)
278 {
279   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
280 }
281
282 void pic16_emitpLabelFORCE(int key)
283 {
284   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
285 }
286
287 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
288 {
289
290   if(pcop)
291     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
292   else
293     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
294     
295 //    fprintf(stderr, "%s\n", pcop->name);
296 }
297
298 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
299 {
300
301   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
302
303 }
304
305
306 #if 1
307 #define pic16_emitcode  DEBUGpic16_emitcode
308 #else
309 /*-----------------------------------------------------------------*/
310 /* pic16_emitcode - writes the code into a file : for now it is simple    */
311 /*-----------------------------------------------------------------*/
312 void pic16_emitcode (char *inst,char *fmt, ...)
313 {
314     va_list ap;
315     char lb[INITIAL_INLINEASM];  
316     char *lbp = lb;
317
318     va_start(ap,fmt);   
319
320     if (inst && *inst) {
321         if (fmt && *fmt)
322             sprintf(lb,"%s\t",inst);
323         else
324             sprintf(lb,"%s",inst);
325         vsprintf(lb+(strlen(lb)),fmt,ap);
326     }  else
327         vsprintf(lb,fmt,ap);
328
329     while (isspace(*lbp)) lbp++;
330
331     if (lbp && *lbp) 
332         lineCurr = (lineCurr ?
333                     connectLine(lineCurr,newLineNode(lb)) :
334                     (lineHead = newLineNode(lb)));
335     lineCurr->isInline = _G.inLine;
336     lineCurr->isDebug  = _G.debugLine;
337
338 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
339
340 //    if(pic16_debug_verbose)
341 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
342
343     va_end(ap);
344 }
345 #endif
346
347
348 /*-----------------------------------------------------------------*/
349 /* pic16_emitDebuggerSymbol - associate the current code location  */
350 /*   with a debugger symbol                                        */
351 /*-----------------------------------------------------------------*/
352 void
353 pic16_emitDebuggerSymbol (char * debugSym)
354 {
355   _G.debugLine = 1;
356   pic16_emitcode (";", "%s ==.", debugSym);
357   _G.debugLine = 0;
358 }
359
360
361 /*-----------------------------------------------------------------*/
362 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
363 /*-----------------------------------------------------------------*/
364 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
365 {
366 //    bool r0iu = FALSE , r1iu = FALSE;
367 //    bool r0ou = FALSE , r1ou = FALSE;
368     bool fsr0iu = FALSE, fsr0ou;
369     bool fsr2iu = FALSE, fsr2ou;
370     
371     fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
372
373     
374     fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
375     fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
376     
377     fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
378     fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
379
380     if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
381         fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
382         DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
383     }
384
385     /* no usage of FSR2 */
386     if(!fsr2iu && !fsr2ou) {
387         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
388         (*aopp)->type = AOP_FSR2;
389
390       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
391     }
392         
393     if(!fsr0iu && !fsr0ou) {
394         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
395         (*aopp)->type = AOP_FSR0;
396         
397       return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
398     }
399
400     /* now we know they both have usage */
401     /* if fsr0 not used in this instruction */
402     if (!fsr0iu) {
403         if (!_G.fsr0Pushed) {
404                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
405                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
406                 _G.fsr0Pushed++;
407         }
408
409         ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
410         (*aopp)->type = AOP_FSR0;
411
412       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
413     }
414         
415
416     fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
417     assert( 0 );
418
419     return NULL;
420 #if 0
421     /* the logic: if r0 & r1 used in the instruction
422     then we are in trouble otherwise */
423
424     /* first check if r0 & r1 are used by this
425     instruction, in which case we are in trouble */
426     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
427         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
428     {
429         goto endOfWorld;      
430     }
431
432     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
433     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
434
435     /* if no usage of r0 then return it */
436     if (!r0iu && !r0ou) {
437         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
438         (*aopp)->type = AOP_R0;
439         
440         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
441     }
442
443     /* if no usage of r1 then return it */
444     if (!r1iu && !r1ou) {
445         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
446         (*aopp)->type = AOP_R1;
447
448         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
449     }    
450
451     /* now we know they both have usage */
452     /* if r0 not used in this instruction */
453     if (!r0iu) {
454         /* push it if not already pushed */
455         if (!_G.r0Pushed) {
456           //pic16_emitcode ("push","%s",
457           //          pic16_regWithIdx(R0_IDX)->dname);
458             _G.r0Pushed++ ;
459         }
460         
461         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
462         (*aopp)->type = AOP_R0;
463
464         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
465     }
466
467     /* if r1 not used then */
468
469     if (!r1iu) {
470         /* push it if not already pushed */
471         if (!_G.r1Pushed) {
472           //pic16_emitcode ("push","%s",
473           //          pic16_regWithIdx(R1_IDX)->dname);
474             _G.r1Pushed++ ;
475         }
476         
477         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
478         (*aopp)->type = AOP_R1;
479         return pic16_regWithIdx(R1_IDX);
480     }
481
482 endOfWorld :
483     /* I said end of world but not quite end of world yet */
484     /* if this is a result then we can push it on the stack*/
485     if (result) {
486         (*aopp)->type = AOP_STK;    
487         return NULL;
488     }
489
490     /* other wise this is true end of the world */
491     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
492            "getFreePtr should never reach here");
493     exit(0);
494 #endif
495 }
496
497 /*-----------------------------------------------------------------*/
498 /* newAsmop - creates a new asmOp                                  */
499 /*-----------------------------------------------------------------*/
500 static asmop *newAsmop (short type)
501 {
502     asmop *aop;
503
504     aop = Safe_calloc(1,sizeof(asmop));
505     aop->type = type;
506     return aop;
507 }
508
509 static void genSetDPTR(int n)
510 {
511     if (!n)
512     {
513         pic16_emitcode(";", "Select standard DPTR");
514         pic16_emitcode("mov", "dps, #0x00");
515     }
516     else
517     {
518         pic16_emitcode(";", "Select alternate DPTR");
519         pic16_emitcode("mov", "dps, #0x01");
520     }
521 }
522
523 /*-----------------------------------------------------------------*/
524 /* resolveIfx - converts an iCode ifx into a form more useful for  */
525 /*              generating code                                    */
526 /*-----------------------------------------------------------------*/
527 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
528 {
529
530   DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
531
532   if(!resIfx) 
533     return;
534
535
536   resIfx->condition = 1;    /* assume that the ifx is true */
537   resIfx->generated = 0;    /* indicate that the ifx has not been used */
538
539   if(!ifx) {
540     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
541
542 #if 1
543     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
544                         __FUNCTION__,__LINE__,resIfx->lbl->key);
545 #endif
546
547   } else {
548     if(IC_TRUE(ifx)) {
549       resIfx->lbl = IC_TRUE(ifx);
550     } else {
551       resIfx->lbl = IC_FALSE(ifx);
552       resIfx->condition = 0;
553     }
554
555 #if 1
556     if(IC_TRUE(ifx)) 
557       DEBUGpic16_emitcode("; ***","ifx true is non-null");
558     if(IC_FALSE(ifx)) 
559       DEBUGpic16_emitcode("; ***","ifx false is non-null");
560 #endif
561   }
562
563   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
564
565 }
566 #if 0
567 /*-----------------------------------------------------------------*/
568 /* pointerCode - returns the code for a pointer type               */
569 /*-----------------------------------------------------------------*/
570 static int pointerCode (sym_link *etype)
571 {
572
573     return PTR_TYPE(SPEC_OCLS(etype));
574
575 }
576 #endif
577
578 /*-----------------------------------------------------------------*/
579 /* aopForSym - for a true symbol                                   */
580 /*-----------------------------------------------------------------*/
581 static asmop *aopForSym (iCode *ic, operand *op, bool result)
582 {
583     symbol *sym=OP_SYMBOL(op);
584     asmop *aop;
585     memmap *space= SPEC_OCLS(sym->etype);
586
587     DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
588
589 //    sym = OP_SYMBOL(op);
590
591     /* if already has one */
592     if (sym->aop) {
593             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
594         return sym->aop;
595     }
596
597     /* if symbol was initially placed onStack then we must re-place it
598      * to direct memory, since pic16 does not have a specific stack */
599     if(sym->onStack) {
600         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
601     }
602
603
604 #if 1
605     /* assign depending on the storage class */
606     /* if it is on the stack or indirectly addressable */
607     /* space we need to assign either r0 or r1 to it   */    
608     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
609
610         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
611                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
612         
613         sym->aop = aop = newAsmop(0);
614         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
615         aop->size = getSize(sym->type);
616
617         fprintf(stderr, "%s:%d\t%s\n", __FILE__, __LINE__, __FUNCTION__);
618
619 #if 1
620 //        sym->aop = aop = newAsmop (AOP_REG);
621 //        aop->aopu.aop_dir = sym->name;        //sym->rname ;
622 //      aop->aopu.aop_reg[0] = pic16_regWithIdx(IDX_PLUSW0);    //pic16_pc_plusw2.r;
623 //        aop->size = getSize(sym->type);
624         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
625         
626 //      if(_G.accInUse) {
627 //              pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
628 //      }
629         
630 //      pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popCopyReg(&pic16_pc_fsr2l), pic16_popCopyReg(&pic16_pc_fsr0l)));
631 //      pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popCopyReg(&pic16_pc_fsr2h), pic16_popCopyReg(&pic16_pc_fsr0h)));
632         
633         
634         /* initialise for stack access via frame pointer */
635         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
636
637 //      pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
638 //              pic16_popCopyReg(&pic16_pc_plusw2), pic16_popCopyReg(&pic16_pc_kzero)));
639         
640 //      if(_G.accInUse) {
641 //              pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
642 //      }
643         
644         return (aop);
645 #endif
646
647 #if 0
648         /* now assign the address of the variable to 
649         the pointer register */
650         if (aop->type != AOP_STK) {
651
652             if (sym->onStack) {
653                     if ( _G.accInUse )
654                         pic16_emitcode("push","acc");
655
656                     pic16_emitcode("mov","a,_bp");
657                     pic16_emitcode("add","a,#0x%02x",
658                              ((sym->stack < 0) ?
659                               ((char)(sym->stack - _G.nRegsSaved )) :
660                               ((char)sym->stack)) & 0xff);
661                     pic16_emitcode("mov","%s,a",
662                              aop->aopu.aop_ptr->name);
663
664                     if ( _G.accInUse )
665                         pic16_emitcode("pop","acc");
666             } else
667                 pic16_emitcode("mov","%s,#%s",
668                          aop->aopu.aop_ptr->name,
669                          sym->rname);
670             aop->paged = space->paged;
671         } else
672             aop->aopu.aop_stk = sym->stack;
673         return aop;
674 #endif
675
676     }
677 #endif
678
679 #if 0
680     if (sym->onStack && options.stack10bit)
681     {
682         /* It's on the 10 bit stack, which is located in
683          * far data space.
684          */
685          
686       //DEBUGpic16_emitcode(";","%d",__LINE__);
687
688         if ( _G.accInUse )
689                 pic16_emitcode("push","acc");
690
691         pic16_emitcode("mov","a,_bp");
692         pic16_emitcode("add","a,#0x%02x",
693                  ((sym->stack < 0) ?
694                    ((char)(sym->stack - _G.nRegsSaved )) :
695                    ((char)sym->stack)) & 0xff);
696         
697         genSetDPTR(1);
698         pic16_emitcode ("mov","dpx1,#0x40");
699         pic16_emitcode ("mov","dph1,#0x00");
700         pic16_emitcode ("mov","dpl1, a");
701         genSetDPTR(0);
702         
703         if ( _G.accInUse )
704             pic16_emitcode("pop","acc");
705             
706         sym->aop = aop = newAsmop(AOP_DPTR2);
707         aop->size = getSize(sym->type); 
708         return aop;
709     }
710 #endif
711     //DEBUGpic16_emitcode(";","%d",__LINE__);
712     /* if in bit space */
713     if (IN_BITSPACE(space)) {
714         sym->aop = aop = newAsmop (AOP_CRY);
715         aop->aopu.aop_dir = sym->rname ;
716         aop->size = getSize(sym->type);
717         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
718         return aop;
719     }
720     /* if it is in direct space */
721     if (IN_DIRSPACE(space)) {
722         sym->aop = aop = newAsmop (AOP_DIR);
723         aop->aopu.aop_dir = sym->rname ;
724         aop->size = getSize(sym->type);
725         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
726         pic16_allocDirReg( IC_LEFT(ic) );
727         return aop;
728     }
729
730     if (IN_FARSPACE(space)) {
731         sym->aop = aop = newAsmop (AOP_DIR);
732         aop->aopu.aop_dir = sym->rname ;
733         aop->size = getSize(sym->type);
734         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
735         pic16_allocDirReg( IC_LEFT(ic) );
736         return aop;
737     }
738
739 #if 0                                                                                           // patch 14
740     /* special case for a function */
741     if (IS_FUNC(sym->type)) {   
742         sym->aop = aop = newAsmop(AOP_IMMD);    
743         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
744         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
745         strcpy(aop->aopu.aop_immd,sym->rname);
746         aop->size = FPTRSIZE; 
747         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
748         return aop;
749     }
750 #endif                                                                                          // patch 14
751
752
753     /* only remaining is far space */
754     /* in which case DPTR gets the address */
755     sym->aop = aop = newAsmop(AOP_PCODE);
756
757 /* change the next if to 1 to revert to good old immediate code */
758         if(IN_CODESPACE(space)) {
759                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
760                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
761                 PCOI(aop->aopu.pcop)->index = 0;
762         } else {
763                 /* try to allocate via direct register */
764                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
765 //              aop->size = getSize( sym->type );
766         }
767
768         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
769                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
770
771 #if 0
772         if(!pic16_allocDirReg (IC_LEFT(ic)))
773                 return NULL;
774 #endif
775
776         if(IN_DIRSPACE( space ))
777                 aop->size = PTRSIZE;
778         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
779                 aop->size = FPTRSIZE;
780         else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
781         else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
782         else {
783                 assert( 0 );
784         }
785
786     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
787
788     /* if it is in code space */
789     if (IN_CODESPACE(space))
790         aop->code = 1;
791
792     return aop;     
793 }
794
795 /*-----------------------------------------------------------------*/
796 /* aopForRemat - rematerialzes an object                           */
797 /*-----------------------------------------------------------------*/
798 static asmop *aopForRemat (operand *op) // x symbol *sym)
799 {
800   symbol *sym = OP_SYMBOL(op);
801   iCode *ic = NULL, *oldic;
802   asmop *aop = newAsmop(AOP_PCODE);
803   int val = 0;
804   int offset = 0;
805   int viaimmd=0;
806
807
808         ic = sym->rematiCode;
809
810         DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
811         
812         if(IS_OP_POINTER(op)) {
813                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
814         }
815
816         for (;;) {
817                 oldic = ic;
818
819 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
820         
821                 if (ic->op == '+') {
822                         val += (int) operandLitValue(IC_RIGHT(ic));
823                 } else if (ic->op == '-') {
824                         val -= (int) operandLitValue(IC_RIGHT(ic));
825                 } else
826                         break;
827                 
828                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
829         }
830
831         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
832
833         if(!op->isaddr)viaimmd++; else viaimmd=0;
834                 
835 /* set the following if to 1 to revert to good old immediate code */
836         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))
837                 || viaimmd) {
838
839                 DEBUGpic16_emitcode("%s:%d immediate", __FILE__, __LINE__);
840
841                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
842
843 #if 0
844                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
845 #else
846                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
847 #endif
848
849                 PCOI(aop->aopu.pcop)->index = val;
850         } else {
851                 DEBUGpic16_emitcode("%s:%d dir", __FILE__, __LINE__);
852
853                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
854                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
855 //              aop->size = AOP_SIZE( IC_LEFT(ic) );
856         }
857
858
859         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
860                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
861 #if 0
862                 val, IS_PTR_CONST(operandType(op)));
863 #else
864                 val, IS_CODEPTR(operandType(op)));
865 #endif
866
867 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
868
869         pic16_allocDirReg (IC_LEFT(ic));
870
871         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
872                 aop->code = 1;
873
874   return aop;        
875 }
876
877 #if 0
878 static int aopIdx (asmop *aop, int offset)
879 {
880   if(!aop)
881     return -1;
882
883   if(aop->type !=  AOP_REG)
884     return -2;
885         
886   return aop->aopu.aop_reg[offset]->rIdx;
887
888 }
889 #endif
890
891 /*-----------------------------------------------------------------*/
892 /* regsInCommon - two operands have some registers in common       */
893 /*-----------------------------------------------------------------*/
894 static bool regsInCommon (operand *op1, operand *op2)
895 {
896     symbol *sym1, *sym2;
897     int i;
898
899     /* if they have registers in common */
900     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
901         return FALSE ;
902
903     sym1 = OP_SYMBOL(op1);
904     sym2 = OP_SYMBOL(op2);
905
906     if (sym1->nRegs == 0 || sym2->nRegs == 0)
907         return FALSE ;
908
909     for (i = 0 ; i < sym1->nRegs ; i++) {
910         int j;
911         if (!sym1->regs[i])
912             continue ;
913
914         for (j = 0 ; j < sym2->nRegs ;j++ ) {
915             if (!sym2->regs[j])
916                 continue ;
917
918             if (sym2->regs[j] == sym1->regs[i])
919                 return TRUE ;
920         }
921     }
922
923     return FALSE ;
924 }
925
926 /*-----------------------------------------------------------------*/
927 /* operandsEqu - equivalent                                        */
928 /*-----------------------------------------------------------------*/
929 static bool operandsEqu ( operand *op1, operand *op2)
930 {
931     symbol *sym1, *sym2;
932
933     /* if they not symbols */
934     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
935         return FALSE;
936
937     sym1 = OP_SYMBOL(op1);
938     sym2 = OP_SYMBOL(op2);
939
940     /* if both are itemps & one is spilt
941        and the other is not then false */
942     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
943         sym1->isspilt != sym2->isspilt )
944         return FALSE ;
945
946     /* if they are the same */
947     if (sym1 == sym2)
948         return TRUE ;
949
950     if (sym1->rname[0] && sym2->rname[0]
951         && strcmp (sym1->rname, sym2->rname) == 0)
952         return TRUE;
953
954
955     /* if left is a tmp & right is not */
956     if (IS_ITEMP(op1)  && 
957         !IS_ITEMP(op2) &&
958         sym1->isspilt  &&
959         (sym1->usl.spillLoc == sym2))
960         return TRUE;
961
962     if (IS_ITEMP(op2)  && 
963         !IS_ITEMP(op1) &&
964         sym2->isspilt  &&
965         sym1->level > 0 &&
966         (sym2->usl.spillLoc == sym1))
967         return TRUE ;
968
969     return FALSE ;
970 }
971
972 /*-----------------------------------------------------------------*/
973 /* pic16_sameRegs - two asmops have the same registers                   */
974 /*-----------------------------------------------------------------*/
975 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
976 {
977     int i;
978
979     if (aop1 == aop2)
980         return TRUE ;
981
982     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
983                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
984
985     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
986
987 #if 0
988     if (aop1->type != AOP_REG ||
989         aop2->type != AOP_REG )
990         return FALSE ;
991 #endif
992
993     if (aop1->size != aop2->size )
994         return FALSE ;
995
996     for (i = 0 ; i < aop1->size ; i++ )
997         if (aop1->aopu.aop_reg[i] !=
998             aop2->aopu.aop_reg[i] )
999             return FALSE ;
1000
1001     return TRUE ;
1002 }
1003
1004 /*-----------------------------------------------------------------*/
1005 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1006 /*-----------------------------------------------------------------*/
1007 void pic16_aopOp (operand *op, iCode *ic, bool result)
1008 {
1009     asmop *aop;
1010     symbol *sym;
1011     int i;
1012
1013     if (!op)
1014         return ;
1015
1016 //      DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1017
1018     /* if this a literal */
1019     if (IS_OP_LITERAL(op)) {
1020         op->aop = aop = newAsmop(AOP_LIT);
1021         aop->aopu.aop_lit = op->operand.valOperand;
1022         aop->size = getSize(operandType(op));
1023         return;
1024     }
1025
1026     {
1027       sym_link *type = operandType(op);
1028 #if 0
1029       if(IS_PTR_CONST(type))
1030 #else
1031       if(IS_CODEPTR(type))
1032 #endif
1033         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1034     }
1035
1036     /* if already has a asmop then continue */
1037     if (op->aop)
1038         return ;
1039
1040     /* if the underlying symbol has a aop */
1041     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1042       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1043         op->aop = OP_SYMBOL(op)->aop;
1044         return;
1045     }
1046
1047     /* if this is a true symbol */
1048     if (IS_TRUE_SYMOP(op)) {    
1049         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1050       op->aop = aopForSym(ic, op, result);
1051       return ;
1052     }
1053
1054     /* this is a temporary : this has
1055     only four choices :
1056     a) register
1057     b) spillocation
1058     c) rematerialize 
1059     d) conditional   
1060     e) can be a return use only */
1061
1062     sym = OP_SYMBOL(op);
1063
1064         DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
1065     /* if the type is a conditional */
1066     if (sym->regType == REG_CND) {
1067         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1068         aop->size = 0;
1069         return;
1070     }
1071
1072     /* if it is spilt then two situations
1073     a) is rematerialize 
1074     b) has a spill location */
1075     if (sym->isspilt || sym->nRegs == 0) {
1076
1077       DEBUGpic16_emitcode(";","%d",__LINE__);
1078         /* rematerialize it NOW */
1079         if (sym->remat) {
1080
1081             sym->aop = op->aop = aop =
1082                                       aopForRemat (op);
1083             aop->size = getSize(sym->type);
1084             //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1085             return;
1086         }
1087
1088 #if 1
1089         if (sym->accuse) {
1090             int i;
1091             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1092             aop->size = getSize(sym->type);
1093             for ( i = 0 ; i < 1 ; i++ ) {
1094                 aop->aopu.aop_str[i] = accUse[i];
1095 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1096             }
1097             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1098             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1099             return;  
1100         }
1101 #endif
1102
1103 #if 1
1104         if (sym->ruonly ) {
1105           /*
1106           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1107           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1108           //pic16_allocDirReg (IC_LEFT(ic));
1109           aop->size = getSize(sym->type);
1110           */
1111
1112           unsigned i;
1113
1114           aop = op->aop = sym->aop = newAsmop(AOP_STR);
1115           aop->size = getSize(sym->type);
1116           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1117             aop->aopu.aop_str[i] = fReturn[i];
1118
1119           DEBUGpic16_emitcode(";","%d",__LINE__);
1120           return;
1121         }
1122 #endif
1123         /* else spill location  */
1124         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1125             /* force a new aop if sizes differ */
1126             sym->usl.spillLoc->aop = NULL;
1127         }
1128
1129 #if 0
1130         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1131                             __FUNCTION__,__LINE__,
1132                             sym->usl.spillLoc->rname,
1133                             sym->rname, sym->usl.spillLoc->offset);
1134 #endif
1135
1136         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1137         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1138         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1139                                           getSize(sym->type), 
1140                                           sym->usl.spillLoc->offset, op);
1141         aop->size = getSize(sym->type);
1142
1143         return;
1144     }
1145
1146     {
1147       sym_link *type = operandType(op);
1148 #if 0
1149       if(IS_PTR_CONST(type)) 
1150 #else
1151       if(IS_CODEPTR(type)) 
1152 #endif
1153         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1154     }
1155
1156     /* must be in a register */
1157     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1158     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1159     aop->size = sym->nRegs;
1160     for ( i = 0 ; i < sym->nRegs ;i++)
1161         aop->aopu.aop_reg[i] = sym->regs[i];
1162 }
1163
1164 /*-----------------------------------------------------------------*/
1165 /* pic16_freeAsmop - free up the asmop given to an operand               */
1166 /*----------------------------------------------------------------*/
1167 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1168 {   
1169     asmop *aop ;
1170
1171     if (!op)
1172         aop = aaop;
1173     else 
1174         aop = op->aop;
1175
1176     if (!aop)
1177         return ;
1178
1179     if (aop->freed)
1180         goto dealloc; 
1181
1182     aop->freed = 1;
1183
1184     /* depending on the asmop type only three cases need work AOP_RO
1185        , AOP_R1 && AOP_STK */
1186 #if 1
1187     switch (aop->type) {
1188         case AOP_FSR0 :
1189             if (_G.fsr0Pushed ) {
1190                 if (pop) {
1191                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1192                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1193 //                    pic16_emitcode ("pop","ar0");
1194                     _G.fsr0Pushed--;
1195                 }
1196             }
1197             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1198             break;
1199
1200         case AOP_FSR2 :
1201             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1202             break;
1203
1204         case AOP_R0 :
1205             if (_G.r0Pushed ) {
1206                 if (pop) {
1207                     pic16_emitcode ("pop","ar0");     
1208                     _G.r0Pushed--;
1209                 }
1210             }
1211             bitVectUnSetBit(ic->rUsed,R0_IDX);
1212             break;
1213
1214         case AOP_R1 :
1215             if (_G.r1Pushed ) {
1216                 if (pop) {
1217                     pic16_emitcode ("pop","ar1");
1218                     _G.r1Pushed--;
1219                 }
1220             }
1221             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1222             break;
1223
1224         case AOP_STK :
1225         {
1226             int sz = aop->size;    
1227             int stk = aop->aopu.aop_stk + aop->size;
1228             bitVectUnSetBit(ic->rUsed,R0_IDX);
1229             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1230
1231             getFreePtr(ic,&aop,FALSE);
1232             
1233             if (options.stack10bit)
1234             {
1235                 /* I'm not sure what to do here yet... */
1236                 /* #STUB */
1237                 fprintf(stderr, 
1238                         "*** Warning: probably generating bad code for "
1239                         "10 bit stack mode.\n");
1240             }
1241             
1242             if (stk) {
1243                 pic16_emitcode ("mov","a,_bp");
1244                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1245                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1246             } else {
1247                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1248             }
1249
1250             while (sz--) {
1251                 pic16_emitcode("pop","acc");
1252                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1253                 if (!sz) break;
1254                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1255             }
1256             op->aop = aop;
1257             pic16_freeAsmop(op,NULL,ic,TRUE);
1258             if (_G.r0Pushed) {
1259                 pic16_emitcode("pop","ar0");
1260                 _G.r0Pushed--;
1261             }
1262
1263             if (_G.r1Pushed) {
1264                 pic16_emitcode("pop","ar1");
1265                 _G.r1Pushed--;
1266             }       
1267         }
1268     }
1269 #endif
1270
1271 dealloc:
1272     /* all other cases just dealloc */
1273     if (op ) {
1274         op->aop = NULL;
1275         if (IS_SYMOP(op)) {
1276             OP_SYMBOL(op)->aop = NULL;    
1277             /* if the symbol has a spill */
1278             if (SPIL_LOC(op))
1279                 SPIL_LOC(op)->aop = NULL;
1280         }
1281     }
1282 }
1283
1284 /*-----------------------------------------------------------------*/
1285 /* pic16_aopGet - for fetching value of the aop                          */
1286 /*-----------------------------------------------------------------*/
1287 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1288 {
1289     char *s = buffer ;
1290     char *rs;
1291
1292     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1293
1294     /* offset is greater than size then zero */
1295     if (offset > (aop->size - 1) &&
1296         aop->type != AOP_LIT)
1297         return zero;
1298
1299     /* depending on type */
1300     switch (aop->type) {
1301
1302     case AOP_FSR0:
1303     case AOP_FSR2:
1304       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1305       rs = Safe_calloc(1, strlen(s)+1);
1306       strcpy(rs, s);
1307       return (rs);
1308       
1309 #if 0
1310       /* if we need to increment it */
1311       while (offset > aop->coff)
1312         {
1313           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1314           aop->coff++;
1315         }
1316
1317       while (offset < aop->coff)
1318         {
1319           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1320           aop->coff--;
1321         }
1322       aop->coff = offset;
1323       if (aop->paged)
1324         {
1325           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1326           return (dname ? "acc" : "a");
1327         }
1328       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1329       rs = Safe_calloc (1, strlen (s) + 1);
1330       strcpy (rs, s);
1331       return rs;
1332 #endif
1333
1334         
1335     case AOP_IMMD:
1336         if (bit16) 
1337             sprintf (s,"%s",aop->aopu.aop_immd);
1338         else
1339             if (offset) 
1340                 sprintf(s,"(%s >> %d)",
1341                         aop->aopu.aop_immd,
1342                         offset*8);
1343             else
1344                 sprintf(s,"%s",
1345                         aop->aopu.aop_immd);
1346         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1347         rs = Safe_calloc(1,strlen(s)+1);
1348         strcpy(rs,s);   
1349         return rs;
1350         
1351     case AOP_DIR:
1352       if (offset) {
1353         sprintf(s,"(%s + %d)",
1354                 aop->aopu.aop_dir,
1355                 offset);
1356         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1357       } else
1358             sprintf(s,"%s",aop->aopu.aop_dir);
1359         rs = Safe_calloc(1,strlen(s)+1);
1360         strcpy(rs,s);   
1361         return rs;
1362         
1363     case AOP_REG:
1364       //if (dname) 
1365       //    return aop->aopu.aop_reg[offset]->dname;
1366       //else
1367             return aop->aopu.aop_reg[offset]->name;
1368         
1369     case AOP_CRY:
1370       //pic16_emitcode(";","%d",__LINE__);
1371       return aop->aopu.aop_dir;
1372         
1373     case AOP_ACC:
1374         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1375 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1376 //        assert( 0 );
1377 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1378         rs = Safe_strdup("WREG");
1379         return (rs);
1380
1381     case AOP_LIT:
1382         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1383         rs = Safe_calloc(1,strlen(s)+1);
1384         strcpy(rs,s);   
1385         return rs;
1386         
1387     case AOP_STR:
1388         aop->coff = offset ;
1389         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1390             dname)
1391             return "acc";
1392         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1393         
1394         return aop->aopu.aop_str[offset];
1395         
1396     case AOP_PCODE:
1397       {
1398         pCodeOp *pcop = aop->aopu.pcop;
1399         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1400         if(pcop->name) {
1401           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1402           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1403           sprintf(s,"%s", pcop->name);
1404         } else
1405           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1406
1407       }
1408       rs = Safe_calloc(1,strlen(s)+1);
1409       strcpy(rs,s);   
1410       return rs;
1411
1412       case AOP_STK:
1413 //        pCodeOp *pcop = aop->aop
1414         break;
1415
1416     }
1417
1418     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1419     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1420            "aopget got unsupported aop->type");
1421     exit(0);
1422 }
1423
1424
1425 /*-----------------------------------------------------------------*/
1426 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1427 /*-----------------------------------------------------------------*/
1428 pCodeOp *pic16_popGetTempReg(void)
1429 {
1430   pCodeOp *pcop;
1431   symbol *cfunc;
1432
1433 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1434
1435         cfunc = currFunc;
1436         currFunc = NULL;
1437
1438         pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1439         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1440                 PCOR(pcop)->r->wasUsed=1;
1441                 PCOR(pcop)->r->isFree=0;
1442
1443                 /* push value on stack */
1444                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1445         }
1446
1447         currFunc = cfunc;
1448
1449   return pcop;
1450 }
1451
1452 /*-----------------------------------------------------------------*/
1453 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1454 /*-----------------------------------------------------------------*/
1455 void pic16_popReleaseTempReg(pCodeOp *pcop)
1456 {
1457         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1458
1459         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1460                 PCOR(pcop)->r->isFree = 1;
1461                 
1462                 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1463         }
1464 }
1465 /*-----------------------------------------------------------------*/
1466 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1467 /*-----------------------------------------------------------------*/
1468 pCodeOp *pic16_popGetLabel(unsigned int key)
1469 {
1470
1471   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1472
1473   if(key>max_key)
1474     max_key = key;
1475
1476   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1477 }
1478
1479 /*-----------------------------------------------------------------*/
1480 /* pic16_popCopyReg - copy a pcode operator                              */
1481 /*-----------------------------------------------------------------*/
1482 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1483 {
1484   pCodeOpReg *pcor;
1485
1486   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1487   pcor->pcop.type = pc->pcop.type;
1488   if(pc->pcop.name) {
1489     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1490       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1491   } else
1492     pcor->pcop.name = NULL;
1493
1494   pcor->r = pc->r;
1495   pcor->rIdx = pc->rIdx;
1496   pcor->r->wasUsed=1;
1497
1498 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1499
1500   return PCOP(pcor);
1501 }
1502
1503 /*-----------------------------------------------------------------*/
1504 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1505 /*-----------------------------------------------------------------*/
1506 pCodeOp *pic16_popGetLit(unsigned int lit)
1507 {
1508   return pic16_newpCodeOpLit(lit);
1509 }
1510
1511 /*-----------------------------------------------------------------*/
1512 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1513 /*-----------------------------------------------------------------*/
1514 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1515 {
1516   return pic16_newpCodeOpLit2(lit, arg2);
1517 }
1518
1519
1520 /*-----------------------------------------------------------------*/
1521 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1522 /*-----------------------------------------------------------------*/
1523 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1524 {
1525   return pic16_newpCodeOpImmd(name, offset,index, 0);
1526 }
1527
1528
1529 /*-----------------------------------------------------------------*/
1530 /* pic16_popGet - asm operator to pcode operator conversion              */
1531 /*-----------------------------------------------------------------*/
1532 pCodeOp *pic16_popGetWithString(char *str)
1533 {
1534   pCodeOp *pcop;
1535
1536
1537   if(!str) {
1538     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1539     exit (1);
1540   }
1541
1542   pcop = pic16_newpCodeOp(str,PO_STR);
1543
1544   return pcop;
1545 }
1546
1547 /*-----------------------------------------------------------------*/
1548 /* pic16_popRegFromString -                                        */
1549 /*-----------------------------------------------------------------*/
1550 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1551 {
1552
1553   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1554   pcop->type = PO_DIR;
1555
1556   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1557   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1558
1559   if(!str)
1560     str = "BAD_STRING";
1561
1562   pcop->name = Safe_calloc(1,strlen(str)+1);
1563   strcpy(pcop->name,str);
1564
1565   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1566
1567   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1568   if(PCOR(pcop)->r == NULL) {
1569 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1570 //              __FUNCTION__, __LINE__, str, size, offset);
1571
1572
1573 //    PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1574         fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1575
1576 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d - had to alloc by reg name",__LINE__,pcop->name,size,offset);
1577   } else {
1578 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d",__LINE__,pcop->name,size,offset);
1579   }
1580   PCOR(pcop)->instance = offset;
1581
1582   return pcop;
1583 }
1584
1585 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1586 {
1587   pCodeOp *pcop;
1588
1589 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1590
1591         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1592         PCOR(pcop)->rIdx = rIdx;
1593         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1594
1595         PCOR(pcop)->r->isFree = 0;
1596         PCOR(pcop)->r->wasUsed = 1;
1597
1598         pcop->type = PCOR(pcop)->r->pc_type;
1599
1600   return pcop;
1601 }
1602
1603 /*---------------------------------------------------------------------------------*/
1604 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1605 /*                 VR 030601                                                       */
1606 /*---------------------------------------------------------------------------------*/
1607 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1608 {
1609   pCodeOpReg2 *pcop2;
1610   pCodeOp *temp;
1611   
1612         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1613
1614         /* comment the following check, so errors to throw up */
1615 //      if(!pcop2)return NULL;
1616
1617         temp = pic16_popGet(aop_dst, offset);
1618         pcop2->pcop2 = temp;
1619         
1620   return PCOP(pcop2);
1621 }
1622
1623
1624
1625 /*--------------------------------------------------------------------------------.-*/
1626 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1627 /*                  VR 030601 , adapted by Hans Dorn                                */
1628 /*--------------------------------------------------------------------------------.-*/
1629 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1630 {
1631   pCodeOpReg2 *pcop2;
1632  
1633         pcop2 = (pCodeOpReg2 *)src;
1634         pcop2->pcop2 = dst;
1635         
1636         return PCOP(pcop2);
1637 }
1638
1639
1640
1641 /*---------------------------------------------------------------------------------*/
1642 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1643 /*                     movff instruction                                           */
1644 /*---------------------------------------------------------------------------------*/
1645 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1646 {
1647   pCodeOpReg2 *pcop2;
1648
1649         if(!noalloc) {
1650                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1651                 pcop2->pcop2 = pic16_popCopyReg(dst);
1652         } else {
1653                 /* the pCodeOp may be already allocated */
1654                 pcop2 = (pCodeOpReg2 *)(src);
1655                 pcop2->pcop2 = (pCodeOp *)(dst);
1656         }
1657
1658   return PCOP(pcop2);
1659 }
1660
1661
1662 /*-----------------------------------------------------------------*/
1663 /* pic16_popGet - asm operator to pcode operator conversion              */
1664 /*-----------------------------------------------------------------*/
1665 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1666 {
1667   //char *s = buffer ;
1668   char *rs;
1669   pCodeOp *pcop;
1670
1671     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1672     /* offset is greater than
1673     size then zero */
1674
1675 //    if (offset > (aop->size - 1) &&
1676 //        aop->type != AOP_LIT)
1677 //      return NULL;  //zero;
1678
1679     /* depending on type */
1680     switch (aop->type) {
1681         
1682     case AOP_R0:
1683     case AOP_R1:
1684     case AOP_DPTR:
1685     case AOP_DPTR2:
1686         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1687         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1688         assert( 0 );
1689         return NULL;
1690
1691
1692     case AOP_FSR0:
1693     case AOP_FSR2:
1694       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1695       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
1696       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1697       PCOR(pcop)->r->wasUsed = 1;
1698       PCOR(pcop)->r->isFree = 0;
1699       
1700       PCOR(pcop)->instance = offset;
1701       pcop->type = PCOR(pcop)->r->pc_type;
1702       return (pcop);
1703
1704     case AOP_IMMD:
1705       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1706       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1707
1708     case AOP_ACC:
1709       {
1710         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1711
1712         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1713
1714         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1715         
1716         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1717         PCOR(pcop)->rIdx = rIdx;
1718         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1719         PCOR(pcop)->r->wasUsed=1;
1720         PCOR(pcop)->r->isFree=0;
1721
1722         PCOR(pcop)->instance = offset;
1723         pcop->type = PCOR(pcop)->r->pc_type;
1724 //      rs = aop->aopu.aop_reg[offset]->name;
1725 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1726         return pcop;
1727
1728
1729 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1730 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1731
1732 //      assert( 0 );
1733       }
1734         
1735     case AOP_DIR:
1736       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1737       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1738         
1739     case AOP_REG:
1740       {
1741         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1742
1743         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1744         
1745         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1746 //      pcop->type = PO_GPR_REGISTER;
1747         PCOR(pcop)->rIdx = rIdx;
1748         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
1749         PCOR(pcop)->r->wasUsed=1;
1750         PCOR(pcop)->r->isFree=0;
1751
1752         PCOR(pcop)->instance = offset;
1753         pcop->type = PCOR(pcop)->r->pc_type;
1754         rs = aop->aopu.aop_reg[offset]->name;
1755         DEBUGpic16_emitcode(";","%d regiser idx = %d name = %s",__LINE__,rIdx,rs);
1756         return pcop;
1757       }
1758
1759     case AOP_CRY:
1760         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1761
1762       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1763       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1764       //if(PCOR(pcop)->r == NULL)
1765       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1766       return pcop;
1767         
1768     case AOP_LIT:
1769         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1770       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1771
1772     case AOP_STR:
1773       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1774       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1775
1776       /*
1777       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1778       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1779       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1780       pcop->type = PCOR(pcop)->r->pc_type;
1781       pcop->name = PCOR(pcop)->r->name;
1782
1783       return pcop;
1784       */
1785
1786     case AOP_PCODE:
1787       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1788                           __LINE__, 
1789                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1790       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1791 #if 1
1792         switch( aop->aopu.pcop->type ) {
1793                 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1794                 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1795                 default:
1796                         assert( 0 );    /* should never reach here */;
1797         }
1798 #else
1799       PCOI(pcop)->offset = offset;
1800 #endif
1801       return pcop;
1802     }
1803
1804     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1805            "pic16_popGet got unsupported aop->type");
1806     exit(0);
1807 }
1808 /*-----------------------------------------------------------------*/
1809 /* pic16_aopPut - puts a string for a aop                                */
1810 /*-----------------------------------------------------------------*/
1811 void pic16_aopPut (asmop *aop, char *s, int offset)
1812 {
1813     char *d = buffer ;
1814     symbol *lbl ;
1815
1816     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1817
1818     if (aop->size && offset > ( aop->size - 1)) {
1819         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1820                "pic16_aopPut got offset > aop->size");
1821         exit(0);
1822     }
1823
1824     /* will assign value to value */
1825     /* depending on where it is ofcourse */
1826     switch (aop->type) {
1827     case AOP_DIR:
1828       if (offset) {
1829         sprintf(d,"(%s + %d)",
1830                 aop->aopu.aop_dir,offset);
1831         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1832
1833       } else
1834             sprintf(d,"%s",aop->aopu.aop_dir);
1835         
1836         if (strcmp(d,s)) {
1837           DEBUGpic16_emitcode(";","%d",__LINE__);
1838           if(strcmp(s,"W"))
1839             pic16_emitcode("movf","%s,w",s);
1840           pic16_emitcode("movwf","%s",d);
1841
1842           if(strcmp(s,"W")) {
1843             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1844             if(offset >= aop->size) {
1845               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1846               break;
1847             } else
1848               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1849           }
1850
1851           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1852
1853
1854         }
1855         break;
1856         
1857     case AOP_REG:
1858       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1859         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1860           /*
1861             if (*s == '@'           ||
1862                 strcmp(s,"r0") == 0 ||
1863                 strcmp(s,"r1") == 0 ||
1864                 strcmp(s,"r2") == 0 ||
1865                 strcmp(s,"r3") == 0 ||
1866                 strcmp(s,"r4") == 0 ||
1867                 strcmp(s,"r5") == 0 ||
1868                 strcmp(s,"r6") == 0 || 
1869                 strcmp(s,"r7") == 0 )
1870                 pic16_emitcode("mov","%s,%s  ; %d",
1871                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1872             else
1873           */
1874
1875           if(strcmp(s,"W")==0 )
1876             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
1877
1878           pic16_emitcode("movwf","%s",
1879                    aop->aopu.aop_reg[offset]->name);
1880
1881           if(strcmp(s,zero)==0) {
1882             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1883
1884           } else if(strcmp(s,"W")==0) {
1885             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1886             pcop->type = PO_GPR_REGISTER;
1887
1888             PCOR(pcop)->rIdx = -1;
1889             PCOR(pcop)->r = NULL;
1890
1891             DEBUGpic16_emitcode(";","%d",__LINE__);
1892             pcop->name = Safe_strdup(s);
1893             pic16_emitpcode(POC_MOVFW,pcop);
1894             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1895           } else if(strcmp(s,one)==0) {
1896             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1897             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1898           } else {
1899             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1900           }
1901         }
1902         break;
1903         
1904     case AOP_DPTR:
1905     case AOP_DPTR2:
1906     
1907     if (aop->type == AOP_DPTR2)
1908     {
1909         genSetDPTR(1);
1910     }
1911     
1912         if (aop->code) {
1913             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1914                    "pic16_aopPut writting to code space");
1915             exit(0);
1916         }
1917         
1918         while (offset > aop->coff) {
1919             aop->coff++;
1920             pic16_emitcode ("inc","dptr");
1921         }
1922         
1923         while (offset < aop->coff) {
1924             aop->coff-- ;
1925             pic16_emitcode("lcall","__decdptr");
1926         }
1927         
1928         aop->coff = offset;
1929         
1930         /* if not in accumulater */
1931         MOVA(s);        
1932         
1933         pic16_emitcode ("movx","@dptr,a");
1934         
1935     if (aop->type == AOP_DPTR2)
1936     {
1937         genSetDPTR(0);
1938     }
1939         break;
1940         
1941     case AOP_R0:
1942     case AOP_R1:
1943         while (offset > aop->coff) {
1944             aop->coff++;
1945             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1946         }
1947         while (offset < aop->coff) {
1948             aop->coff-- ;
1949             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1950         }
1951         aop->coff = offset;
1952         
1953         if (aop->paged) {
1954             MOVA(s);           
1955             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1956             
1957         } else
1958             if (*s == '@') {
1959                 MOVA(s);
1960                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1961             } else
1962                 if (strcmp(s,"r0") == 0 ||
1963                     strcmp(s,"r1") == 0 ||
1964                     strcmp(s,"r2") == 0 ||
1965                     strcmp(s,"r3") == 0 ||
1966                     strcmp(s,"r4") == 0 ||
1967                     strcmp(s,"r5") == 0 ||
1968                     strcmp(s,"r6") == 0 || 
1969                     strcmp(s,"r7") == 0 ) {
1970                     char buffer[10];
1971                     sprintf(buffer,"a%s",s);
1972                     pic16_emitcode("mov","@%s,%s",
1973                              aop->aopu.aop_ptr->name,buffer);
1974                 } else
1975                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1976         
1977         break;
1978         
1979     case AOP_STK:
1980         if (strcmp(s,"a") == 0)
1981             pic16_emitcode("push","acc");
1982         else
1983             pic16_emitcode("push","%s",s);
1984         
1985         break;
1986         
1987     case AOP_CRY:
1988         /* if bit variable */
1989         if (!aop->aopu.aop_dir) {
1990             pic16_emitcode("clr","a");
1991             pic16_emitcode("rlc","a");
1992         } else {
1993             if (s == zero) 
1994                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1995             else
1996                 if (s == one)
1997                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1998                 else
1999                     if (!strcmp(s,"c"))
2000                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2001                     else {
2002                         lbl = newiTempLabel(NULL);
2003                         
2004                         if (strcmp(s,"a")) {
2005                             MOVA(s);
2006                         }
2007                         pic16_emitcode("clr","c");
2008                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2009                         pic16_emitcode("cpl","c");
2010                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2011                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2012                     }
2013         }
2014         break;
2015         
2016     case AOP_STR:
2017         aop->coff = offset;
2018         if (strcmp(aop->aopu.aop_str[offset],s))
2019             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2020         break;
2021         
2022     case AOP_ACC:
2023         aop->coff = offset;
2024         if (!offset && (strcmp(s,"acc") == 0))
2025             break;
2026         
2027         if (strcmp(aop->aopu.aop_str[offset],s))
2028             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2029         break;
2030
2031     default :
2032         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2033                "pic16_aopPut got unsupported aop->type");
2034         exit(0);    
2035     }    
2036
2037 }
2038
2039 /*-----------------------------------------------------------------*/
2040 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
2041 /*-----------------------------------------------------------------*/
2042 static void mov2w (asmop *aop, int offset)
2043 {
2044
2045 //  if(!aop)
2046 //    return;
2047
2048         DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2049
2050         if(is_LitAOp(aop))
2051                 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2052         else
2053                 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2054
2055 }
2056
2057 static void mov2f(asmop *dst, asmop *src, int offset)
2058 {
2059   if(is_LitAOp(src)) {
2060           pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2061           pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2062         } else {
2063           pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2064                                     pic16_popGet(dst, offset)));
2065         }
2066 }
2067
2068
2069 /* push pcop into stack */
2070 void pic16_pushpCodeOp(pCodeOp *pcop)
2071 {
2072 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2073         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
2074 }
2075
2076 /* pop pcop from stack */
2077 void pic16_poppCodeOp(pCodeOp *pcop)
2078 {
2079         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
2080 }
2081
2082
2083 /*-----------------------------------------------------------------*/
2084 /* pushw - pushes wreg to stack                                    */
2085 /*-----------------------------------------------------------------*/
2086 void pushw(void)
2087 {
2088         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2089         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
2090 }
2091
2092                 
2093 /*-----------------------------------------------------------------*/
2094 /* pushaop - pushes aop to stack                                   */
2095 /*-----------------------------------------------------------------*/
2096 void pushaop(asmop *aop, int offset)
2097 {
2098         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2099         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
2100 }
2101
2102 /*-----------------------------------------------------------------*/
2103 /* popaop - pops aop from stack                                    */
2104 /*-----------------------------------------------------------------*/
2105 void popaop(asmop *aop, int offset)
2106 {
2107         DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2108         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
2109 }
2110
2111 void popaopidx(asmop *aop, int offset, int index)
2112 {
2113   int ofs=1;
2114
2115         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2116
2117         if(STACK_MODEL_LARGE)ofs++;
2118
2119         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2120         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
2121 }
2122
2123 /*-----------------------------------------------------------------*/
2124 /* reAdjustPreg - points a register back to where it should        */
2125 /*-----------------------------------------------------------------*/
2126 static void reAdjustPreg (asmop *aop)
2127 {
2128     int size ;
2129
2130     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2131     aop->coff = 0;
2132     if ((size = aop->size) <= 1)
2133         return ;
2134     size-- ;
2135     switch (aop->type) {
2136         case AOP_R0 :
2137         case AOP_R1 :
2138             while (size--)
2139                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2140             break;          
2141         case AOP_DPTR :
2142         case AOP_DPTR2:
2143             if (aop->type == AOP_DPTR2)
2144             {
2145                 genSetDPTR(1);
2146             } 
2147             while (size--)
2148             {
2149                 pic16_emitcode("lcall","__decdptr");
2150             }
2151                 
2152             if (aop->type == AOP_DPTR2)
2153             {
2154                 genSetDPTR(0);
2155             }                
2156             break;  
2157
2158     }   
2159
2160 }
2161
2162
2163 #if 0
2164 /*-----------------------------------------------------------------*/
2165 /* opIsGptr: returns non-zero if the passed operand is             */   
2166 /* a generic pointer type.                                         */
2167 /*-----------------------------------------------------------------*/ 
2168 static int opIsGptr(operand *op)
2169 {
2170     sym_link *type = operandType(op);
2171     
2172     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2173     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2174     {
2175         return 1;
2176     }
2177     return 0;        
2178 }
2179 #endif
2180
2181 /*-----------------------------------------------------------------*/
2182 /* pic16_getDataSize - get the operand data size                         */
2183 /*-----------------------------------------------------------------*/
2184 int pic16_getDataSize(operand *op)
2185 {
2186     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2187
2188
2189     return AOP_SIZE(op);
2190
2191     // tsd- in the pic port, the genptr size is 1, so this code here
2192     // fails. ( in the 8051 port, the size was 4).
2193 #if 0
2194     int size;
2195     size = AOP_SIZE(op);
2196     if (size == GPTRSIZE)
2197     {
2198         sym_link *type = operandType(op);
2199         if (IS_GENPTR(type))
2200         {
2201             /* generic pointer; arithmetic operations
2202              * should ignore the high byte (pointer type).
2203              */
2204             size--;
2205     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2206         }
2207     }
2208     return size;
2209 #endif
2210 }
2211
2212 /*-----------------------------------------------------------------*/
2213 /* pic16_outAcc - output Acc                                             */
2214 /*-----------------------------------------------------------------*/
2215 void pic16_outAcc(operand *result)
2216 {
2217   int size,offset;
2218   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2219   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2220
2221
2222   size = pic16_getDataSize(result);
2223   if(size){
2224     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2225     size--;
2226     offset = 1;
2227     /* unsigned or positive */
2228     while(size--)
2229       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2230   }
2231
2232 }
2233
2234 /*-----------------------------------------------------------------*/
2235 /* pic16_outBitC - output a bit C                                  */
2236 /*                 Move to result the value of Carry flag -- VR    */
2237 /*-----------------------------------------------------------------*/
2238 void pic16_outBitC(operand *result)
2239 {
2240   int i;
2241
2242     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2243     /* if the result is bit */
2244     if (AOP_TYPE(result) == AOP_CRY) {
2245         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2246         pic16_aopPut(AOP(result),"c",0);
2247     } else {
2248
2249         i = AOP_SIZE(result);
2250         while(i--) {
2251                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2252         }
2253         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2254         
2255 /*
2256         pic16_emitcode("clr","a  ; %d", __LINE__);
2257         pic16_emitcode("rlc","a");
2258         pic16_outAcc(result);
2259 */
2260     }
2261 }
2262
2263 /*-----------------------------------------------------------------*/
2264 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2265 /*-----------------------------------------------------------------*/
2266 void pic16_toBoolean(operand *oper)
2267 {
2268     int size = AOP_SIZE(oper) - 1;
2269     int offset = 1;
2270
2271     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2272
2273     if ( AOP_TYPE(oper) != AOP_ACC) {
2274       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2275     }
2276     while (size--) {
2277       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2278     }
2279 }
2280
2281
2282 #if !defined(GEN_Not)
2283 /*-----------------------------------------------------------------*/
2284 /* genNot - generate code for ! operation                          */
2285 /*-----------------------------------------------------------------*/
2286 static void pic16_genNot (iCode *ic)
2287 {
2288   symbol *tlbl;
2289   int size;
2290
2291   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2292   /* assign asmOps to operand & result */
2293   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2294   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2295
2296   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2297   /* if in bit space then a special case */
2298   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2299     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2300       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2301       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2302     } else {
2303       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2304       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2305       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2306     }
2307     goto release;
2308   }
2309
2310   size = AOP_SIZE(IC_LEFT(ic));
2311   if(size == 1) {
2312     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2313     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2314     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2315     goto release;
2316   }
2317   pic16_toBoolean(IC_LEFT(ic));
2318
2319   tlbl = newiTempLabel(NULL);
2320   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2321   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2322   pic16_outBitC(IC_RESULT(ic));
2323
2324  release:    
2325   /* release the aops */
2326   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2327   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2328 }
2329 #endif
2330
2331
2332 #if !defined(GEN_Cpl)
2333 /*-----------------------------------------------------------------*/
2334 /* genCpl - generate code for complement                           */
2335 /*-----------------------------------------------------------------*/
2336 static void pic16_genCpl (iCode *ic)
2337 {
2338     int offset = 0;
2339     int size ;
2340
2341
2342     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2343     /* assign asmOps to operand & result */
2344     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2345     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2346
2347     /* if both are in bit space then 
2348     a special case */
2349     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2350         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2351
2352         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2353         pic16_emitcode("cpl","c"); 
2354         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2355         goto release; 
2356     } 
2357
2358     size = AOP_SIZE(IC_RESULT(ic));
2359     while (size--) {
2360 /*
2361         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2362         MOVA(l);       
2363         pic16_emitcode("cpl","a");
2364         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2365 */
2366         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2367               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2368         } else {
2369                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2370                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2371         }
2372         offset++;
2373
2374     }
2375
2376
2377 release:
2378     /* release the aops */
2379     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2380     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2381 }
2382 #endif
2383
2384 /*-----------------------------------------------------------------*/
2385 /* genUminusFloat - unary minus for floating points                */
2386 /*-----------------------------------------------------------------*/
2387 static void genUminusFloat(operand *op,operand *result)
2388 {
2389     int size ,offset =0 ;
2390     char *l;
2391
2392     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2393     /* for this we just need to flip the 
2394     first it then copy the rest in place */
2395     size = AOP_SIZE(op) - 1;
2396     l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2397
2398     MOVA(l);    
2399
2400     pic16_emitcode("cpl","acc.7");
2401     pic16_aopPut(AOP(result),"a",3);    
2402
2403     while(size--) {
2404         pic16_aopPut(AOP(result),
2405                pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2406                offset);
2407         offset++;
2408     }          
2409 }
2410
2411 /*-----------------------------------------------------------------*/
2412 /* genUminus - unary minus code generation                         */
2413 /*-----------------------------------------------------------------*/
2414 static void genUminus (iCode *ic)
2415 {
2416   int size, i;
2417   sym_link *optype, *rtype;
2418
2419         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2420         
2421         /* assign asmops */
2422         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2423         pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2424
2425         /* if both in bit space then special case */
2426         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2427                 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2428
2429                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2430                 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2431                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2432                 
2433                 goto release; 
2434         } 
2435
2436         optype = operandType(IC_LEFT(ic));
2437         rtype = operandType(IC_RESULT(ic));
2438
2439         /* if float then do float stuff */
2440         if (IS_FLOAT(optype)) {
2441                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2442                 goto release;
2443         }
2444
2445         /* otherwise subtract from zero by taking the 2's complement */
2446         size = AOP_SIZE(IC_LEFT(ic));
2447
2448         for(i=0; i<size; i++) {
2449                 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2450                         pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2451                 else {
2452                         pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2453                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2454                 }
2455         }
2456
2457         pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2458         for(i=1; i<size; i++) {
2459                 emitSKPNZ;
2460                 pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2461         }
2462
2463 release:
2464         /* release the aops */
2465         pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2466         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2467 }
2468
2469 /*-----------------------------------------------------------------*/
2470 /* saveRegisters - will look for a call and save the registers     */
2471 /*-----------------------------------------------------------------*/
2472 static void saveRegisters(iCode *lic) 
2473 {
2474     int i;
2475     iCode *ic;
2476     bitVect *rsave;
2477     sym_link *dtype;
2478
2479     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2480     /* look for call */
2481     for (ic = lic ; ic ; ic = ic->next) 
2482         if (ic->op == CALL || ic->op == PCALL)
2483             break;
2484
2485     if (!ic) {
2486         fprintf(stderr,"found parameter push with no function call\n");
2487         return ;
2488     }
2489
2490     /* if the registers have been saved already then
2491     do nothing */
2492     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2493         return ;
2494
2495     /* find the registers in use at this time 
2496     and push them away to safety */
2497     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2498                           ic->rUsed);
2499
2500     ic->regsSaved = 1;
2501     if (options.useXstack) {
2502         if (bitVectBitValue(rsave,R0_IDX))
2503             pic16_emitcode("mov","b,r0");
2504         pic16_emitcode("mov","r0,%s",spname);
2505         for (i = 0 ; i < pic16_nRegs ; i++) {
2506             if (bitVectBitValue(rsave,i)) {
2507                 if (i == R0_IDX)
2508                     pic16_emitcode("mov","a,b");
2509                 else
2510                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2511                 pic16_emitcode("movx","@r0,a");
2512                 pic16_emitcode("inc","r0");
2513             }
2514         }
2515         pic16_emitcode("mov","%s,r0",spname);
2516         if (bitVectBitValue(rsave,R0_IDX))
2517             pic16_emitcode("mov","r0,b");           
2518     }// else
2519     //for (i = 0 ; i < pic16_nRegs ; i++) {
2520     //    if (bitVectBitValue(rsave,i))
2521     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2522     //}
2523
2524     dtype = operandType(IC_LEFT(ic));
2525     if (currFunc && dtype && 
2526         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2527         IFFUNC_ISISR(currFunc->type) &&
2528         !ic->bankSaved) 
2529
2530         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2531
2532 }
2533 /*-----------------------------------------------------------------*/
2534 /* unsaveRegisters - pop the pushed registers                      */
2535 /*-----------------------------------------------------------------*/
2536 static void unsaveRegisters (iCode *ic)
2537 {
2538     int i;
2539     bitVect *rsave;
2540
2541     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2542     /* find the registers in use at this time 
2543     and push them away to safety */
2544     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2545                           ic->rUsed);
2546     
2547     if (options.useXstack) {
2548         pic16_emitcode("mov","r0,%s",spname);   
2549         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2550             if (bitVectBitValue(rsave,i)) {
2551                 pic16_emitcode("dec","r0");
2552                 pic16_emitcode("movx","a,@r0");
2553                 if (i == R0_IDX)
2554                     pic16_emitcode("mov","b,a");
2555                 else
2556                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2557             }       
2558
2559         }
2560         pic16_emitcode("mov","%s,r0",spname);
2561         if (bitVectBitValue(rsave,R0_IDX))
2562             pic16_emitcode("mov","r0,b");
2563     } //else
2564     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2565     //    if (bitVectBitValue(rsave,i))
2566     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2567     //}
2568
2569 }  
2570
2571 #if 0  // patch 14
2572 /*-----------------------------------------------------------------*/
2573 /* pushSide -                                                      */
2574 /*-----------------------------------------------------------------*/
2575 static void pushSide(operand * oper, int size)
2576 {
2577         int offset = 0;
2578     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2579         while (size--) {
2580                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2581                 if (AOP_TYPE(oper) != AOP_REG &&
2582                     AOP_TYPE(oper) != AOP_DIR &&
2583                     strcmp(l,"a") ) {
2584                         pic16_emitcode("mov","a,%s",l);
2585                         pic16_emitcode("push","acc");
2586                 } else
2587                         pic16_emitcode("push","%s",l);
2588         }
2589 }
2590 #endif // patch 14
2591
2592 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2593 {
2594 //              (AOP(left)->aopu.pcop->type == PO_DIR)?
2595
2596         if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2597                 pic16_emitpcode(POC_MOVFW, src);
2598                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2599         } else {
2600                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2601                         src, pic16_popGet(AOP(op), offset)));
2602         }
2603 }
2604
2605
2606 /*-----------------------------------------------------------------*/
2607 /* assignResultValue - assign results to oper, rescall==1 is       */
2608 /*                     called from genCall() or genPCall()         */
2609 /*-----------------------------------------------------------------*/
2610 static void assignResultValue(operand * oper, int rescall)
2611 {
2612   int size = AOP_SIZE(oper);
2613
2614         DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2615         DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2616
2617         if(rescall) {
2618                 /* assign result from a call/pcall function() */
2619                 
2620                 /* function results are stored in a special order,
2621                  * see top of file with Function return policy, or manual */
2622
2623                 if(size <= 4) {
2624                         /* 8-bits, result in WREG */
2625                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2626                         
2627                         if(size>1) {
2628                                 /* 16-bits, result in PRODL:WREG */
2629                                 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2630                         }
2631                         
2632                         if(size>2) {
2633                                 /* 24-bits, result in PRODH:PRODL:WREG */
2634                                 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2635                         }
2636                         
2637                         if(size>3) {
2638                                 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2639                                 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2640                         }
2641                 } else {
2642                         /* >32-bits, result on stack, and FSR0 points to beginning.
2643                          * Fix stack when done */
2644                          /* FIXME FIXME */
2645                         while (size--) {
2646 //                              DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2647 //                              DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2648                 
2649                                 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2650                                 GpsuedoStkPtr++;
2651                         }
2652                         
2653                         /* fix stack */
2654                         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2655                         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2656                         if(STACK_MODEL_LARGE) {
2657                                 emitSKPNC;
2658                                 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2659                         }
2660                 }                       
2661         } else {        
2662                 if(!GpsuedoStkPtr) {
2663 //                      DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2664                         /* The last byte in the assignment is in W */
2665                         size--;
2666                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2667                         GpsuedoStkPtr++;
2668                 }
2669
2670                 while (size--) {
2671 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2672 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2673                 
2674                         popaopidx(AOP(oper), size, GpsuedoStkPtr);
2675                         GpsuedoStkPtr++;
2676
2677 #if 0
2678 #if STACK_SUPPORT
2679                 if(!USE_STACK)
2680                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2681 #else
2682                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2683 #endif
2684 #endif
2685
2686                 }
2687         }
2688                 
2689 }
2690
2691
2692 /*-----------------------------------------------------------------*/
2693 /* genIpush - genrate code for pushing this gets a little complex  */
2694 /*-----------------------------------------------------------------*/
2695 static void genIpush (iCode *ic)
2696 {
2697   int size, offset=0;
2698
2699   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2700
2701
2702         pic16_aopOp(IC_LEFT(ic), ic, FALSE);
2703         
2704
2705         size = AOP_SIZE( IC_LEFT(ic) );
2706         
2707         while(size--) {
2708                 mov2w( AOP(IC_LEFT(ic)), offset );
2709                 pushw();
2710                 offset++;
2711         }
2712         
2713 #if 0
2714     int size, offset = 0 ;
2715     char *l;
2716
2717
2718     /* if this is not a parm push : ie. it is spill push 
2719     and spill push is always done on the local stack */
2720     if (!ic->parmPush) {
2721
2722         /* and the item is spilt then do nothing */
2723         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2724             return ;
2725
2726         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2727         size = AOP_SIZE(IC_LEFT(ic));
2728         /* push it on the stack */
2729         while(size--) {
2730             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2731             if (*l == '#') {
2732                 MOVA(l);
2733                 l = "acc";
2734             }
2735             pic16_emitcode("push","%s",l);
2736         }
2737         return ;        
2738     }
2739
2740     /* this is a paramter push: in this case we call
2741     the routine to find the call and save those
2742     registers that need to be saved */   
2743     saveRegisters(ic);
2744
2745     /* then do the push */
2746     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2747
2748
2749         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2750     size = AOP_SIZE(IC_LEFT(ic));
2751
2752     while (size--) {
2753         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2754         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2755             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2756             strcmp(l,"a") ) {
2757             pic16_emitcode("mov","a,%s",l);
2758             pic16_emitcode("push","acc");
2759         } else
2760             pic16_emitcode("push","%s",l);
2761     }       
2762
2763     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2764 #endif
2765 }
2766
2767 /*-----------------------------------------------------------------*/
2768 /* genIpop - recover the registers: can happen only for spilling   */
2769 /*-----------------------------------------------------------------*/
2770 static void genIpop (iCode *ic)
2771 {
2772   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2773 #if 0
2774     int size,offset ;
2775
2776
2777     /* if the temp was not pushed then */
2778     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2779         return ;
2780
2781     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2782     size = AOP_SIZE(IC_LEFT(ic));
2783     offset = (size-1);
2784     while (size--) 
2785         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2786                                    FALSE,TRUE));
2787
2788     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2789 #endif
2790 }
2791
2792 /*-----------------------------------------------------------------*/
2793 /* unsaverbank - restores the resgister bank from stack            */
2794 /*-----------------------------------------------------------------*/
2795 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2796 {
2797   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2798 #if 0
2799     int i;
2800     asmop *aop ;
2801     regs *r = NULL;
2802
2803     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2804     if (popPsw) {
2805         if (options.useXstack) {
2806             aop = newAsmop(0);
2807             r = getFreePtr(ic,&aop,FALSE);
2808             
2809             
2810             pic16_emitcode("mov","%s,_spx",r->name);
2811             pic16_emitcode("movx","a,@%s",r->name);
2812             pic16_emitcode("mov","psw,a");
2813             pic16_emitcode("dec","%s",r->name);
2814             
2815         }else
2816             pic16_emitcode ("pop","psw");
2817     }
2818
2819     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2820         if (options.useXstack) {       
2821             pic16_emitcode("movx","a,@%s",r->name);
2822             //pic16_emitcode("mov","(%s+%d),a",
2823             //       regspic16[i].base,8*bank+regspic16[i].offset);
2824             pic16_emitcode("dec","%s",r->name);
2825
2826         } else 
2827           pic16_emitcode("pop",""); //"(%s+%d)",
2828         //regspic16[i].base,8*bank); //+regspic16[i].offset);
2829     }
2830
2831     if (options.useXstack) {
2832
2833         pic16_emitcode("mov","_spx,%s",r->name);
2834         pic16_freeAsmop(NULL,aop,ic,TRUE);
2835
2836     }
2837 #endif 
2838 }
2839
2840 /*-----------------------------------------------------------------*/
2841 /* saverbank - saves an entire register bank on the stack          */
2842 /*-----------------------------------------------------------------*/
2843 static void saverbank (int bank, iCode *ic, bool pushPsw)
2844 {
2845   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2846 #if 0
2847     int i;
2848     asmop *aop ;
2849     regs *r = NULL;
2850
2851     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2852     if (options.useXstack) {
2853
2854         aop = newAsmop(0);
2855         r = getFreePtr(ic,&aop,FALSE);  
2856         pic16_emitcode("mov","%s,_spx",r->name);
2857
2858     }
2859
2860     for (i = 0 ; i < pic16_nRegs ;i++) {
2861         if (options.useXstack) {
2862             pic16_emitcode("inc","%s",r->name);
2863             //pic16_emitcode("mov","a,(%s+%d)",
2864             //         regspic16[i].base,8*bank+regspic16[i].offset);
2865             pic16_emitcode("movx","@%s,a",r->name);           
2866         } else 
2867           pic16_emitcode("push","");// "(%s+%d)",
2868                      //regspic16[i].base,8*bank+regspic16[i].offset);
2869     }
2870     
2871     if (pushPsw) {
2872         if (options.useXstack) {
2873             pic16_emitcode("mov","a,psw");
2874             pic16_emitcode("movx","@%s,a",r->name);     
2875             pic16_emitcode("inc","%s",r->name);
2876             pic16_emitcode("mov","_spx,%s",r->name);       
2877             pic16_freeAsmop (NULL,aop,ic,TRUE);
2878             
2879         } else
2880             pic16_emitcode("push","psw");
2881         
2882         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2883     }
2884     ic->bankSaved = 1;
2885 #endif
2886 }
2887
2888
2889
2890 /*-----------------------------------------------------------------*/
2891 /* genCall - generates a call statement                            */
2892 /*-----------------------------------------------------------------*/
2893 static void genCall (iCode *ic)
2894 {
2895   sym_link *dtype;   
2896   int stackParms=0;
2897   
2898         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2899
2900         /* if caller saves & we have not saved then */
2901         if (!ic->regsSaved)
2902                 saveRegisters(ic);
2903
2904         /* if we are calling a function that is not using
2905          * the same register bank then we need to save the
2906          * destination registers on the stack */
2907         dtype = operandType(IC_LEFT(ic));
2908         if (currFunc && dtype && 
2909                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2910                 IFFUNC_ISISR(currFunc->type) &&
2911                 !ic->bankSaved) 
2912
2913                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2914
2915
2916         /* initialise stackParms for IPUSH pushes */
2917 //      stackParms = psuedoStkPtr;
2918 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
2919
2920         /* if send set is not empty the assign */
2921         if (_G.sendSet) {
2922           iCode *sic;
2923
2924                 /* For the Pic port, there is no data stack.
2925                  * So parameters passed to functions are stored
2926                  * in registers. (The pCode optimizer will get
2927                  * rid of most of these :). */
2928
2929           int psuedoStkPtr=-1; 
2930           int firstTimeThruLoop = 1;
2931
2932                 _G.sendSet = reverseSet(_G.sendSet);
2933
2934                 /* First figure how many parameters are getting passed */
2935                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2936                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2937                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2938                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2939                 }
2940
2941                 stackParms = psuedoStkPtr;
2942
2943                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2944                   int size, offset = 0;
2945
2946                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2947                         size = AOP_SIZE(IC_LEFT(sic));
2948
2949                         while (size--) {
2950                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2951                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2952                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2953
2954                                 if(!firstTimeThruLoop) {
2955                                         /* If this is not the first time we've been through the loop
2956                                          * then we need to save the parameter in a temporary
2957                                          * register. The last byte of the last parameter is
2958                                          * passed in W. */
2959
2960                                         pushw();
2961                                         --psuedoStkPtr;         // sanity check
2962                                 }
2963                         
2964                                 firstTimeThruLoop=0;
2965
2966                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2967                                 offset++;
2968                         }
2969                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2970                 }
2971                 _G.sendSet = NULL;
2972         }
2973
2974         /* make the call */
2975         pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2976                         OP_SYMBOL(IC_LEFT(ic))->rname :
2977                         OP_SYMBOL(IC_LEFT(ic))->name));
2978
2979         GpsuedoStkPtr=0;
2980         /* if we need assign a result value */
2981         if ((IS_ITEMP(IC_RESULT(ic)) && 
2982                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2983                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2984                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2985
2986                 _G.accInUse++;
2987                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2988                 _G.accInUse--;
2989
2990                 assignResultValue(IC_RESULT(ic), 1);
2991
2992                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2993                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2994                 
2995                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2996         }
2997
2998         if(!stackParms && ic->parmBytes) {
2999                 stackParms = ic->parmBytes;
3000         }
3001         
3002         if(stackParms>0) {
3003                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3004                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3005                 if(STACK_MODEL_LARGE) {
3006                         emitSKPNC;
3007                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3008                 }
3009         }
3010
3011         /* adjust the stack for parameters if required */
3012 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3013 #if 0
3014         if (ic->parmBytes) {
3015           int i;
3016
3017                 if (ic->parmBytes > 3) {
3018                         pic16_emitcode("mov","a,%s",spname);
3019                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3020                         pic16_emitcode("mov","%s,a",spname);
3021                 } else 
3022                         for ( i = 0 ; i <  ic->parmBytes ;i++)
3023                                 pic16_emitcode("dec","%s",spname);
3024         }
3025 #endif
3026
3027 #if 0
3028         /* if register bank was saved then pop them */
3029         if (ic->bankSaved)
3030                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3031
3032         /* if we hade saved some registers then unsave them */
3033         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3034                 unsaveRegisters (ic);
3035 #endif
3036 }
3037
3038
3039
3040 /*-----------------------------------------------------------------*/   // patch 14
3041 /* genPcall - generates a call by pointer statement                */
3042 /*-----------------------------------------------------------------*/
3043
3044 // new version, created from genCall
3045
3046 static void genPcall (iCode *ic)
3047 {
3048   sym_link *dtype;   
3049   int stackParms=0;
3050   symbol *retlbl = newiTempLabel(NULL);
3051   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3052   
3053         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3054
3055         /* if caller saves & we have not saved then */
3056         if (!ic->regsSaved)
3057                 saveRegisters(ic);
3058
3059         /* if we are calling a function that is not using
3060          * the same register bank then we need to save the
3061          * destination registers on the stack */
3062         dtype = operandType(IC_LEFT(ic));
3063         if (currFunc && dtype && 
3064                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
3065                 IFFUNC_ISISR(currFunc->type) &&
3066                 !ic->bankSaved) 
3067
3068                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3069
3070         /* if send set is not empty the assign */
3071         if (_G.sendSet) {
3072           iCode *sic;
3073
3074                 /* For the Pic port, there is no data stack.
3075                  * So parameters passed to functions are stored
3076                  * in registers. (The pCode optimizer will get
3077                  * rid of most of these :). */
3078
3079           int psuedoStkPtr=-1; 
3080           int firstTimeThruLoop = 1;
3081
3082                 _G.sendSet = reverseSet(_G.sendSet);
3083
3084                 /* First figure how many parameters are getting passed */
3085                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3086                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3087                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
3088                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
3089                 }
3090
3091                 stackParms = psuedoStkPtr;
3092
3093                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3094                   int size, offset = 0;
3095
3096                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3097                         size = AOP_SIZE(IC_LEFT(sic));
3098
3099                         while (size--) {
3100                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3101                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3102                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3103
3104                                 if(!firstTimeThruLoop) {
3105                                         /* If this is not the first time we've been through the loop
3106                                          * then we need to save the parameter in a temporary
3107                                          * register. The last byte of the last parameter is
3108                                          * passed in W. */
3109
3110                                         pushw();
3111                                         --psuedoStkPtr;         // sanity check
3112                                 }
3113                         
3114                                 firstTimeThruLoop=0;
3115
3116                                 mov2w (AOP(IC_LEFT(sic)),  offset);
3117                                 offset++;
3118                         }
3119                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3120                 }
3121                 _G.sendSet = NULL;
3122         }
3123
3124         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3125
3126         // push return address
3127         // push $ on return stack, then replace with retlbl
3128
3129         pic16_emitpcodeNULLop(POC_PUSH);
3130
3131         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3132         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3133         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3134         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3135         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3136         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3137
3138         /* make the call by writing the pointer into pc */
3139         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3140         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3141
3142         // note: MOVFF to PCL not allowed
3143         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3144         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3145
3146
3147 //      pic16_emitpcode(POC_GOTO, pic16_popGetLabel(retlbl->key));
3148 //      pic16_emitpcodeNULLop(POC_NOP);
3149 //      pic16_emitpcodeNULLop(POC_NOP);
3150
3151         /* return address is here: (X) */
3152         pic16_emitpLabelFORCE(retlbl->key);
3153
3154 //      pic16_emitpcodeNULLop(POC_NOP);
3155
3156         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3157
3158         GpsuedoStkPtr=0;
3159         /* if we need assign a result value */
3160         if ((IS_ITEMP(IC_RESULT(ic)) && 
3161                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3162                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
3163                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3164
3165                 _G.accInUse++;
3166                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3167                 _G.accInUse--;
3168
3169                 assignResultValue(IC_RESULT(ic), 1);
3170
3171                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3172                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3173                 
3174                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3175         }
3176
3177         if(stackParms>0) {
3178                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3179                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3180                 if(STACK_MODEL_LARGE) {
3181                         emitSKPNC;
3182                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3183                 }
3184         }
3185
3186         /* adjust the stack for parameters if required */
3187 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3188
3189         if (ic->parmBytes) {
3190           int i;
3191
3192                 if (ic->parmBytes > 3) {
3193                         pic16_emitcode("mov","a,%s",spname);
3194                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3195                         pic16_emitcode("mov","%s,a",spname);
3196                 } else 
3197                         for ( i = 0 ; i <  ic->parmBytes ;i++)
3198                                 pic16_emitcode("dec","%s",spname);
3199         }
3200
3201         /* if register bank was saved then pop them */
3202         if (ic->bankSaved)
3203                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3204
3205         /* if we hade saved some registers then unsave them */
3206         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3207                 unsaveRegisters (ic);
3208 }
3209
3210
3211 #if 0                                                                           // patch 14
3212 // old version, kept for reference
3213
3214 /*-----------------------------------------------------------------*/
3215 /* genPcall - generates a call by pointer statement                */
3216 /*-----------------------------------------------------------------*/
3217 static void genPcall (iCode *ic)
3218 {
3219     sym_link *dtype;
3220     symbol *rlbl = newiTempLabel(NULL);
3221
3222
3223     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3224     /* if caller saves & we have not saved then */
3225     if (!ic->regsSaved)
3226         saveRegisters(ic);
3227
3228     /* if we are calling a function that is not using
3229     the same register bank then we need to save the
3230     destination registers on the stack */
3231     dtype = operandType(IC_LEFT(ic));
3232     if (currFunc && dtype && 
3233         IFFUNC_ISISR(currFunc->type) &&
3234         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3235         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3236
3237
3238     /* push the return address on to the stack */
3239     pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
3240     pic16_emitcode("push","acc");    
3241     pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
3242     pic16_emitcode("push","acc");
3243     
3244     if (options.model == MODEL_FLAT24)
3245     {
3246         pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
3247         pic16_emitcode("push","acc");    
3248     }
3249
3250     /* now push the calling address */
3251     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3252
3253     pushSide(IC_LEFT(ic), FPTRSIZE);
3254
3255     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
3256
3257     /* if send set is not empty the assign */
3258     if (_G.sendSet) {
3259         iCode *sic ;
3260
3261         for (sic = setFirstItem(_G.sendSet) ; sic ; 
3262              sic = setNextItem(_G.sendSet)) {
3263             int size, offset = 0;
3264             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3265             size = AOP_SIZE(IC_LEFT(sic));
3266             while (size--) {
3267                 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
3268                                 FALSE,FALSE);
3269                 if (strcmp(l,fReturn[offset]))
3270                     pic16_emitcode("mov","%s,%s",
3271                              fReturn[offset],
3272                              l);
3273                 offset++;
3274             }
3275             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3276         }
3277         _G.sendSet = NULL;
3278     }
3279
3280     pic16_emitcode("ret","");
3281     pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
3282
3283
3284     /* if we need assign a result value */
3285     if ((IS_ITEMP(IC_RESULT(ic)) &&
3286          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3287           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
3288         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3289
3290         _G.accInUse++;
3291         pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3292         _G.accInUse--;
3293         
3294         assignResultValue(IC_RESULT(ic), 1);
3295
3296         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3297     }
3298
3299     /* adjust the stack for parameters if 
3300     required */
3301     if (ic->parmBytes) {
3302         int i;
3303         if (ic->parmBytes > 3) {
3304             pic16_emitcode("mov","a,%s",spname);
3305             pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3306             pic16_emitcode("mov","%s,a",spname);
3307         } else 
3308             for ( i = 0 ; i <  ic->parmBytes ;i++)
3309                 pic16_emitcode("dec","%s",spname);
3310
3311     }
3312
3313     /* if register bank was saved then unsave them */
3314     if (currFunc && dtype && 
3315         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3316         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3317
3318     /* if we hade saved some registers then
3319     unsave them */
3320     if (ic->regsSaved)
3321         unsaveRegisters (ic);
3322
3323 }
3324 #endif                                                                          // patch 14
3325
3326
3327 /*-----------------------------------------------------------------*/
3328 /* resultRemat - result  is rematerializable                       */
3329 /*-----------------------------------------------------------------*/
3330 static int resultRemat (iCode *ic)
3331 {
3332   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3333   if (SKIP_IC(ic) || ic->op == IFX)
3334     return 0;
3335
3336   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3337     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3338     if (sym->remat && !POINTER_SET(ic)) 
3339       return 1;
3340   }
3341
3342   return 0;
3343 }
3344
3345 #if defined(__BORLANDC__) || defined(_MSC_VER)
3346 #define STRCASECMP stricmp
3347 #else
3348 #define STRCASECMP strcasecmp
3349 #endif
3350
3351 #if 0
3352 /*-----------------------------------------------------------------*/
3353 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3354 /*-----------------------------------------------------------------*/
3355 static bool inExcludeList(char *s)
3356 {
3357   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3358     int i =0;
3359     
3360     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3361     if (options.excludeRegs[i] &&
3362     STRCASECMP(options.excludeRegs[i],"none") == 0)
3363         return FALSE ;
3364
3365     for ( i = 0 ; options.excludeRegs[i]; i++) {
3366         if (options.excludeRegs[i] &&
3367         STRCASECMP(s,options.excludeRegs[i]) == 0)
3368             return TRUE;
3369     }
3370     return FALSE ;
3371 }
3372 #endif
3373
3374 /*-----------------------------------------------------------------*/
3375 /* genFunction - generated code for function entry                 */
3376 /*-----------------------------------------------------------------*/
3377 static void genFunction (iCode *ic)
3378 {
3379   symbol *sym;
3380   sym_link *ftype;
3381   
3382         DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3383
3384         pic16_labelOffset += (max_key+4);
3385         max_key=0;
3386         GpsuedoStkPtr=0;
3387         _G.nRegsSaved = 0;
3388
3389         ftype = operandType(IC_LEFT(ic));
3390         sym = OP_SYMBOL(IC_LEFT(ic));
3391
3392         if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3393                 /* create an absolute section at the interrupt vector:
3394                  * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3395           symbol *asym;
3396           char asymname[128];
3397           pBlock *apb;
3398
3399                 {
3400                   int i, found=-1;
3401
3402                         sym = OP_SYMBOL( IC_LEFT(ic));
3403                         for(i=0;i<=2;i++) {
3404                                 if(interrupts[i]->name
3405                                         && !STRCASECMP(interrupts[i]->name, sym->name)) {
3406                                         found = i;
3407                                         break;
3408                                 }
3409                         }
3410                         
3411                         if(found == -1) {
3412                                 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3413                                         __FILE__, __LINE__, sym->name);
3414                                 assert( 0 );
3415                         }
3416                         _G.interruptvector = found;
3417                 }
3418
3419                 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3420                 asym = newSymbol(asymname, 0);
3421
3422                 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3423                 pic16_addpBlock( apb );
3424
3425                 pic16_addpCode2pBlock(apb,
3426                         pic16_newpCodeCharP(";-----------------------------------------"));
3427
3428
3429                 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3430
3431                 pic16_addpCode2pBlock(apb,
3432                         pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3433                 
3434                 /* mark the end of this tiny function */
3435                 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3436
3437                 {
3438                   absSym *abSym;
3439
3440                         abSym = Safe_calloc(1, sizeof(absSym));
3441                         abSym->name = Safe_strdup( asymname );
3442
3443                         switch( _G.interruptvector ) {
3444                                 case 0: abSym->address = 0x000000; break;
3445                                 case 1: abSym->address = 0x000008; break;
3446                                 case 2: abSym->address = 0x000018; break;
3447                         }
3448
3449                         /* relocate interrupt vectors if needed */
3450                         abSym->address += pic16_options.ivt_loc;
3451
3452                         addSet(&absSymSet, abSym);
3453                 }
3454         }
3455
3456
3457         /* create the function header */
3458         pic16_emitcode(";","-----------------------------------------");
3459         pic16_emitcode(";"," function %s",sym->name);
3460         pic16_emitcode(";","-----------------------------------------");
3461
3462         pic16_emitcode("","%s:",sym->rname);
3463         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3464
3465
3466         {
3467           absSym *ab;
3468
3469                 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
3470                         if(!strcmp(ab->name, sym->name)) {
3471                                 pic16_pBlockConvert2Absolute(pb);
3472                                 break;
3473                         }
3474
3475         }
3476
3477
3478         if(IFFUNC_ISNAKED(ftype)) {
3479                 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3480                 return;
3481         }
3482         
3483         /* if critical function then turn interrupts off */
3484         if (IFFUNC_ISCRITICAL(ftype))
3485                 pic16_emitcode("clr","ea");
3486
3487         /* if this is an interrupt service routine then
3488          * save acc, b, dpl, dph  */
3489         if (IFFUNC_ISISR(sym->type)) {
3490           int i;
3491
3492                 _G.usefastretfie = 1;   /* use shadow registers by default */
3493                 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3494                 if(!(_G.interruptvector == 1)) {
3495
3496                         /* do not save WREG,STATUS,BSR for high priority interrupts
3497                          * because they are stored in the hardware shadow registers already */
3498                         _G.usefastretfie = 0;
3499                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3500                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3501                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3502                 }
3503
3504
3505                 /* these should really be optimized somehow, because not all
3506                  * interrupt handlers modify them */
3507                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3508                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3509                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3510                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3511
3512 //                pic16_pBlockConvert2ISR(pb);
3513                 
3514                 /* if any registers used */
3515                 if (sym->regsUsed) {
3516                         /* save the registers used */
3517                         DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3518                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3519                                 if (bitVectBitValue(sym->regsUsed,i)) {
3520 #if 0
3521                                         fprintf(stderr, "%s:%d function %s uses register %s\n",
3522                                                         __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3523                                                         pic16_regWithIdx(i)->name);
3524 #endif
3525
3526                                         pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3527                                         _G.nRegsSaved++;
3528
3529                                         if(!pic16_regWithIdx(i)->wasUsed) {
3530                                                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3531                                                         __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3532
3533                                                 pic16_regWithIdx(i)->wasUsed = 1;
3534                                         }
3535                                 }
3536                         }
3537                 }
3538         } else {
3539                 /* emit code to setup stack frame if user enabled,
3540                  * and function is not main() */
3541          
3542 //              fprintf(stderr, "function name: %s\n", sym->name);
3543                 if(strcmp(sym->name, "main")) {
3544                         if(/*!options.ommitFramePtr || */sym->regsUsed) {
3545                         /* setup the stack frame */
3546                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3547                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3548                                 if(STACK_MODEL_LARGE)
3549                                         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3550                         }
3551                 }
3552
3553                 /* if callee-save to be used for this function
3554                 * then save the registers being used in this function */
3555 //              if (IFFUNC_CALLEESAVES(sym->type))
3556                 {
3557                   int i;
3558
3559 //                      fprintf(stderr, "%s:%d function sym->regsUsed= %d\n", __FILE__, __LINE__, sym->regsUsed->size);
3560
3561 //                      pic16_emitpcomment("entry regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3562
3563                         /* if any registers used */
3564                         if (sym->regsUsed) {
3565                                 /* save the registers used */
3566                                 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3567                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3568                                         if (bitVectBitValue(sym->regsUsed,i)) {
3569
3570 #if 0
3571                                                 fprintf(stderr, "%s:%d function %s uses register %s (wasUsed: %d, %p)\n",
3572                                                                 __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3573                                                                 pic16_regWithIdx(i)->name,
3574                                                                 pic16_regWithIdx(i)->wasUsed,
3575                                                                 pic16_regWithIdx(i));
3576 #endif
3577
3578                                                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3579
3580 //                                              pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3581 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
3582 //                                                      &pic16_pc_postdec1, 0));
3583
3584                                                 _G.nRegsSaved++;
3585
3586                                                 if(!pic16_regWithIdx(i)->wasUsed) {
3587                                                         fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3588                                                                 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3589
3590                                                         pic16_regWithIdx(i)->wasUsed = 1;
3591                                                 }
3592                                         
3593                                         }
3594                                 }
3595                         }
3596                 }
3597         }
3598
3599
3600         
3601 #if 0
3602         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3603
3604                 if (options.useXstack) {
3605                         pic16_emitcode("mov","r0,%s",spname);
3606                         pic16_emitcode("mov","a,_bp");
3607                         pic16_emitcode("movx","@r0,a");
3608                         pic16_emitcode("inc","%s",spname);
3609                 } else {
3610                         /* set up the stack */
3611                         pic16_emitcode ("push","_bp");     /* save the callers stack  */
3612                 }
3613                 pic16_emitcode ("mov","_bp,%s",spname);
3614         }
3615 #endif
3616         DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3617
3618         /* adjust the stack for the function */
3619         if (sym->stack) {
3620           int i = sym->stack;
3621
3622                 if (i > 127 ) 
3623                         werror(W_STACK_OVERFLOW,sym->name);
3624
3625                 if (i > 3 && sym->recvSize < 4) {              
3626                         pic16_emitcode ("mov","a,sp");
3627                         pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3628                         pic16_emitcode ("mov","sp,a");
3629                 } else
3630                         while(i--)
3631                                 pic16_emitcode("inc","sp");
3632         }
3633
3634         if (sym->xstack) {
3635                 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3636
3637                 pic16_emitcode ("mov","a,_spx");
3638                 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3639                 pic16_emitcode ("mov","_spx,a");
3640         }
3641     
3642 }
3643
3644 /*-----------------------------------------------------------------*/
3645 /* genEndFunction - generates epilogue for functions               */
3646 /*-----------------------------------------------------------------*/
3647 static void genEndFunction (iCode *ic)
3648 {
3649     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3650
3651     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3652
3653     if(IFFUNC_ISNAKED(sym->type)) {
3654         DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3655         return;
3656     }
3657
3658     /* add code for ISCRITICAL */
3659
3660 #if 0
3661     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3662     {
3663         pic16_emitcode ("mov","%s,_bp",spname);
3664     }
3665 #endif
3666
3667     /* if use external stack but some variables were
3668     added to the local stack then decrement the
3669     local stack */
3670     if (options.useXstack && sym->stack) {      
3671         pic16_emitcode("mov","a,sp");
3672         pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3673         pic16_emitcode("mov","sp,a");
3674     }
3675
3676
3677 #if 0
3678     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3679         if (options.useXstack) {
3680             pic16_emitcode("mov","r0,%s",spname);
3681             pic16_emitcode("movx","a,@r0");
3682             pic16_emitcode("mov","_bp,a");
3683             pic16_emitcode("dec","%s",spname);
3684         }
3685         else
3686         {
3687             pic16_emitcode ("pop","_bp");
3688         }
3689     }
3690 #endif
3691
3692         if (IFFUNC_ISISR(sym->type)) {
3693                 /* now we need to restore the registers */
3694                 /* if any registers used */
3695                 if (sym->regsUsed) {
3696                   int i;
3697
3698                         /* restore registers used */
3699                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3700                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3701                                 if (bitVectBitValue(sym->regsUsed,i)) {
3702
3703 //                                      fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3704 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3705 //                                                      pic16_regWithIdx(i)->name);
3706
3707                                         pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3708
3709 //                                      pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3710 //                                                      &pic16_pc_preinc1,
3711 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3712
3713                                 }
3714                         }
3715                 }
3716         
3717                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3718                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3719                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3720                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3721
3722                 if(!(_G.interruptvector == 1)) {
3723                         /* do not restore interrupt vector for WREG,STATUS,BSR
3724                          * for high priority interrupt, see genFunction */
3725                          
3726                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3727                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3728                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3729                 }
3730         
3731                 _G.interruptvector = 0;         /* sanity check */
3732
3733 //              pic16_pBlockConvert2ISR(pb);
3734
3735
3736                 /* if debug then send end of function */
3737 /*      if (options.debug && currFunc)  */
3738                 if (currFunc) {
3739                         debugFile->writeEndFunction (currFunc, ic, 1);
3740                 }
3741         
3742                 if(_G.usefastretfie)
3743                         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3744                 else
3745                 pic16_emitpcodeNULLop(POC_RETFIE);
3746                 _G.usefastretfie = 0;
3747         } else {
3748                 if (IFFUNC_ISCRITICAL(sym->type))
3749                         pic16_emitcode("setb","ea");
3750         
3751
3752 //              pic16_emitpcomment("exit regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3753
3754                 /* if any registers used */
3755                 if (sym->regsUsed) {
3756                   int i;
3757                         /* save the registers used */
3758                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3759                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3760                                 if (bitVectBitValue(sym->regsUsed,i)) {
3761         
3762 //                                      fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3763 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3764 //                                                      pic16_regWithIdx(i)->name);
3765         
3766                                         pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3767                                         
3768 //                                      pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3769 //                                              &pic16_pc_preinc1,
3770 //                                              PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3771
3772                                         _G.nRegsSaved--;
3773                                 }
3774                         }
3775                 }
3776         
3777 //              pic16_emitpcomment("%s: _G.nRegsSaved upon exit from function: %d\n", __FUNCTION__, _G.nRegsSaved);
3778                 /* if debug then send end of function */
3779                 if (currFunc) {
3780                         debugFile->writeEndFunction (currFunc, ic, 1);
3781                 }
3782
3783                 /* insert code to restore stack frame, if user enabled it
3784                  * and function is not main() */
3785          
3786
3787                 if(strcmp(sym->name, "main")) {
3788                         if(/*!options.ommitFramePtr ||*/ sym->regsUsed) {
3789                                 /* restore stack frame */
3790                                 if(STACK_MODEL_LARGE)
3791                                         pic16_emitpcode(POC_MOVFF,
3792                                                 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3793                                 pic16_emitpcode(POC_MOVFF,
3794                                                 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3795                         }
3796                 }
3797
3798                 pic16_emitpcodeNULLop(POC_RETURN);
3799
3800                 /* Mark the end of a function */
3801                 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3802         }
3803
3804 }
3805
3806
3807 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3808 {
3809
3810         if(is_LitOp(op)) {
3811                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12
3812
3813                 if(dest->type != PO_WREG)
3814                         pic16_emitpcode(POC_MOVWF, dest);
3815         } else {
3816                 if(dest->type == PO_WREG && (offset == 0)) {
3817                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3818                         return;
3819                 }
3820                 
3821                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3822                         pic16_popGet(AOP(op), offset), dest));
3823         }
3824 }
3825
3826 /*-----------------------------------------------------------------*/
3827 /* genRet - generate code for return statement                     */
3828 /*-----------------------------------------------------------------*/
3829 static void genRet (iCode *ic)
3830 {
3831   int size;
3832   operand *left;
3833
3834         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3835         /* if we have no return value then
3836          * just generate the "ret" */
3837         
3838         if (!IC_LEFT(ic)) 
3839                 goto jumpret;       
3840     
3841         /* we have something to return then
3842          * move the return value into place */
3843         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3844         size = AOP_SIZE(IC_LEFT(ic));
3845
3846         if(size <= 4) {
3847                 if(size>3) {
3848                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3849 //                      pic16_emitpcode(POC_MOVFF,
3850 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3851                 }
3852                 if(size>2) {
3853                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3854 //                      pic16_emitpcode(POC_MOVFF,
3855 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3856                 }
3857                 if(size>1) {
3858                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3859 //                      pic16_emitpcode(POC_MOVFF,
3860 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3861                 }
3862
3863 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3864
3865                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3866 //              pic16_emitpcode(POC_MOVFF,
3867 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3868
3869         } else {
3870                 /* >32-bits, setup stack and FSR0 */
3871                 while (size--) {
3872 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3873 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3874
3875                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3876
3877 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3878                         GpsuedoStkPtr++;
3879                 }
3880                         
3881                 /* setup FSR0 */
3882                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3883                         pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3884
3885                 if(STACK_MODEL_LARGE) {
3886                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3887                                 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3888                 } else {
3889                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3890                 }
3891         }
3892                                 
3893 #if 0
3894         /* old code, left here for reference -- VR */    
3895         while (size--) {
3896           char *l ;
3897
3898                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3899                         /* #NOCHANGE */
3900                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3901                         pic16_emitpcomment("push %s",l);
3902                         pushed++;
3903                 } else {
3904                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3905                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3906                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3907                         
3908                         if (strcmp(fReturn[offset],l)) {
3909                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3910                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3911                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3912                                 } else {
3913                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3914                                 }
3915                                 
3916                                 if(size) {
3917                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3918                                 }
3919                                 offset++;
3920                         }
3921                 }
3922         }    
3923
3924         if (pushed) {
3925                 while(pushed) {
3926                         pushed--;
3927                         if (strcmp(fReturn[pushed],"a"))
3928                                 pic16_emitcode("pop",fReturn[pushed]);
3929                         else
3930                                 pic16_emitcode("pop","acc");
3931                 }
3932         }
3933 #endif
3934
3935
3936         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3937     
3938 jumpret:
3939         /* generate a jump to the return label
3940          * if the next is not the return statement */
3941         if (!(ic->next && ic->next->op == LABEL
3942                 && IC_LABEL(ic->next) == returnLabel)) {
3943         
3944                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3945                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3946         }
3947 }
3948
3949 /*-----------------------------------------------------------------*/
3950 /* genLabel - generates a label                                    */
3951 /*-----------------------------------------------------------------*/
3952 static void genLabel (iCode *ic)
3953 {
3954
3955
3956     /* special case never generate */
3957     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3958     if (IC_LABEL(ic) == entryLabel)
3959         return ;
3960
3961     pic16_emitpLabel(IC_LABEL(ic)->key);
3962     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3963 }
3964
3965 /*-----------------------------------------------------------------*/
3966 /* genGoto - generates a goto                                      */
3967 /*-----------------------------------------------------------------*/
3968 //tsd
3969 static void genGoto (iCode *ic)
3970 {
3971   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3972   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3973 }
3974
3975
3976 /*-----------------------------------------------------------------*/
3977 /* genMultbits :- multiplication of bits                           */
3978 /*-----------------------------------------------------------------*/
3979 static void genMultbits (operand *left, 
3980                          operand *right, 
3981                          operand *result)
3982 {
3983   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3984
3985   if(!pic16_sameRegs(AOP(result),AOP(right)))
3986     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3987
3988   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3989   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3990   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3991
3992 }
3993
3994
3995 /*-----------------------------------------------------------------*/
3996 /* genMultOneByte : 8 bit multiplication & division                */
3997 /*-----------------------------------------------------------------*/
3998 static void genMultOneByte (operand *left,
3999                             operand *right,
4000                             operand *result)
4001 {
4002
4003   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4004   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4005   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4006
4007   /* (if two literals, the value is computed before) */
4008   /* if one literal, literal on the right */
4009   if (AOP_TYPE(left) == AOP_LIT){
4010     operand *t = right;
4011     right = left;
4012     left = t;
4013   }
4014
4015         /* size is already checked in genMult == 1 */
4016 //      size = AOP_SIZE(result);
4017
4018         if (AOP_TYPE(right) == AOP_LIT){
4019                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4020                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4021                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4022                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4023         } else {
4024                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4025                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4026                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4027                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4028         }
4029         
4030         pic16_genMult8X8_8 (left, right,result);
4031 }
4032
4033 /*-----------------------------------------------------------------*/
4034 /* genMultOneWord : 16 bit multiplication                          */
4035 /*-----------------------------------------------------------------*/
4036 static void genMultOneWord (operand *left,
4037                             operand *right,
4038                             operand *result)
4039 {
4040
4041         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4042         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4043         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4044
4045         /* (if two literals, the value is computed before)
4046          * if one literal, literal on the right */
4047         if (AOP_TYPE(left) == AOP_LIT){
4048           operand *t = right;
4049                 right = left;
4050                 left = t;
4051         }
4052
4053         /* size is checked already == 2 */
4054 //      size = AOP_SIZE(result);
4055
4056         if (AOP_TYPE(right) == AOP_LIT) {
4057                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4058                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4059                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4060                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4061         } else {
4062                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4063                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4064                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4065                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4066         }
4067         
4068         pic16_genMult16X16_16(left, right,result);
4069 }
4070
4071 /*-----------------------------------------------------------------*/
4072 /* genMultOneLong : 32 bit multiplication                          */
4073 /*-----------------------------------------------------------------*/
4074 static void genMultOneLong (operand *left,
4075                             operand *right,
4076                             operand *result)
4077 {
4078
4079         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4080         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4081         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4082
4083         /* (if two literals, the value is computed before)
4084          * if one literal, literal on the right */
4085         if (AOP_TYPE(left) == AOP_LIT){
4086           operand *t = right;
4087                 right = left;
4088                 left = t;
4089         }
4090
4091         /* size is checked already == 4 */
4092 //      size = AOP_SIZE(result);
4093
4094         if (AOP_TYPE(right) == AOP_LIT) {
4095                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4096                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4097                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4098                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4099         } else {
4100                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4101                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4102                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4103                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4104         }
4105         
4106         pic16_genMult32X32_32(left, right,result);
4107 }
4108
4109
4110
4111 /*-----------------------------------------------------------------*/
4112 /* genMult - generates code for multiplication                     */
4113 /*-----------------------------------------------------------------*/
4114 static void genMult (iCode *ic)
4115 {
4116   operand *left = IC_LEFT(ic);
4117   operand *right = IC_RIGHT(ic);
4118   operand *result= IC_RESULT(ic);   
4119
4120         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4121         /* assign the amsops */
4122         pic16_aopOp (left,ic,FALSE);
4123         pic16_aopOp (right,ic,FALSE);
4124         pic16_aopOp (result,ic,TRUE);
4125
4126         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4127
4128         /* special cases first *
4129         * both are bits */
4130         if (AOP_TYPE(left) == AOP_CRY
4131                 && AOP_TYPE(right)== AOP_CRY) {
4132                 genMultbits(left,right,result);
4133           goto release ;
4134         }
4135
4136         /* if both are of size == 1 */
4137         if(AOP_SIZE(left) == 1
4138                 && AOP_SIZE(right) == 1) {
4139                 genMultOneByte(left,right,result);
4140           goto release ;
4141         }
4142
4143         /* if both are of size == 2 */
4144         if(AOP_SIZE(left) == 2
4145                 && AOP_SIZE(right) == 2) {
4146                 genMultOneWord(left, right, result);
4147           goto release;
4148         }
4149         
4150         /* if both are of size == 4 */
4151         if(AOP_SIZE(left) == 4
4152                 && AOP_SIZE(right) == 4) {
4153                 genMultOneLong(left, right, result);
4154           goto release;
4155         }
4156         
4157         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4158
4159
4160         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4161         /* should have been converted to function call */
4162         assert(0) ;
4163
4164 release :
4165         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4166         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4167         pic16_freeAsmop(result,NULL,ic,TRUE); 
4168 }
4169
4170 /*-----------------------------------------------------------------*/
4171 /* genDivbits :- division of bits                                  */
4172 /*-----------------------------------------------------------------*/
4173 static void genDivbits (operand *left, 
4174                         operand *right, 
4175                         operand *result)
4176 {
4177
4178     char *l;
4179
4180     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4181     /* the result must be bit */    
4182     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4183     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4184
4185     MOVA(l);    
4186
4187     pic16_emitcode("div","ab");
4188     pic16_emitcode("rrc","a");
4189     pic16_aopPut(AOP(result),"c",0);
4190 }
4191
4192 /*-----------------------------------------------------------------*/
4193 /* genDivOneByte : 8 bit division                                  */
4194 /*-----------------------------------------------------------------*/
4195 static void genDivOneByte (operand *left,
4196                            operand *right,
4197                            operand *result)
4198 {
4199     sym_link *opetype = operandType(result);
4200     char *l ;
4201     symbol *lbl ;
4202     int size,offset;
4203
4204         /* result = divident / divisor
4205          * - divident may be a register or a literal,
4206          * - divisor may be a register or a literal,
4207          * so there are 3 cases (literal / literal is optimized
4208          * by the front-end) to handle.
4209          * In addition we must handle signed and unsigned, which
4210          * result in 6 final different cases -- VR */
4211
4212     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4213     size = AOP_SIZE(result) - 1;
4214     offset = 1;
4215     /* signed or unsigned */
4216     if (SPEC_USIGN(opetype)) {
4217       pCodeOp *pct1,    /* count */
4218                 *pct2,  /* reste */
4219                 *pct3;  /* temp */
4220       symbol *label1, *label2, *label3;;
4221
4222
4223         /* unsigned is easy */
4224
4225         pct1 = pic16_popGetTempReg();
4226         pct2 = pic16_popGetTempReg();
4227         pct3 = pic16_popGetTempReg();
4228         
4229         label1 = newiTempLabel(NULL);
4230         label2 = newiTempLabel(NULL);
4231         label3 = newiTempLabel(NULL);
4232
4233         /* the following algorithm is extracted from divuint.c */
4234
4235         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4236         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4237         
4238         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4239
4240         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4241         
4242         pic16_emitpLabel(label1->key);
4243         
4244         emitCLRC;
4245         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4246
4247
4248         emitCLRC;
4249         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4250         
4251
4252         emitSKPNC;
4253         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4254         
4255         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4256         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4257         
4258         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4259         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4260         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4261         
4262         pic16_emitpLabel( label3->key );
4263         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4264         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4265         
4266         
4267
4268         pic16_emitpLabel(label2->key);
4269         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4270         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4271         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4272         
4273         /* result is in wreg */
4274         if(AOP_TYPE(result) != AOP_ACC)
4275                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4276
4277         pic16_popReleaseTempReg( pct3 );
4278         pic16_popReleaseTempReg( pct2 );
4279         pic16_popReleaseTempReg( pct1 );
4280
4281         return ;
4282     }
4283
4284     /* signed is a little bit more difficult */
4285
4286     /* save the signs of the operands */
4287     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4288     MOVA(l);    
4289     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4290     pic16_emitcode("push","acc"); /* save it on the stack */
4291
4292     /* now sign adjust for both left & right */
4293     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4294     MOVA(l);       
4295     lbl = newiTempLabel(NULL);
4296     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4297     pic16_emitcode("cpl","a");   
4298     pic16_emitcode("inc","a");
4299     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4300     pic16_emitcode("mov","b,a");
4301
4302     /* sign adjust left side */
4303     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4304     MOVA(l);
4305
4306     lbl = newiTempLabel(NULL);
4307     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4308     pic16_emitcode("cpl","a");
4309     pic16_emitcode("inc","a");
4310     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4311
4312     /* now the division */
4313     pic16_emitcode("div","ab");
4314     /* we are interested in the lower order
4315     only */
4316     pic16_emitcode("mov","b,a");
4317     lbl = newiTempLabel(NULL);
4318     pic16_emitcode("pop","acc");   
4319     /* if there was an over flow we don't 
4320     adjust the sign of the result */
4321     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4322     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4323     CLRC;
4324     pic16_emitcode("clr","a");
4325     pic16_emitcode("subb","a,b");
4326     pic16_emitcode("mov","b,a");
4327     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4328
4329     /* now we are done */
4330     pic16_aopPut(AOP(result),"b",0);
4331     if(size > 0){
4332         pic16_emitcode("mov","c,b.7");
4333         pic16_emitcode("subb","a,acc");   
4334     }
4335     while (size--)
4336         pic16_aopPut(AOP(result),"a",offset++);
4337
4338 }
4339
4340 /*-----------------------------------------------------------------*/
4341 /* genDiv - generates code for division                            */
4342 /*-----------------------------------------------------------------*/
4343 static void genDiv (iCode *ic)
4344 {
4345     operand *left = IC_LEFT(ic);
4346     operand *right = IC_RIGHT(ic);
4347     operand *result= IC_RESULT(ic);   
4348
4349
4350         /* Division is a very lengthy algorithm, so it is better
4351          * to call support routines than inlining algorithm.
4352          * Division functions written here just in case someone
4353          * wants to inline and not use the support libraries -- VR */
4354
4355     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4356     /* assign the amsops */
4357     pic16_aopOp (left,ic,FALSE);
4358     pic16_aopOp (right,ic,FALSE);
4359     pic16_aopOp (result,ic,TRUE);
4360
4361     /* special cases first */
4362     /* both are bits */
4363     if (AOP_TYPE(left) == AOP_CRY &&
4364         AOP_TYPE(right)== AOP_CRY) {
4365         genDivbits(left,right,result);
4366         goto release ;
4367     }
4368
4369     /* if both are of size == 1 */
4370     if (AOP_SIZE(left) == 1 &&
4371         AOP_SIZE(right) == 1 ) {
4372         genDivOneByte(left,right,result);
4373         goto release ;
4374     }
4375
4376     /* should have been converted to function call */
4377     assert(0);
4378 release :
4379     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4380     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4381     pic16_freeAsmop(result,NULL,ic,TRUE); 
4382 }
4383
4384 /*-----------------------------------------------------------------*/
4385 /* genModbits :- modulus of bits                                   */
4386 /*-----------------------------------------------------------------*/
4387 static void genModbits (operand *left, 
4388                         operand *right, 
4389                         operand *result)
4390 {
4391
4392     char *l;
4393
4394     /* the result must be bit */    
4395     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4396     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4397
4398     MOVA(l);       
4399
4400     pic16_emitcode("div","ab");
4401     pic16_emitcode("mov","a,b");
4402     pic16_emitcode("rrc","a");
4403     pic16_aopPut(AOP(result),"c",0);
4404 }
4405
4406 /*-----------------------------------------------------------------*/
4407 /* genModOneByte : 8 bit modulus                                   */
4408 /*-----------------------------------------------------------------*/
4409 static void genModOneByte (operand *left,
4410                            operand *right,
4411                            operand *result)
4412 {
4413     sym_link *opetype = operandType(result);
4414     char *l ;
4415     symbol *lbl ;
4416
4417     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4418     /* signed or unsigned */
4419     if (SPEC_USIGN(opetype)) {
4420         /* unsigned is easy */
4421         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4422         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4423         MOVA(l);    
4424         pic16_emitcode("div","ab");
4425         pic16_aopPut(AOP(result),"b",0);
4426         return ;
4427     }
4428
4429     /* signed is a little bit more difficult */
4430
4431     /* save the signs of the operands */
4432     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4433     MOVA(l);
4434
4435     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4436     pic16_emitcode("push","acc"); /* save it on the stack */
4437
4438     /* now sign adjust for both left & right */
4439     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4440     MOVA(l);
4441
4442     lbl = newiTempLabel(NULL);
4443     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4444     pic16_emitcode("cpl","a");   
4445     pic16_emitcode("inc","a");
4446     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4447     pic16_emitcode("mov","b,a"); 
4448
4449     /* sign adjust left side */
4450     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4451     MOVA(l);
4452
4453     lbl = newiTempLabel(NULL);
4454     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4455     pic16_emitcode("cpl","a");   
4456     pic16_emitcode("inc","a");
4457     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4458
4459     /* now the multiplication */
4460     pic16_emitcode("div","ab");
4461     /* we are interested in the lower order
4462     only */
4463     lbl = newiTempLabel(NULL);
4464     pic16_emitcode("pop","acc");   
4465     /* if there was an over flow we don't 
4466     adjust the sign of the result */
4467     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4468     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4469     CLRC ;
4470     pic16_emitcode("clr","a");
4471     pic16_emitcode("subb","a,b");
4472     pic16_emitcode("mov","b,a");
4473     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4474
4475     /* now we are done */
4476     pic16_aopPut(AOP(result),"b",0);
4477
4478 }
4479
4480 /*-----------------------------------------------------------------*/
4481 /* genMod - generates code for division                            */
4482 /*-----------------------------------------------------------------*/
4483 static void genMod (iCode *ic)
4484 {
4485     operand *left = IC_LEFT(ic);
4486     operand *right = IC_RIGHT(ic);
4487     operand *result= IC_RESULT(ic);  
4488
4489     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4490     /* assign the amsops */
4491     pic16_aopOp (left,ic,FALSE);
4492     pic16_aopOp (right,ic,FALSE);
4493     pic16_aopOp (result,ic,TRUE);
4494
4495     /* special cases first */
4496     /* both are bits */
4497     if (AOP_TYPE(left) == AOP_CRY &&
4498         AOP_TYPE(right)== AOP_CRY) {
4499         genModbits(left,right,result);
4500         goto release ;
4501     }
4502
4503     /* if both are of size == 1 */
4504     if (AOP_SIZE(left) == 1 &&
4505         AOP_SIZE(right) == 1 ) {
4506         genModOneByte(left,right,result);
4507         goto release ;
4508     }
4509
4510     /* should have been converted to function call */
4511     assert(0);
4512
4513 release :
4514     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4515     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4516     pic16_freeAsmop(result,NULL,ic,TRUE); 
4517 }
4518
4519 /*-----------------------------------------------------------------*/
4520 /* genIfxJump :- will create a jump depending on the ifx           */
4521 /*-----------------------------------------------------------------*/
4522 /*
4523   note: May need to add parameter to indicate when a variable is in bit space.
4524 */
4525 static void genIfxJump (iCode *ic, char *jval)
4526 {
4527
4528     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4529     /* if true label then we jump if condition
4530     supplied is true */
4531     if ( IC_TRUE(ic) ) {
4532
4533         if(strcmp(jval,"a") == 0)
4534           emitSKPZ;
4535         else if (strcmp(jval,"c") == 0)
4536           emitSKPC;
4537         else {
4538           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4539           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4540         }
4541
4542         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4543         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4544
4545     }
4546     else {
4547         /* false label is present */
4548         if(strcmp(jval,"a") == 0)
4549           emitSKPNZ;
4550         else if (strcmp(jval,"c") == 0)
4551           emitSKPNC;
4552         else {
4553           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4554           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4555         }
4556
4557         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4558         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4559
4560     }
4561
4562
4563     /* mark the icode as generated */
4564     ic->generated = 1;
4565 }
4566
4567 #if 0
4568 // not needed ATM
4569
4570 /*-----------------------------------------------------------------*/
4571 /* genSkip                                                         */
4572 /*-----------------------------------------------------------------*/
4573 static void genSkip(iCode *ifx,int status_bit)
4574 {
4575   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4576   if(!ifx)
4577     return;
4578
4579   if ( IC_TRUE(ifx) ) {
4580     switch(status_bit) {
4581     case 'z':
4582       emitSKPNZ;
4583       break;
4584
4585     case 'c':
4586       emitSKPNC;
4587       break;
4588
4589     case 'd':
4590       emitSKPDC;
4591       break;
4592
4593     }
4594
4595     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4596     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4597
4598   } else {
4599
4600     switch(status_bit) {
4601
4602     case 'z':
4603       emitSKPZ;
4604       break;
4605
4606     case 'c':
4607       emitSKPC;
4608       break;
4609
4610     case 'd':
4611       emitSKPDC;
4612       break;
4613     }
4614     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4615     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4616
4617   }
4618
4619 }
4620 #endif
4621
4622 /*-----------------------------------------------------------------*/
4623 /* genSkipc                                                        */
4624 /*-----------------------------------------------------------------*/
4625 static void genSkipc(resolvedIfx *rifx)
4626 {
4627   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4628   
4629   if(!rifx)
4630     return;
4631
4632   if(rifx->condition)
4633     emitSKPC;
4634   else
4635     emitSKPNC;
4636
4637   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4638   rifx->generated = 1;
4639 }
4640
4641 /*-----------------------------------------------------------------*/
4642 /* genSkipz2                                                       */
4643 /*-----------------------------------------------------------------*/
4644 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4645 {
4646   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4647   
4648   if(!rifx)
4649     return;
4650
4651   if( (rifx->condition ^ invert_condition) & 1)
4652     emitSKPZ;
4653   else
4654     emitSKPNZ;
4655
4656   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4657   rifx->generated = 1;
4658 }
4659
4660 #if 0
4661 /*-----------------------------------------------------------------*/
4662 /* genSkipz                                                        */
4663 /*-----------------------------------------------------------------*/
4664 static void genSkipz(iCode *ifx, int condition)
4665 {
4666   if(!ifx)
4667     return;
4668
4669   if(condition)
4670     emitSKPNZ;
4671   else
4672     emitSKPZ;
4673
4674   if ( IC_TRUE(ifx) )
4675     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4676   else
4677     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4678
4679   if ( IC_TRUE(ifx) )
4680     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4681   else
4682     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4683
4684 }
4685 #endif
4686
4687 /*-----------------------------------------------------------------*/
4688 /* genSkipCond                                                     */
4689 /*-----------------------------------------------------------------*/
4690 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4691 {
4692   if(!rifx)
4693     return;
4694
4695   if(rifx->condition)
4696     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4697   else
4698     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4699
4700
4701   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4702   rifx->generated = 1;
4703 }
4704
4705 #if 0
4706 /*-----------------------------------------------------------------*/
4707 /* genChkZeroes :- greater or less than comparison                 */
4708 /*     For each byte in a literal that is zero, inclusive or the   */
4709 /*     the corresponding byte in the operand with W                */
4710 /*     returns true if any of the bytes are zero                   */
4711 /*-----------------------------------------------------------------*/
4712 static int genChkZeroes(operand *op, int lit,  int size)
4713 {
4714
4715   int i;
4716   int flag =1;
4717
4718   while(size--) {
4719     i = (lit >> (size*8)) & 0xff;
4720
4721     if(i==0) {
4722       if(flag) 
4723         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4724       else
4725         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4726       flag = 0;
4727     }
4728   }
4729
4730   return (flag==0);
4731 }
4732 #endif
4733
4734 /*-----------------------------------------------------------------*/
4735 /* genCmp :- greater or less than comparison                       */
4736 /*-----------------------------------------------------------------*/
4737 static void genCmp (operand *left,operand *right,
4738                     operand *result, iCode *ifx, int sign)
4739 {
4740   int size; //, offset = 0 ;
4741   unsigned long lit = 0L,i = 0;
4742   resolvedIfx rFalseIfx;
4743   //  resolvedIfx rTrueIfx;
4744   symbol *truelbl;
4745   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4746 /*
4747   if(ifx) {
4748     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4749     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4750   }
4751 */
4752
4753   resolveIfx(&rFalseIfx,ifx);
4754   truelbl  = newiTempLabel(NULL);
4755   size = max(AOP_SIZE(left),AOP_SIZE(right));
4756
4757   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4758
4759 #define _swapp
4760
4761   /* if literal is on the right then swap with left */
4762   if ((AOP_TYPE(right) == AOP_LIT)) {
4763     operand *tmp = right ;
4764     unsigned long mask = (0x100 << (8*(size-1))) - 1;
4765     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4766 #ifdef _swapp
4767
4768     lit = (lit - 1) & mask;
4769     right = left;
4770     left = tmp;
4771     rFalseIfx.condition ^= 1;
4772 #endif
4773
4774   } else if ((AOP_TYPE(left) == AOP_LIT)) {
4775     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4776   }
4777
4778
4779   //if(IC_TRUE(ifx) == NULL)
4780   /* if left & right are bit variables */
4781   if (AOP_TYPE(left) == AOP_CRY &&
4782       AOP_TYPE(right) == AOP_CRY ) {
4783     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4784     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4785   } else {
4786     /* subtract right from left if at the
4787        end the carry flag is set then we know that
4788        left is greater than right */
4789
4790     symbol *lbl  = newiTempLabel(NULL);
4791
4792 #if 0
4793         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4794                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
4795 #endif
4796
4797 #ifndef _swapp
4798     if(AOP_TYPE(right) == AOP_LIT) {
4799
4800       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4801
4802       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4803
4804       /* special cases */
4805
4806       if(lit == 0) {
4807
4808         if(sign != 0) 
4809           genSkipCond(&rFalseIfx,left,size-1,7);
4810         else 
4811           /* no need to compare to 0...*/
4812           /* NOTE: this is a de-generate compare that most certainly 
4813            *       creates some dead code. */
4814           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4815
4816         if(ifx) ifx->generated = 1;
4817         return;
4818
4819       }
4820       size--;
4821
4822       if(size == 0) {
4823         //i = (lit >> (size*8)) & 0xff;
4824         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4825         
4826         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4827
4828         i = ((0-lit) & 0xff);
4829         if(sign) {
4830           if( i == 0x81) { 
4831             /* lit is 0x7f, all signed chars are less than
4832              * this except for 0x7f itself */
4833             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4834             genSkipz2(&rFalseIfx,0);
4835           } else {
4836             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4837             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4838             genSkipc(&rFalseIfx);
4839           }
4840
4841         } else {
4842           if(lit == 1) {
4843             genSkipz2(&rFalseIfx,1);
4844           } else {
4845             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4846             genSkipc(&rFalseIfx);
4847           }
4848         }
4849
4850         if(ifx) ifx->generated = 1;
4851         return;
4852       }
4853
4854       /* chars are out of the way. now do ints and longs */
4855
4856
4857       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4858         
4859       /* special cases */
4860
4861       if(sign) {
4862
4863         if(lit == 0) {
4864           genSkipCond(&rFalseIfx,left,size,7);
4865           if(ifx) ifx->generated = 1;
4866           return;
4867         }
4868
4869         if(lit <0x100) {
4870           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4871
4872           //rFalseIfx.condition ^= 1;
4873           //genSkipCond(&rFalseIfx,left,size,7);
4874           //rFalseIfx.condition ^= 1;
4875
4876           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4877           if(rFalseIfx.condition)
4878             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4879           else
4880             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4881
4882           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4883           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4884           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4885
4886           while(size > 1)
4887             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4888
4889           if(rFalseIfx.condition) {
4890             emitSKPZ;
4891             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4892
4893           } else {
4894             emitSKPNZ;
4895           }
4896
4897           genSkipc(&rFalseIfx);
4898           pic16_emitpLabel(truelbl->key);
4899           if(ifx) ifx->generated = 1;
4900           return;
4901
4902         }
4903
4904         if(size == 1) {
4905
4906           if( (lit & 0xff) == 0) {
4907             /* lower byte is zero */
4908             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4909             i = ((lit >> 8) & 0xff) ^0x80;
4910             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4911             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4912             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4913             genSkipc(&rFalseIfx);
4914
4915
4916             if(ifx) ifx->generated = 1;
4917             return;
4918
4919           }
4920         } else {
4921           /* Special cases for signed longs */
4922           if( (lit & 0xffffff) == 0) {
4923             /* lower byte is zero */
4924             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4925             i = ((lit >> 8*3) & 0xff) ^0x80;
4926             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4927             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4928             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4929             genSkipc(&rFalseIfx);
4930
4931
4932             if(ifx) ifx->generated = 1;
4933             return;
4934
4935           }
4936
4937         }
4938
4939
4940         if(lit & (0x80 << (size*8))) {
4941           /* lit is negative */
4942           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4943
4944           //genSkipCond(&rFalseIfx,left,size,7);
4945
4946           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4947
4948           if(rFalseIfx.condition)
4949             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4950           else
4951             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4952
4953
4954         } else {
4955           /* lit is positive */
4956           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4957           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4958           if(rFalseIfx.condition)
4959             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4960           else
4961             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4962
4963         }
4964
4965         /*
4966           This works, but is only good for ints.
4967           It also requires a "known zero" register.
4968           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4969           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4970           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4971           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4972           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4973           genSkipc(&rFalseIfx);
4974
4975           pic16_emitpLabel(truelbl->key);
4976           if(ifx) ifx->generated = 1;
4977           return;
4978         **/
4979           
4980         /* There are no more special cases, so perform a general compare */
4981   
4982         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4983         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4984
4985         while(size--) {
4986
4987           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4988           emitSKPNZ;
4989           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4990         }
4991         //rFalseIfx.condition ^= 1;
4992         genSkipc(&rFalseIfx);
4993
4994         pic16_emitpLabel(truelbl->key);
4995
4996         if(ifx) ifx->generated = 1;
4997         return;
4998
4999
5000       }
5001
5002
5003       /* sign is out of the way. So now do an unsigned compare */
5004       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5005
5006
5007       /* General case - compare to an unsigned literal on the right.*/
5008
5009       i = (lit >> (size*8)) & 0xff;
5010       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5011       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5012       while(size--) {
5013         i = (lit >> (size*8)) & 0xff;
5014
5015         if(i) {
5016           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5017           emitSKPNZ;
5018           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5019         } else {
5020           /* this byte of the lit is zero, 
5021            *if it's not the last then OR in the variable */
5022           if(size)
5023             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5024         }
5025       }
5026
5027
5028       pic16_emitpLabel(lbl->key);
5029 //      pic16_emitpLabel(truelbl->key);
5030       //if(emitFinalCheck)
5031       genSkipc(&rFalseIfx);
5032       if(sign)
5033         pic16_emitpLabel(truelbl->key);
5034
5035       if(ifx) ifx->generated = 1;
5036       return;
5037
5038
5039     }
5040 #endif  // _swapp
5041
5042     if(AOP_TYPE(left) == AOP_LIT) {
5043       //symbol *lbl = newiTempLabel(NULL);
5044
5045       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5046
5047
5048       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5049
5050       /* Special cases */
5051       if((lit == 0) && (sign == 0)){
5052
5053         size--;
5054         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5055         while(size) 
5056           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5057
5058         genSkipz2(&rFalseIfx,0);
5059         if(ifx) ifx->generated = 1;
5060         return;
5061       }
5062
5063       if(size==1) {
5064         /* Special cases */
5065         lit &= 0xff;
5066         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5067           /* degenerate compare can never be true */
5068           if(rFalseIfx.condition == 0)
5069             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5070
5071           if(ifx) ifx->generated = 1;
5072           return;
5073         }
5074
5075         if(sign) {
5076           /* signed comparisons to a literal byte */
5077
5078           int lp1 = (lit+1) & 0xff;
5079
5080           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5081           switch (lp1) {
5082           case 0:
5083             rFalseIfx.condition ^= 1;
5084             genSkipCond(&rFalseIfx,right,0,7);
5085             break;
5086           case 0x7f:
5087             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5088             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5089             genSkipz2(&rFalseIfx,1);
5090             break;
5091           default:
5092             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5093             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5094             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5095             rFalseIfx.condition ^= 1;
5096             genSkipc(&rFalseIfx);
5097             break;
5098           }
5099         } else {
5100           /* unsigned comparisons to a literal byte */
5101
5102           switch(lit & 0xff ) {
5103           case 0:
5104             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5105             genSkipz2(&rFalseIfx,0);
5106             break;
5107           case 0x7f:
5108             rFalseIfx.condition ^= 1;
5109             genSkipCond(&rFalseIfx,right,0,7);
5110             break;
5111
5112           default:
5113             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5114             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5115             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5116             rFalseIfx.condition ^= 1;
5117             if (AOP_TYPE(result) == AOP_CRY)
5118               genSkipc(&rFalseIfx);
5119             else {
5120               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5121               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5122             }         
5123             break;
5124           }
5125         }
5126
5127         if(ifx) ifx->generated = 1;
5128         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5129                 goto check_carry;
5130         return;
5131
5132       } else {
5133
5134         /* Size is greater than 1 */
5135
5136         if(sign) {
5137           int lp1 = lit+1;
5138
5139           size--;
5140
5141           if(lp1 == 0) {
5142             /* this means lit = 0xffffffff, or -1 */
5143
5144
5145             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5146             rFalseIfx.condition ^= 1;
5147             genSkipCond(&rFalseIfx,right,size,7);
5148             if(ifx) ifx->generated = 1;
5149             return;
5150           }
5151
5152           if(lit == 0) {
5153             int s = size;
5154
5155             if(rFalseIfx.condition) {
5156               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5157               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5158             }
5159
5160             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5161             while(size--)
5162               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5163
5164
5165             emitSKPZ;
5166             if(rFalseIfx.condition) {
5167               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5168               pic16_emitpLabel(truelbl->key);
5169             }else {
5170               rFalseIfx.condition ^= 1;
5171               genSkipCond(&rFalseIfx,right,s,7);
5172             }
5173
5174             if(ifx) ifx->generated = 1;
5175             return;
5176           }
5177
5178           if((size == 1) &&  (0 == (lp1&0xff))) {
5179             /* lower byte of signed word is zero */
5180             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5181             i = ((lp1 >> 8) & 0xff) ^0x80;
5182             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5183             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5184             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5185             rFalseIfx.condition ^= 1;
5186             genSkipc(&rFalseIfx);
5187
5188
5189             if(ifx) ifx->generated = 1;
5190             return;
5191           }
5192
5193           if(lit & (0x80 << (size*8))) {
5194             /* Lit is less than zero */
5195             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5196             //rFalseIfx.condition ^= 1;
5197             //genSkipCond(&rFalseIfx,left,size,7);
5198             //rFalseIfx.condition ^= 1;
5199             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5200             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5201
5202             if(rFalseIfx.condition)
5203               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5204             else
5205               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5206
5207
5208           } else {
5209             /* Lit is greater than or equal to zero */
5210             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5211             //rFalseIfx.condition ^= 1;
5212             //genSkipCond(&rFalseIfx,right,size,7);
5213             //rFalseIfx.condition ^= 1;
5214
5215             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5216             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5217
5218             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5219             if(rFalseIfx.condition)
5220               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5221             else
5222               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5223
5224           }
5225
5226
5227           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5228           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5229
5230           while(size--) {
5231
5232             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5233             emitSKPNZ;
5234             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5235           }
5236           rFalseIfx.condition ^= 1;
5237           //rFalseIfx.condition = 1;
5238           genSkipc(&rFalseIfx);
5239
5240           pic16_emitpLabel(truelbl->key);
5241
5242           if(ifx) ifx->generated = 1;
5243           return;
5244           // end of if (sign)
5245         } else {
5246
5247           /* compare word or long to an unsigned literal on the right.*/
5248
5249
5250           size--;
5251           if(lit < 0xff) {
5252             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5253             switch (lit) {
5254             case 0:
5255               break; /* handled above */
5256 /*
5257             case 0xff:
5258               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5259               while(size--)
5260                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5261               genSkipz2(&rFalseIfx,0);
5262               break;
5263 */
5264             default:
5265               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5266               while(--size)
5267                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5268
5269               emitSKPZ;
5270               if(rFalseIfx.condition)
5271                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5272               else
5273                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5274
5275
5276               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5277               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5278
5279               rFalseIfx.condition ^= 1;
5280               genSkipc(&rFalseIfx);
5281             }
5282
5283             pic16_emitpLabel(truelbl->key);
5284
5285             if(ifx) ifx->generated = 1;
5286             return;
5287           }
5288
5289
5290           lit++;
5291           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5292           i = (lit >> (size*8)) & 0xff;
5293
5294           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5295           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5296
5297           while(size--) {
5298             i = (lit >> (size*8)) & 0xff;
5299
5300             if(i) {
5301               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5302               emitSKPNZ;
5303               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5304             } else {
5305               /* this byte of the lit is zero, 
5306                * if it's not the last then OR in the variable */
5307               if(size)
5308                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5309             }
5310           }
5311
5312
5313           pic16_emitpLabel(lbl->key);
5314
5315           rFalseIfx.condition ^= 1;
5316
5317           genSkipc(&rFalseIfx);
5318         }
5319
5320         if(sign)
5321           pic16_emitpLabel(truelbl->key);
5322         if(ifx) ifx->generated = 1;
5323         return;
5324       }
5325     }
5326     /* Compare two variables */
5327
5328     DEBUGpic16_emitcode(";sign","%d",sign);
5329
5330     size--;
5331     if(sign) {
5332       /* Sigh. thus sucks... */
5333       if(size) {
5334         pCodeOp *pctemp;
5335         
5336         pctemp = pic16_popGetTempReg();
5337         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5338         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5339         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5340         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5341         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5342         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5343         pic16_popReleaseTempReg(pctemp);
5344       } else {
5345         /* Signed char comparison */
5346         /* Special thanks to Nikolai Golovchenko for this snippet */
5347         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5348         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5349         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5350         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5351         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5352         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5353
5354         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5355         genSkipc(&rFalseIfx);
5356           
5357         if(ifx) ifx->generated = 1;
5358         return;
5359       }
5360
5361     } else {
5362
5363       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5364       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5365     }
5366
5367
5368     /* The rest of the bytes of a multi-byte compare */
5369     while (size) {
5370
5371       emitSKPZ;
5372       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5373       size--;
5374
5375       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5376       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5377
5378
5379     }
5380
5381     pic16_emitpLabel(lbl->key);
5382
5383     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5384     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5385         (AOP_TYPE(result) == AOP_REG)) {
5386       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5387       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5388     } else {
5389       genSkipc(&rFalseIfx);
5390     }         
5391     //genSkipc(&rFalseIfx);
5392     if(ifx) ifx->generated = 1;
5393
5394     return;
5395
5396   }
5397
5398 check_carry:
5399   if ((AOP_TYPE(result) != AOP_CRY) 
5400         && AOP_SIZE(result)) {
5401     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5402
5403     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5404
5405     pic16_outBitC(result);
5406   } else {
5407     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5408     /* if the result is used in the next
5409        ifx conditional branch then generate
5410        code a little differently */
5411     if (ifx )
5412       genIfxJump (ifx,"c");
5413     else
5414       pic16_outBitC(result);
5415     /* leave the result in acc */
5416   }
5417
5418 }
5419
5420 /*-----------------------------------------------------------------*/
5421 /* genCmpGt :- greater than comparison                             */
5422 /*-----------------------------------------------------------------*/
5423 static void genCmpGt (iCode *ic, iCode *ifx)
5424 {
5425     operand *left, *right, *result;
5426     sym_link *letype , *retype;
5427     int sign ;
5428
5429     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5430     left = IC_LEFT(ic);
5431     right= IC_RIGHT(ic);
5432     result = IC_RESULT(ic);
5433
5434     letype = getSpec(operandType(left));
5435     retype =getSpec(operandType(right));
5436     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5437     /* assign the amsops */
5438     pic16_aopOp (left,ic,FALSE);
5439     pic16_aopOp (right,ic,FALSE);
5440     pic16_aopOp (result,ic,TRUE);
5441
5442     genCmp(right, left, result, ifx, sign);
5443
5444     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5445     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5446     pic16_freeAsmop(result,NULL,ic,TRUE); 
5447 }
5448
5449 /*-----------------------------------------------------------------*/
5450 /* genCmpLt - less than comparisons                                */
5451 /*-----------------------------------------------------------------*/
5452 static void genCmpLt (iCode *ic, iCode *ifx)
5453 {
5454     operand *left, *right, *result;
5455     sym_link *letype , *retype;
5456     int sign ;
5457
5458     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5459     left = IC_LEFT(ic);
5460     right= IC_RIGHT(ic);
5461     result = IC_RESULT(ic);
5462
5463     letype = getSpec(operandType(left));
5464     retype =getSpec(operandType(right));
5465     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5466
5467     /* assign the amsops */
5468     pic16_aopOp (left,ic,FALSE);
5469     pic16_aopOp (right,ic,FALSE);
5470     pic16_aopOp (result,ic,TRUE);
5471
5472     genCmp(left, right, result, ifx, sign);
5473
5474     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5475     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5476     pic16_freeAsmop(result,NULL,ic,TRUE); 
5477 }
5478
5479 #if 0
5480 // not needed ATM
5481 // FIXME reenable literal optimisation when the pic16 port is stable
5482
5483 /*-----------------------------------------------------------------*/
5484 /* genc16bit2lit - compare a 16 bit value to a literal             */
5485 /*-----------------------------------------------------------------*/
5486 static void genc16bit2lit(operand *op, int lit, int offset)
5487 {
5488   int i;
5489
5490   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
5491   if( (lit&0xff) == 0) 
5492     i=1;
5493   else
5494     i=0;
5495
5496   switch( BYTEofLONG(lit,i)) { 
5497   case 0:
5498     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5499     break;
5500   case 1:
5501     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5502     break;
5503   case 0xff:
5504     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5505     break;
5506   default:
5507     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5508     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5509   }
5510
5511   i ^= 1;
5512
5513   switch( BYTEofLONG(lit,i)) { 
5514   case 0:
5515     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5516     break;
5517   case 1:
5518     emitSKPNZ;
5519     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5520     break;
5521   case 0xff:
5522     emitSKPNZ;
5523     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5524     break;
5525   default:
5526     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5527     emitSKPNZ;
5528     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5529
5530   }
5531
5532 }
5533 #endif
5534
5535 #if 0
5536 // not needed ATM
5537 /*-----------------------------------------------------------------*/
5538 /* gencjneshort - compare and jump if not equal                    */
5539 /*-----------------------------------------------------------------*/
5540 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5541 {
5542   int size = max(AOP_SIZE(left),AOP_SIZE(right));
5543   int offset = 0;
5544   int res_offset = 0;  /* the result may be a different size then left or right */
5545   int res_size = AOP_SIZE(result);
5546   resolvedIfx rIfx;
5547   symbol *lbl, *lbl_done;
5548
5549   unsigned long lit = 0L;
5550   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5551
5552   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5553   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5554   if(result)
5555     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
5556   resolveIfx(&rIfx,ifx);
5557   lbl =  newiTempLabel(NULL);
5558   lbl_done =  newiTempLabel(NULL);
5559
5560
5561   /* if the left side is a literal or 
5562      if the right is in a pointer register and left 
5563      is not */
5564   if ((AOP_TYPE(left) == AOP_LIT) || 
5565       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5566     operand *t = right;
5567     right = left;
5568     left = t;
5569   }
5570   if(AOP_TYPE(right) == AOP_LIT)
5571     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5572
5573   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5574     preserve_result = 1;
5575
5576   if(result && !preserve_result)
5577     {
5578       int i;
5579       for(i = 0; i < AOP_SIZE(result); i++)
5580         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5581     }
5582
5583
5584   /* if the right side is a literal then anything goes */
5585   if (AOP_TYPE(right) == AOP_LIT &&
5586       AOP_TYPE(left) != AOP_DIR ) {
5587     switch(size) {
5588     case 2:
5589       genc16bit2lit(left, lit, 0);
5590       emitSKPZ;
5591       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5592       break;
5593     default:
5594       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5595       while (size--) {
5596         if(lit & 0xff) {
5597           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5598           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5599         } else {
5600           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5601         }
5602
5603         emitSKPZ;
5604         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5605         offset++;
5606         if(res_offset < res_size-1)
5607           res_offset++;
5608         lit >>= 8;
5609       }
5610       break;
5611     }
5612   }
5613
5614   /* if the right side is in a register or in direct space or
5615      if the left is a pointer register & right is not */    
5616   else if (AOP_TYPE(right) == AOP_REG ||
5617            AOP_TYPE(right) == AOP_DIR || 
5618            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5619            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5620     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5621     int lbl_key = lbl->key;
5622
5623     if(result) {
5624       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5625       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5626     }else {
5627       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5628       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5629               __FUNCTION__,__LINE__);
5630       return;
5631     }
5632    
5633 /*     switch(size) { */
5634 /*     case 2: */
5635 /*       genc16bit2lit(left, lit, 0); */
5636 /*       emitSKPNZ; */
5637 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5638 /*       break; */
5639 /*     default: */
5640     while (size--) {
5641       int emit_skip=1;
5642       if((AOP_TYPE(left) == AOP_DIR) && 
5643          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5644
5645         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5646         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5647
5648       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5649             
5650         switch (lit & 0xff) {
5651         case 0:
5652           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5653           break;
5654         case 1:
5655           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5656           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5657           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5658           emit_skip=0;
5659           break;
5660         case 0xff:
5661           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5662           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5663           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5664           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5665           emit_skip=0;
5666           break;
5667         default:
5668           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5669           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5670         }
5671         lit >>= 8;
5672
5673       } else {
5674         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5675       }
5676       if(emit_skip) {
5677         if(AOP_TYPE(result) == AOP_CRY) {
5678           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5679           if(rIfx.condition)
5680             emitSKPNZ;
5681           else
5682             emitSKPZ;
5683           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5684         } else {
5685           /* fix me. probably need to check result size too */
5686           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5687           if(rIfx.condition)
5688             emitSKPZ;
5689           else
5690             emitSKPNZ;
5691           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5692           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5693         }
5694         if(ifx)
5695           ifx->generated=1;
5696       }
5697       emit_skip++;
5698       offset++;
5699       if(res_offset < res_size-1)
5700         res_offset++;
5701     }
5702 /*       break; */
5703 /*     } */
5704   } else if(AOP_TYPE(right) == AOP_REG &&
5705             AOP_TYPE(left) != AOP_DIR){
5706
5707     while(size--) {
5708       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5709       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5710       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5711       if(rIfx.condition)
5712         emitSKPNZ;
5713       else
5714         emitSKPZ;
5715       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5716       offset++;
5717       if(res_offset < res_size-1)
5718         res_offset++;
5719     }
5720       
5721   }else{
5722     /* right is a pointer reg need both a & b */
5723     while(size--) {
5724       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5725       if(strcmp(l,"b"))
5726         pic16_emitcode("mov","b,%s",l);
5727       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5728       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5729       offset++;
5730     }
5731   }
5732
5733   if(result && preserve_result)
5734     {
5735       int i;
5736       for(i = 0; i < AOP_SIZE(result); i++)
5737         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5738     }
5739
5740   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
5741
5742   if(result && preserve_result)
5743     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
5744
5745   if(!rIfx.condition)
5746     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5747
5748   pic16_emitpLabel(lbl->key);
5749
5750   if(result && preserve_result)
5751     {
5752       int i;
5753       for(i = 0; i < AOP_SIZE(result); i++)
5754         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5755
5756       pic16_emitpLabel(lbl_done->key);
5757    }
5758
5759   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5760
5761   if(ifx)
5762     ifx->generated = 1;
5763 }
5764 #endif
5765
5766 #if 0
5767 /*-----------------------------------------------------------------*/
5768 /* gencjne - compare and jump if not equal                         */
5769 /*-----------------------------------------------------------------*/
5770 static void gencjne(operand *left, operand *right, iCode *ifx)
5771 {
5772     symbol *tlbl  = newiTempLabel(NULL);
5773
5774     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5775     gencjneshort(left, right, lbl);
5776
5777     pic16_emitcode("mov","a,%s",one);
5778     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5779     pic16_emitcode("","%05d_DS_:",lbl->key+100);
5780     pic16_emitcode("clr","a");
5781     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5782
5783     pic16_emitpLabel(lbl->key);
5784     pic16_emitpLabel(tlbl->key);
5785
5786 }
5787 #endif
5788
5789
5790 /*-----------------------------------------------------------------*/
5791 /* is_LitOp - check if operand has to be treated as literal        */
5792 /*-----------------------------------------------------------------*/
5793 static bool is_LitOp(operand *op)
5794 {
5795   return (AOP_TYPE(op) == AOP_LIT)
5796       || ( (AOP_TYPE(op) == AOP_PCODE)
5797           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
5798               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ));  
5799 }
5800
5801 /*-----------------------------------------------------------------*/
5802 /* is_LitAOp - check if operand has to be treated as literal        */
5803 /*-----------------------------------------------------------------*/
5804 static bool is_LitAOp(asmop *aop)
5805 {
5806   return (aop->type == AOP_LIT)
5807       || ( (aop->type == AOP_PCODE)
5808           && ( (aop->aopu.pcop->type == PO_LITERAL)
5809               || (aop->aopu.pcop->type == PO_IMMEDIATE) ));  
5810 }
5811
5812
5813
5814 /*-----------------------------------------------------------------*/
5815 /* genCmpEq - generates code for equal to                          */
5816 /*-----------------------------------------------------------------*/
5817 static void genCmpEq (iCode *ic, iCode *ifx)
5818 {
5819   operand *left, *right, *result;
5820   symbol *falselbl = newiTempLabel(NULL);
5821   symbol *donelbl = newiTempLabel(NULL);
5822
5823   int preserve_result = 0;
5824   int generate_result = 0;
5825   int i=0;
5826
5827   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5828   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5829   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5830  
5831   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5832   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5833
5834   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
5835     {
5836       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5837       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
5838       goto release;
5839     }
5840
5841   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
5842     {
5843       operand *tmp = right ;
5844       right = left;
5845       left = tmp;
5846     }
5847
5848   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5849     preserve_result = 1;
5850
5851   if(result && AOP_SIZE(result))
5852     generate_result = 1;
5853
5854   if(generate_result && !preserve_result)
5855     {
5856       for(i = 0; i < AOP_SIZE(result); i++)
5857         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5858     }
5859
5860   for(i=0; i < AOP_SIZE(left); i++)
5861     {
5862       if(AOP_TYPE(left) != AOP_ACC)
5863         {
5864           if(is_LitOp(left))
5865             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
5866           else
5867             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
5868         }
5869       if(is_LitOp(right))
5870         pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
5871       else
5872         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
5873
5874       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
5875     }
5876
5877   // result == true
5878
5879   if(generate_result && preserve_result)
5880     {
5881       for(i = 0; i < AOP_SIZE(result); i++)
5882         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5883     }
5884
5885   if(generate_result)
5886     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
5887
5888   if(generate_result && preserve_result)
5889     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5890
5891   if(ifx && IC_TRUE(ifx))
5892     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5893
5894   if(ifx && IC_FALSE(ifx))
5895     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5896
5897   pic16_emitpLabel(falselbl->key);
5898
5899   // result == false
5900
5901   if(ifx && IC_FALSE(ifx))
5902     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5903
5904   if(generate_result && preserve_result)
5905     {
5906       for(i = 0; i < AOP_SIZE(result); i++)
5907         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5908     }
5909
5910   pic16_emitpLabel(donelbl->key);
5911
5912   if(ifx)
5913     ifx->generated = 1;
5914
5915 release:
5916   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5917   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5918   pic16_freeAsmop(result,NULL,ic,TRUE);
5919
5920 }
5921
5922
5923 #if 0
5924 // old version kept for reference
5925
5926 /*-----------------------------------------------------------------*/
5927 /* genCmpEq - generates code for equal to                          */
5928 /*-----------------------------------------------------------------*/
5929 static void genCmpEq (iCode *ic, iCode *ifx)
5930 {
5931     operand *left, *right, *result;
5932     unsigned long lit = 0L;
5933     int size,offset=0;
5934     symbol *falselbl  = newiTempLabel(NULL);
5935
5936
5937     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5938
5939     if(ifx)
5940       DEBUGpic16_emitcode ("; ifx is non-null","");
5941     else
5942       DEBUGpic16_emitcode ("; ifx is null","");
5943
5944     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5945     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5946     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5947
5948     size = max(AOP_SIZE(left),AOP_SIZE(right));
5949
5950     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5951
5952     /* if literal, literal on the right or 
5953     if the right is in a pointer register and left 
5954     is not */
5955     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
5956         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5957       operand *tmp = right ;
5958       right = left;
5959       left = tmp;
5960     }
5961
5962
5963     if(ifx && !AOP_SIZE(result)){
5964         symbol *tlbl;
5965         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
5966         /* if they are both bit variables */
5967         if (AOP_TYPE(left) == AOP_CRY &&
5968             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5969                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
5970             if(AOP_TYPE(right) == AOP_LIT){
5971                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5972                 if(lit == 0L){
5973                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5974                     pic16_emitcode("cpl","c");
5975                 } else if(lit == 1L) {
5976                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5977                 } else {
5978                     pic16_emitcode("clr","c");
5979                 }
5980                 /* AOP_TYPE(right) == AOP_CRY */
5981             } else {
5982                 symbol *lbl = newiTempLabel(NULL);
5983                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5984                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5985                 pic16_emitcode("cpl","c");
5986                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5987             }
5988             /* if true label then we jump if condition
5989             supplied is true */
5990             tlbl = newiTempLabel(NULL);
5991             if ( IC_TRUE(ifx) ) {
5992                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5993                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5994             } else {
5995                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5996                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5997             }
5998             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5999
6000                 {
6001                 /* left and right are both bit variables, result is carry */
6002                         resolvedIfx rIfx;
6003               
6004                         resolveIfx(&rIfx,ifx);
6005
6006                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6007                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6008                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6009                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6010                         genSkipz2(&rIfx,0);
6011                 }
6012         } else {
6013
6014                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6015
6016                         /* They're not both bit variables. Is the right a literal? */
6017                         if(AOP_TYPE(right) == AOP_LIT) {
6018                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6019             
6020                         switch(size) {
6021
6022                                 case 1:
6023                                         switch(lit & 0xff) {
6024                                                 case 1:
6025                                                                 if ( IC_TRUE(ifx) ) {
6026                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6027                                                                         emitSKPNZ;
6028                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6029                                                                 } else {
6030                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6031                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6032                                                                 }
6033                                                                 break;
6034                                                 case 0xff:
6035                                                                 if ( IC_TRUE(ifx) ) {
6036                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6037                                                                         emitSKPNZ;
6038                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6039                                                                 } else {
6040                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6041                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6042                                                                 }
6043                                                                 break;
6044                                                 default:
6045                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6046                                                                 if(lit)
6047                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6048                                                                 genSkip(ifx,'z');
6049                                         } // switch lit
6050
6051
6052                                         /* end of size == 1 */
6053                                         break;
6054               
6055                                 case 2:
6056                                         genc16bit2lit(left,lit,offset);
6057                                         genSkip(ifx,'z');
6058                                         break;
6059                                         /* end of size == 2 */
6060
6061                                 default:
6062                                         /* size is 4 */
6063                                         if(lit==0) {
6064                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6065                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6066                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6067                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6068                                                 genSkip(ifx,'z');
6069                                         } else {
6070                                                 /* search for patterns that can be optimized */
6071
6072                                                 genc16bit2lit(left,lit,0);
6073                                                 lit >>= 16;
6074                                                 if(lit) {
6075                                                                 if(IC_TRUE(ifx))
6076                                                                 emitSKPZ; // if hi word unequal
6077                                                                 else
6078                                                                 emitSKPNZ; // if hi word equal
6079                                                                 // fail early
6080                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6081                                                         genc16bit2lit(left,lit,2);
6082                                                         genSkip(ifx,'z');
6083                                                 } else {
6084                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6085                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6086                                                         genSkip(ifx,'z');
6087                                                 }
6088                                         }
6089                                                 pic16_emitpLabel(falselbl->key);
6090                                                 break;
6091
6092                         } // switch size
6093           
6094                         ifx->generated = 1;
6095                         goto release ;
6096             
6097
6098           } else if(AOP_TYPE(right) == AOP_CRY ) {
6099             /* we know the left is not a bit, but that the right is */
6100             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6101             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6102                       pic16_popGet(AOP(right),offset));
6103             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6104
6105             /* if the two are equal, then W will be 0 and the Z bit is set
6106              * we could test Z now, or go ahead and check the high order bytes if
6107              * the variable we're comparing is larger than a byte. */
6108
6109             while(--size)
6110               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6111
6112             if ( IC_TRUE(ifx) ) {
6113               emitSKPNZ;
6114               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6115               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6116             } else {
6117               emitSKPZ;
6118               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6119               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6120             }
6121
6122           } else {
6123             /* They're both variables that are larger than bits */
6124             int s = size;
6125
6126             tlbl = newiTempLabel(NULL);
6127
6128             while(size--) {
6129               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6130               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6131
6132               if ( IC_TRUE(ifx) ) {
6133                 if(size) {
6134                   emitSKPZ;
6135                 
6136                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6137
6138                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6139                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6140                 } else {
6141                   emitSKPNZ;
6142
6143                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6144
6145
6146                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6147                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6148                 }
6149               } else {
6150                 emitSKPZ;
6151
6152                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6153
6154                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6155                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6156               }
6157               offset++;
6158             }
6159             if(s>1 && IC_TRUE(ifx)) {
6160               pic16_emitpLabel(tlbl->key);
6161               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
6162             }
6163           }
6164         }
6165         /* mark the icode as generated */
6166         ifx->generated = 1;
6167         goto release ;
6168     }
6169
6170     /* if they are both bit variables */
6171     if (AOP_TYPE(left) == AOP_CRY &&
6172         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6173         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
6174         if(AOP_TYPE(right) == AOP_LIT){
6175             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6176             if(lit == 0L){
6177                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6178                 pic16_emitcode("cpl","c");
6179             } else if(lit == 1L) {
6180                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6181             } else {
6182                 pic16_emitcode("clr","c");
6183             }
6184             /* AOP_TYPE(right) == AOP_CRY */
6185         } else {
6186             symbol *lbl = newiTempLabel(NULL);
6187             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6188             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6189             pic16_emitcode("cpl","c");
6190             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6191         }
6192         /* c = 1 if egal */
6193         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
6194             pic16_outBitC(result);
6195             goto release ;
6196         }
6197         if (ifx) {
6198             genIfxJump (ifx,"c");
6199             goto release ;
6200         }
6201         /* if the result is used in an arithmetic operation
6202         then put the result in place */
6203         pic16_outBitC(result);
6204     } else {
6205       
6206       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
6207       gencjne(left,right,result,ifx);
6208 /*
6209       if(ifx) 
6210         gencjne(left,right,newiTempLabel(NULL));
6211       else {
6212         if(IC_TRUE(ifx)->key)
6213           gencjne(left,right,IC_TRUE(ifx)->key);
6214         else
6215           gencjne(left,right,IC_FALSE(ifx)->key);
6216         ifx->generated = 1;
6217         goto release ;
6218       }
6219       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
6220         pic16_aopPut(AOP(result),"a",0);
6221         goto release ;
6222       }
6223
6224       if (ifx) {
6225         genIfxJump (ifx,"a");
6226         goto release ;
6227       }
6228 */
6229       /* if the result is used in an arithmetic operation
6230          then put the result in place */
6231 /*
6232       if (AOP_TYPE(result) != AOP_CRY) 
6233         pic16_outAcc(result);
6234 */
6235       /* leave the result in acc */
6236     }
6237
6238 release:
6239     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6240     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6241     pic16_freeAsmop(result,NULL,ic,TRUE);
6242 }
6243 #endif
6244
6245 /*-----------------------------------------------------------------*/
6246 /* ifxForOp - returns the icode containing the ifx for operand     */
6247 /*-----------------------------------------------------------------*/
6248 static iCode *ifxForOp ( operand *op, iCode *ic )
6249 {
6250     /* if true symbol then needs to be assigned */
6251     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6252     if (IS_TRUE_SYMOP(op))
6253         return NULL ;
6254
6255     /* if this has register type condition and
6256     the next instruction is ifx with the same operand
6257     and live to of the operand is upto the ifx only then */
6258     if (ic->next
6259         && ic->next->op == IFX
6260         && IC_COND(ic->next)->key == op->key
6261         && OP_SYMBOL(op)->liveTo <= ic->next->seq
6262         ) {
6263                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
6264           return ic->next;
6265     }
6266
6267     if (ic->next &&
6268         ic->next->op == IFX &&
6269         IC_COND(ic->next)->key == op->key) {
6270       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6271       return ic->next;
6272     }
6273
6274     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
6275     if (ic->next &&
6276         ic->next->op == IFX)
6277       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
6278
6279     if (ic->next &&
6280         ic->next->op == IFX &&
6281         IC_COND(ic->next)->key == op->key) {
6282       DEBUGpic16_emitcode ("; "," key is okay");
6283       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
6284                            OP_SYMBOL(op)->liveTo,
6285                            ic->next->seq);
6286     }
6287
6288 #if 0
6289     /* the code below is completely untested
6290      * it just allows ulong2fs.c compile -- VR */
6291          
6292     ic = ic->next;
6293     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
6294                                         __FILE__, __FUNCTION__, __LINE__);
6295         
6296     /* if this has register type condition and
6297     the next instruction is ifx with the same operand
6298     and live to of the operand is upto the ifx only then */
6299     if (ic->next &&
6300         ic->next->op == IFX &&
6301         IC_COND(ic->next)->key == op->key &&
6302         OP_SYMBOL(op)->liveTo <= ic->next->seq )
6303         return ic->next;
6304
6305     if (ic->next &&
6306         ic->next->op == IFX &&
6307         IC_COND(ic->next)->key == op->key) {
6308       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6309       return ic->next;
6310     }
6311
6312     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
6313                                         __FILE__, __FUNCTION__, __LINE__);
6314
6315 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
6316 #endif
6317
6318     return NULL;
6319 }
6320 /*-----------------------------------------------------------------*/
6321 /* genAndOp - for && operation                                     */
6322 /*-----------------------------------------------------------------*/
6323 static void genAndOp (iCode *ic)
6324 {
6325     operand *left,*right, *result;
6326 /*     symbol *tlbl; */
6327
6328     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6329     /* note here that && operations that are in an
6330     if statement are taken away by backPatchLabels
6331     only those used in arthmetic operations remain */
6332     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6333     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6334     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6335
6336     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6337
6338     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6339     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
6340     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
6341
6342     /* if both are bit variables */
6343 /*     if (AOP_TYPE(left) == AOP_CRY && */
6344 /*         AOP_TYPE(right) == AOP_CRY ) { */
6345 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
6346 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
6347 /*         pic16_outBitC(result); */
6348 /*     } else { */
6349 /*         tlbl = newiTempLabel(NULL); */
6350 /*         pic16_toBoolean(left);     */
6351 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
6352 /*         pic16_toBoolean(right); */
6353 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
6354 /*         pic16_outBitAcc(result); */
6355 /*     } */
6356
6357     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6358     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6359     pic16_freeAsmop(result,NULL,ic,TRUE);
6360 }
6361
6362
6363 /*-----------------------------------------------------------------*/
6364 /* genOrOp - for || operation                                      */
6365 /*-----------------------------------------------------------------*/
6366 /*
6367   tsd pic port -
6368   modified this code, but it doesn't appear to ever get called
6369 */
6370
6371 static void genOrOp (iCode *ic)
6372 {
6373     operand *left,*right, *result;
6374     symbol *tlbl;
6375
6376     /* note here that || operations that are in an
6377     if statement are taken away by backPatchLabels
6378     only those used in arthmetic operations remain */
6379     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6380     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6381     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6382     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6383
6384     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6385
6386     /* if both are bit variables */
6387     if (AOP_TYPE(left) == AOP_CRY &&
6388         AOP_TYPE(right) == AOP_CRY ) {
6389       pic16_emitcode("clrc","");
6390       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6391                AOP(left)->aopu.aop_dir,
6392                AOP(left)->aopu.aop_dir);
6393       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6394                AOP(right)->aopu.aop_dir,
6395                AOP(right)->aopu.aop_dir);
6396       pic16_emitcode("setc","");
6397
6398     } else {
6399         tlbl = newiTempLabel(NULL);
6400         pic16_toBoolean(left);
6401         emitSKPZ;
6402         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
6403         pic16_toBoolean(right);
6404         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6405
6406         pic16_outBitAcc(result);
6407     }
6408
6409     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6410     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6411     pic16_freeAsmop(result,NULL,ic,TRUE);            
6412 }
6413
6414 /*-----------------------------------------------------------------*/
6415 /* isLiteralBit - test if lit == 2^n                               */
6416 /*-----------------------------------------------------------------*/
6417 static int isLiteralBit(unsigned long lit)
6418 {
6419     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
6420     0x100L,0x200L,0x400L,0x800L,
6421     0x1000L,0x2000L,0x4000L,0x8000L,
6422     0x10000L,0x20000L,0x40000L,0x80000L,
6423     0x100000L,0x200000L,0x400000L,0x800000L,
6424     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
6425     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
6426     int idx;
6427     
6428     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6429     for(idx = 0; idx < 32; idx++)
6430         if(lit == pw[idx])
6431             return idx+1;
6432     return 0;
6433 }
6434
6435 /*-----------------------------------------------------------------*/
6436 /* continueIfTrue -                                                */
6437 /*-----------------------------------------------------------------*/
6438 static void continueIfTrue (iCode *ic)
6439 {
6440     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6441     if(IC_TRUE(ic))
6442         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6443     ic->generated = 1;
6444 }
6445
6446 /*-----------------------------------------------------------------*/
6447 /* jmpIfTrue -                                                     */
6448 /*-----------------------------------------------------------------*/
6449 static void jumpIfTrue (iCode *ic)
6450 {
6451     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6452     if(!IC_TRUE(ic))
6453         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6454     ic->generated = 1;
6455 }
6456
6457 /*-----------------------------------------------------------------*/
6458 /* jmpTrueOrFalse -                                                */
6459 /*-----------------------------------------------------------------*/
6460 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
6461 {
6462     // ugly but optimized by peephole
6463     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6464     if(IC_TRUE(ic)){
6465         symbol *nlbl = newiTempLabel(NULL);
6466         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
6467         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6468         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6469         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
6470     }
6471     else{
6472         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6473         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6474     }
6475     ic->generated = 1;
6476 }
6477
6478 /*-----------------------------------------------------------------*/
6479 /* genAnd  - code for and                                          */
6480 /*-----------------------------------------------------------------*/
6481 static void genAnd (iCode *ic, iCode *ifx)
6482 {
6483   operand *left, *right, *result;
6484   int size, offset=0;  
6485   unsigned long lit = 0L;
6486   int bytelit = 0;
6487   resolvedIfx rIfx;
6488
6489
6490   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6491   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6492   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6493   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6494
6495   resolveIfx(&rIfx,ifx);
6496
6497   /* if left is a literal & right is not then exchange them */
6498   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6499       AOP_NEEDSACC(left)) {
6500     operand *tmp = right ;
6501     right = left;
6502     left = tmp;
6503   }
6504
6505   /* if result = right then exchange them */
6506   if(pic16_sameRegs(AOP(result),AOP(right))){
6507     operand *tmp = right ;
6508     right = left;
6509     left = tmp;
6510   }
6511
6512   /* if right is bit then exchange them */
6513   if (AOP_TYPE(right) == AOP_CRY &&
6514       AOP_TYPE(left) != AOP_CRY){
6515     operand *tmp = right ;
6516     right = left;
6517     left = tmp;
6518   }
6519   if(AOP_TYPE(right) == AOP_LIT)
6520     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6521
6522   size = AOP_SIZE(result);
6523
6524   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6525
6526   // if(bit & yy)
6527   // result = bit & yy;
6528   if (AOP_TYPE(left) == AOP_CRY){
6529     // c = bit & literal;
6530     if(AOP_TYPE(right) == AOP_LIT){
6531       if(lit & 1) {
6532         if(size && pic16_sameRegs(AOP(result),AOP(left)))
6533           // no change
6534           goto release;
6535         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6536       } else {
6537         // bit(result) = 0;
6538         if(size && (AOP_TYPE(result) == AOP_CRY)){
6539           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
6540           goto release;
6541         }
6542         if((AOP_TYPE(result) == AOP_CRY) && ifx){
6543           jumpIfTrue(ifx);
6544           goto release;
6545         }
6546         pic16_emitcode("clr","c");
6547       }
6548     } else {
6549       if (AOP_TYPE(right) == AOP_CRY){
6550         // c = bit & bit;
6551         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6552         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6553       } else {
6554         // c = bit & val;
6555         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
6556         // c = lsb
6557         pic16_emitcode("rrc","a");
6558         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6559       }
6560     }
6561     // bit = c
6562     // val = c
6563     if(size)
6564       pic16_outBitC(result);
6565     // if(bit & ...)
6566     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6567       genIfxJump(ifx, "c");           
6568     goto release ;
6569   }
6570
6571   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6572   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6573   if((AOP_TYPE(right) == AOP_LIT) &&
6574      (AOP_TYPE(result) == AOP_CRY) &&
6575      (AOP_TYPE(left) != AOP_CRY)){
6576     int posbit = isLiteralBit(lit);
6577     /* left &  2^n */
6578     if(posbit){
6579       posbit--;
6580       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6581       // bit = left & 2^n
6582       if(size)
6583         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6584       // if(left &  2^n)
6585       else{
6586         if(ifx){
6587 /*
6588           if(IC_TRUE(ifx)) {
6589             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6590             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
6591           } else {
6592             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6593             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
6594           }
6595 */
6596         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
6597         size = AOP_SIZE(left);
6598
6599         {
6600           int bp = posbit, ofs=0;
6601           
6602             while(bp > 7) {
6603               bp -= 8;
6604               ofs++;
6605             }
6606         
6607           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6608                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
6609
6610         }
6611 /*
6612           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6613                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6614 */
6615           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6616           
6617           ifx->generated = 1;
6618         }
6619         goto release;
6620       }
6621     } else {
6622       symbol *tlbl = newiTempLabel(NULL);
6623       int sizel = AOP_SIZE(left);
6624
6625       if(size)
6626         emitSETC;
6627
6628       while(sizel--) {
6629         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
6630
6631           /* patch provided by Aaron Colwell */
6632           if((posbit = isLiteralBit(bytelit)) != 0) {
6633               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
6634                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
6635                                                 (posbit-1),0, PO_GPR_REGISTER));
6636
6637               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
6638 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
6639           } else {
6640               if (bytelit == 0xff) {
6641                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
6642                    * a peephole could optimize it out -- VR */
6643                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
6644               } else {
6645                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
6646                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
6647               }
6648
6649               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
6650                             pic16_popGetLabel(tlbl->key));
6651           }
6652         
6653 #if 0
6654           /* old code, left here for reference -- VR 09/2004 */
6655           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6656           // byte ==  2^n ?
6657           if((posbit = isLiteralBit(bytelit)) != 0)
6658             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6659           else{
6660             if(bytelit != 0x0FFL)
6661               pic16_emitcode("anl","a,%s",
6662                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6663             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6664           }
6665 #endif
6666         }
6667         offset++;
6668       }
6669       // bit = left & literal
6670       if(size) {
6671         emitCLRC;
6672         pic16_emitpLabel(tlbl->key);
6673       }
6674       // if(left & literal)
6675       else {
6676         if(ifx) {
6677           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
6678           pic16_emitpLabel(tlbl->key);
6679           ifx->generated = 1;
6680         }
6681         goto release;
6682       }
6683     }
6684
6685     pic16_outBitC(result);
6686     goto release ;
6687   }
6688
6689   /* if left is same as result */
6690   if(pic16_sameRegs(AOP(result),AOP(left))){
6691     int know_W = -1;
6692     for(;size--; offset++,lit>>=8) {
6693       if(AOP_TYPE(right) == AOP_LIT){
6694         switch(lit & 0xff) {
6695         case 0x00:
6696           /*  and'ing with 0 has clears the result */
6697 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6698           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6699           break;
6700         case 0xff:
6701           /* and'ing with 0xff is a nop when the result and left are the same */
6702           break;
6703
6704         default:
6705           {
6706             int p = my_powof2( (~lit) & 0xff );
6707             if(p>=0) {
6708               /* only one bit is set in the literal, so use a bcf instruction */
6709 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6710               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
6711
6712             } else {
6713               pic16_emitcode("movlw","0x%x", (lit & 0xff));
6714               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6715               if(know_W != (lit&0xff))
6716                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6717               know_W = lit &0xff;
6718               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6719             }
6720           }    
6721         }
6722       } else {
6723         if (AOP_TYPE(left) == AOP_ACC) {
6724           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6725         } else {                    
6726           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6727           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6728
6729         }
6730       }
6731     }
6732
6733   } else {
6734     // left & result in different registers
6735     if(AOP_TYPE(result) == AOP_CRY){
6736       // result = bit
6737       // if(size), result in bit
6738       // if(!size && ifx), conditional oper: if(left & right)
6739       symbol *tlbl = newiTempLabel(NULL);
6740       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6741       if(size)
6742         pic16_emitcode("setb","c");
6743       while(sizer--){
6744         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6745         pic16_emitcode("anl","a,%s",
6746                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6747         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6748         offset++;
6749       }
6750       if(size){
6751         CLRC;
6752         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6753         pic16_outBitC(result);
6754       } else if(ifx)
6755         jmpTrueOrFalse(ifx, tlbl);
6756     } else {
6757       for(;(size--);offset++) {
6758         // normal case
6759         // result = left & right
6760         if(AOP_TYPE(right) == AOP_LIT){
6761           int t = (lit >> (offset*8)) & 0x0FFL;
6762           switch(t) { 
6763           case 0x00:
6764             pic16_emitcode("clrf","%s",
6765                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6766             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6767             break;
6768           case 0xff:
6769             pic16_emitcode("movf","%s,w",
6770                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6771             pic16_emitcode("movwf","%s",
6772                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6773             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6774             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6775             break;
6776           default:
6777             pic16_emitcode("movlw","0x%x",t);
6778             pic16_emitcode("andwf","%s,w",
6779                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6780             pic16_emitcode("movwf","%s",
6781                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6782               
6783             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6784             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6785             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6786           }
6787           continue;
6788         }
6789
6790         if (AOP_TYPE(left) == AOP_ACC) {
6791           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6792           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6793         } else {
6794           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6795           pic16_emitcode("andwf","%s,w",
6796                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6797           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6798           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6799         }
6800         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6801         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6802       }
6803     }
6804   }
6805
6806   release :
6807     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6808   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6809   pic16_freeAsmop(result,NULL,ic,TRUE);     
6810 }
6811
6812 /*-----------------------------------------------------------------*/
6813 /* genOr  - code for or                                            */
6814 /*-----------------------------------------------------------------*/
6815 static void genOr (iCode *ic, iCode *ifx)
6816 {
6817     operand *left, *right, *result;
6818     int size, offset=0;
6819     unsigned long lit = 0L;
6820
6821     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6822
6823     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6824     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6825     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6826
6827     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6828
6829     /* if left is a literal & right is not then exchange them */
6830     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6831         AOP_NEEDSACC(left)) {
6832         operand *tmp = right ;
6833         right = left;
6834         left = tmp;
6835     }
6836
6837     /* if result = right then exchange them */
6838     if(pic16_sameRegs(AOP(result),AOP(right))){
6839         operand *tmp = right ;
6840         right = left;
6841         left = tmp;
6842     }
6843
6844     /* if right is bit then exchange them */
6845     if (AOP_TYPE(right) == AOP_CRY &&
6846         AOP_TYPE(left) != AOP_CRY){
6847         operand *tmp = right ;
6848         right = left;
6849         left = tmp;
6850     }
6851
6852     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6853
6854     if(AOP_TYPE(right) == AOP_LIT)
6855         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6856
6857     size = AOP_SIZE(result);
6858
6859     // if(bit | yy)
6860     // xx = bit | yy;
6861     if (AOP_TYPE(left) == AOP_CRY){
6862         if(AOP_TYPE(right) == AOP_LIT){
6863             // c = bit & literal;
6864             if(lit){
6865                 // lit != 0 => result = 1
6866                 if(AOP_TYPE(result) == AOP_CRY){
6867                   if(size)
6868                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6869                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6870                   //     AOP(result)->aopu.aop_dir,
6871                   //     AOP(result)->aopu.aop_dir);
6872                     else if(ifx)
6873                         continueIfTrue(ifx);
6874                     goto release;
6875                 }
6876             } else {
6877                 // lit == 0 => result = left
6878                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6879                     goto release;
6880                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6881             }
6882         } else {
6883             if (AOP_TYPE(right) == AOP_CRY){
6884               if(pic16_sameRegs(AOP(result),AOP(left))){
6885                 // c = bit | bit;
6886                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6887                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6888                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6889
6890                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6891                          AOP(result)->aopu.aop_dir,
6892                          AOP(result)->aopu.aop_dir);
6893                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6894                          AOP(right)->aopu.aop_dir,
6895                          AOP(right)->aopu.aop_dir);
6896                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6897                          AOP(result)->aopu.aop_dir,
6898                          AOP(result)->aopu.aop_dir);
6899               } else {
6900                 if( AOP_TYPE(result) == AOP_ACC) {
6901                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6902                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6903                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6904                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6905
6906                 } else {
6907
6908                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6909                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6910                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6911                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6912
6913                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6914                                  AOP(result)->aopu.aop_dir,
6915                                  AOP(result)->aopu.aop_dir);
6916                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6917                                  AOP(right)->aopu.aop_dir,
6918                                  AOP(right)->aopu.aop_dir);
6919                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6920                                  AOP(left)->aopu.aop_dir,
6921                                  AOP(left)->aopu.aop_dir);
6922                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6923                                  AOP(result)->aopu.aop_dir,
6924                                  AOP(result)->aopu.aop_dir);
6925                 }
6926               }
6927             } else {
6928                 // c = bit | val;
6929                 symbol *tlbl = newiTempLabel(NULL);
6930                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6931
6932
6933                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6934                 if( AOP_TYPE(right) == AOP_ACC) {
6935                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6936                   emitSKPNZ;
6937                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6938                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6939                 }
6940
6941
6942
6943                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6944                     pic16_emitcode(";XXX setb","c");
6945                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6946                          AOP(left)->aopu.aop_dir,tlbl->key+100);
6947                 pic16_toBoolean(right);
6948                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6949                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6950                     jmpTrueOrFalse(ifx, tlbl);
6951                     goto release;
6952                 } else {
6953                     CLRC;
6954                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6955                 }
6956             }
6957         }
6958         // bit = c
6959         // val = c
6960         if(size)
6961             pic16_outBitC(result);
6962         // if(bit | ...)
6963         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6964             genIfxJump(ifx, "c");           
6965         goto release ;
6966     }
6967
6968     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6969     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6970     if((AOP_TYPE(right) == AOP_LIT) &&
6971        (AOP_TYPE(result) == AOP_CRY) &&
6972        (AOP_TYPE(left) != AOP_CRY)){
6973         if(lit){
6974           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6975             // result = 1
6976             if(size)
6977                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6978             else 
6979                 continueIfTrue(ifx);
6980             goto release;
6981         } else {
6982           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6983             // lit = 0, result = boolean(left)
6984             if(size)
6985                 pic16_emitcode(";XXX setb","c");
6986             pic16_toBoolean(right);
6987             if(size){
6988                 symbol *tlbl = newiTempLabel(NULL);
6989                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6990                 CLRC;
6991                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6992             } else {
6993                 genIfxJump (ifx,"a");
6994                 goto release;
6995             }
6996         }
6997         pic16_outBitC(result);
6998         goto release ;
6999     }
7000
7001     /* if left is same as result */
7002     if(pic16_sameRegs(AOP(result),AOP(left))){
7003       int know_W = -1;
7004       for(;size--; offset++,lit>>=8) {
7005         if(AOP_TYPE(right) == AOP_LIT){
7006           if((lit & 0xff) == 0)
7007             /*  or'ing with 0 has no effect */
7008             continue;
7009           else {
7010             int p = my_powof2(lit & 0xff);
7011             if(p>=0) {
7012               /* only one bit is set in the literal, so use a bsf instruction */
7013               pic16_emitpcode(POC_BSF,
7014                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7015             } else {
7016               if(know_W != (lit & 0xff))
7017                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7018               know_W = lit & 0xff;
7019               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7020             }
7021                     
7022           }
7023         } else {
7024           if (AOP_TYPE(left) == AOP_ACC) {
7025             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7026             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7027           } else {                  
7028             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7029             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7030
7031             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7032             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7033
7034           }
7035         }
7036       }
7037     } else {
7038         // left & result in different registers
7039         if(AOP_TYPE(result) == AOP_CRY){
7040             // result = bit
7041             // if(size), result in bit
7042             // if(!size && ifx), conditional oper: if(left | right)
7043             symbol *tlbl = newiTempLabel(NULL);
7044             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7045             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7046
7047
7048             if(size)
7049                 pic16_emitcode(";XXX setb","c");
7050             while(sizer--){
7051                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7052                 pic16_emitcode(";XXX orl","a,%s",
7053                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7054                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7055                 offset++;
7056             }
7057             if(size){
7058                 CLRC;
7059                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7060                 pic16_outBitC(result);
7061             } else if(ifx)
7062                 jmpTrueOrFalse(ifx, tlbl);
7063         } else for(;(size--);offset++){
7064           // normal case
7065           // result = left & right
7066           if(AOP_TYPE(right) == AOP_LIT){
7067             int t = (lit >> (offset*8)) & 0x0FFL;
7068             switch(t) { 
7069             case 0x00:
7070               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7071               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7072
7073               pic16_emitcode("movf","%s,w",
7074                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7075               pic16_emitcode("movwf","%s",
7076                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7077               break;
7078             default:
7079               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7080               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7081               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7082
7083               pic16_emitcode("movlw","0x%x",t);
7084               pic16_emitcode("iorwf","%s,w",
7085                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7086               pic16_emitcode("movwf","%s",
7087                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7088               
7089             }
7090             continue;
7091           }
7092
7093           // faster than result <- left, anl result,right
7094           // and better if result is SFR
7095           if (AOP_TYPE(left) == AOP_ACC) {
7096             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7097             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7098           } else {
7099             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7100             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7101
7102             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7103             pic16_emitcode("iorwf","%s,w",
7104                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7105           }
7106           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7107           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7108         }
7109     }
7110
7111 release :
7112     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7113     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7114     pic16_freeAsmop(result,NULL,ic,TRUE);     
7115 }
7116
7117 /*-----------------------------------------------------------------*/
7118 /* genXor - code for xclusive or                                   */
7119 /*-----------------------------------------------------------------*/
7120 static void genXor (iCode *ic, iCode *ifx)
7121 {
7122   operand *left, *right, *result;
7123   int size, offset=0;
7124   unsigned long lit = 0L;
7125
7126   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7127
7128   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7129   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7130   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7131
7132   /* if left is a literal & right is not ||
7133      if left needs acc & right does not */
7134   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7135       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7136     operand *tmp = right ;
7137     right = left;
7138     left = tmp;
7139   }
7140
7141   /* if result = right then exchange them */
7142   if(pic16_sameRegs(AOP(result),AOP(right))){
7143     operand *tmp = right ;
7144     right = left;
7145     left = tmp;
7146   }
7147
7148   /* if right is bit then exchange them */
7149   if (AOP_TYPE(right) == AOP_CRY &&
7150       AOP_TYPE(left) != AOP_CRY){
7151     operand *tmp = right ;
7152     right = left;
7153     left = tmp;
7154   }
7155   if(AOP_TYPE(right) == AOP_LIT)
7156     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7157
7158   size = AOP_SIZE(result);
7159
7160   // if(bit ^ yy)
7161   // xx = bit ^ yy;
7162   if (AOP_TYPE(left) == AOP_CRY){
7163     if(AOP_TYPE(right) == AOP_LIT){
7164       // c = bit & literal;
7165       if(lit>>1){
7166         // lit>>1  != 0 => result = 1
7167         if(AOP_TYPE(result) == AOP_CRY){
7168           if(size)
7169             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
7170             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7171           else if(ifx)
7172             continueIfTrue(ifx);
7173           goto release;
7174         }
7175         pic16_emitcode("setb","c");
7176       } else{
7177         // lit == (0 or 1)
7178         if(lit == 0){
7179           // lit == 0, result = left
7180           if(size && pic16_sameRegs(AOP(result),AOP(left)))
7181             goto release;
7182           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7183         } else{
7184           // lit == 1, result = not(left)
7185           if(size && pic16_sameRegs(AOP(result),AOP(left))){
7186             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
7187             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
7188             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
7189             goto release;
7190           } else {
7191             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7192             pic16_emitcode("cpl","c");
7193           }
7194         }
7195       }
7196
7197     } else {
7198       // right != literal
7199       symbol *tlbl = newiTempLabel(NULL);
7200       if (AOP_TYPE(right) == AOP_CRY){
7201         // c = bit ^ bit;
7202         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7203       }
7204       else{
7205         int sizer = AOP_SIZE(right);
7206         // c = bit ^ val
7207         // if val>>1 != 0, result = 1
7208         pic16_emitcode("setb","c");
7209         while(sizer){
7210           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
7211           if(sizer == 1)
7212             // test the msb of the lsb
7213             pic16_emitcode("anl","a,#0xfe");
7214           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7215           sizer--;
7216         }
7217         // val = (0,1)
7218         pic16_emitcode("rrc","a");
7219       }
7220       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
7221       pic16_emitcode("cpl","c");
7222       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
7223     }
7224     // bit = c
7225     // val = c
7226     if(size)
7227       pic16_outBitC(result);
7228     // if(bit | ...)
7229     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7230       genIfxJump(ifx, "c");           
7231     goto release ;
7232   }
7233
7234   if(pic16_sameRegs(AOP(result),AOP(left))){
7235     /* if left is same as result */
7236     for(;size--; offset++) {
7237       if(AOP_TYPE(right) == AOP_LIT){
7238         int t  = (lit >> (offset*8)) & 0x0FFL;
7239         if(t == 0x00L)
7240           continue;
7241         else
7242           if (IS_AOP_PREG(left)) {
7243             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7244             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7245             pic16_aopPut(AOP(result),"a",offset);
7246           } else {
7247             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7248             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7249             pic16_emitcode("xrl","%s,%s",
7250                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
7251                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7252           }
7253       } else {
7254         if (AOP_TYPE(left) == AOP_ACC)
7255           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7256         else {
7257           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7258           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7259 /*
7260           if (IS_AOP_PREG(left)) {
7261             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7262             pic16_aopPut(AOP(result),"a",offset);
7263           } else
7264             pic16_emitcode("xrl","%s,a",
7265                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7266 */
7267         }
7268       }
7269     }
7270   } else {
7271     // left & result in different registers
7272     if(AOP_TYPE(result) == AOP_CRY){
7273       // result = bit
7274       // if(size), result in bit
7275       // if(!size && ifx), conditional oper: if(left ^ right)
7276       symbol *tlbl = newiTempLabel(NULL);
7277       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7278       if(size)
7279         pic16_emitcode("setb","c");
7280       while(sizer--){
7281         if((AOP_TYPE(right) == AOP_LIT) &&
7282            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
7283           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7284         } else {
7285           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7286           pic16_emitcode("xrl","a,%s",
7287                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7288         }
7289         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7290         offset++;
7291       }
7292       if(size){
7293         CLRC;
7294         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7295         pic16_outBitC(result);
7296       } else if(ifx)
7297         jmpTrueOrFalse(ifx, tlbl);
7298     } else for(;(size--);offset++){
7299       // normal case
7300       // result = left & right
7301       if(AOP_TYPE(right) == AOP_LIT){
7302         int t = (lit >> (offset*8)) & 0x0FFL;
7303         switch(t) { 
7304         case 0x00:
7305           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7306           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7307           pic16_emitcode("movf","%s,w",
7308                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7309           pic16_emitcode("movwf","%s",
7310                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7311           break;
7312         case 0xff:
7313           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
7314           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7315           pic16_emitcode("comf","%s,w",
7316                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7317           pic16_emitcode("movwf","%s",
7318                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7319           break;
7320         default:
7321           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7322           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7323           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7324           pic16_emitcode("movlw","0x%x",t);
7325           pic16_emitcode("xorwf","%s,w",
7326                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7327           pic16_emitcode("movwf","%s",
7328                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7329
7330         }
7331         continue;
7332       }
7333
7334       // faster than result <- left, anl result,right
7335       // and better if result is SFR
7336       if (AOP_TYPE(left) == AOP_ACC) {
7337         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7338         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7339       } else {
7340         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7341         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7342         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7343         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7344       }
7345       if ( AOP_TYPE(result) != AOP_ACC){
7346         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7347         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7348       }
7349     }
7350   }
7351
7352   release :
7353     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7354   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7355   pic16_freeAsmop(result,NULL,ic,TRUE);     
7356 }
7357
7358 /*-----------------------------------------------------------------*/
7359 /* genInline - write the inline code out                           */
7360 /*-----------------------------------------------------------------*/
7361 static void genInline (iCode *ic)
7362 {
7363   char *buffer, *bp, *bp1;
7364     
7365         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7366
7367         _G.inLine += (!options.asmpeep);
7368
7369         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7370         strcpy(buffer,IC_INLINE(ic));
7371
7372 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
7373
7374         /* emit each line as a code */
7375         while (*bp) {
7376                 if (*bp == '\n') {
7377                         *bp++ = '\0';
7378
7379                         if(*bp1)
7380                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7381                         bp1 = bp;
7382                 } else {
7383                         if (*bp == ':') {
7384                                 bp++;
7385                                 *bp = '\0';
7386                                 bp++;
7387
7388                                 /* print label, use this special format with NULL directive
7389                                  * to denote that the argument should not be indented with tab */
7390                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
7391                                 bp1 = bp;
7392                         } else
7393                                 bp++;
7394                 }
7395         }
7396
7397         if ((bp1 != bp) && *bp1)
7398                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7399
7400
7401     Safe_free(buffer);
7402
7403     _G.inLine -= (!options.asmpeep);
7404 }
7405
7406 /*-----------------------------------------------------------------*/
7407 /* genRRC - rotate right with carry                                */
7408 /*-----------------------------------------------------------------*/
7409 static void genRRC (iCode *ic)
7410 {
7411   operand *left , *result ;
7412   int size, offset = 0, same;
7413
7414   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7415
7416   /* rotate right with carry */
7417   left = IC_LEFT(ic);
7418   result=IC_RESULT(ic);
7419   pic16_aopOp (left,ic,FALSE);
7420   pic16_aopOp (result,ic,FALSE);
7421
7422   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7423
7424   same = pic16_sameRegs(AOP(result),AOP(left));
7425
7426   size = AOP_SIZE(result);    
7427
7428   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
7429
7430   /* get the lsb and put it into the carry */
7431   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
7432
7433   offset = 0 ;
7434
7435   while(size--) {
7436
7437     if(same) {
7438       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
7439     } else {
7440       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
7441       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7442     }
7443
7444     offset++;
7445   }
7446
7447   pic16_freeAsmop(left,NULL,ic,TRUE);
7448   pic16_freeAsmop(result,NULL,ic,TRUE);
7449 }
7450
7451 /*-----------------------------------------------------------------*/
7452 /* genRLC - generate code for rotate left with carry               */
7453 /*-----------------------------------------------------------------*/
7454 static void genRLC (iCode *ic)
7455 {    
7456   operand *left , *result ;
7457   int size, offset = 0;
7458   int same;
7459
7460   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7461   /* rotate right with carry */
7462   left = IC_LEFT(ic);
7463   result=IC_RESULT(ic);
7464   pic16_aopOp (left,ic,FALSE);
7465   pic16_aopOp (result,ic,FALSE);
7466
7467   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7468
7469   same = pic16_sameRegs(AOP(result),AOP(left));
7470
7471   /* move it to the result */
7472   size = AOP_SIZE(result);    
7473
7474   /* get the msb and put it into the carry */
7475   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7476
7477   offset = 0 ;
7478
7479   while(size--) {
7480
7481     if(same) {
7482       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7483     } else {
7484       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7485       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7486     }
7487
7488     offset++;
7489   }
7490
7491
7492   pic16_freeAsmop(left,NULL,ic,TRUE);
7493   pic16_freeAsmop(result,NULL,ic,TRUE);
7494 }
7495
7496
7497 /* gpasm can get the highest order bit with HIGH/UPPER
7498  * so the following probably is not needed -- VR */
7499  
7500 /*-----------------------------------------------------------------*/
7501 /* genGetHbit - generates code get highest order bit               */
7502 /*-----------------------------------------------------------------*/
7503 static void genGetHbit (iCode *ic)
7504 {
7505     operand *left, *result;
7506     left = IC_LEFT(ic);
7507     result=IC_RESULT(ic);
7508     pic16_aopOp (left,ic,FALSE);
7509     pic16_aopOp (result,ic,FALSE);
7510
7511     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7512     /* get the highest order byte into a */
7513     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7514     if(AOP_TYPE(result) == AOP_CRY){
7515         pic16_emitcode("rlc","a");
7516         pic16_outBitC(result);
7517     }
7518     else{
7519         pic16_emitcode("rl","a");
7520         pic16_emitcode("anl","a,#0x01");
7521         pic16_outAcc(result);
7522     }
7523
7524
7525     pic16_freeAsmop(left,NULL,ic,TRUE);
7526     pic16_freeAsmop(result,NULL,ic,TRUE);
7527 }
7528
7529 #if 0
7530 /*-----------------------------------------------------------------*/
7531 /* AccRol - rotate left accumulator by known count                 */
7532 /*-----------------------------------------------------------------*/
7533 static void AccRol (int shCount)
7534 {
7535     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7536     shCount &= 0x0007;              // shCount : 0..7
7537     switch(shCount){
7538         case 0 :
7539             break;
7540         case 1 :
7541             pic16_emitcode("rl","a");
7542             break;
7543         case 2 :
7544             pic16_emitcode("rl","a");
7545             pic16_emitcode("rl","a");
7546             break;
7547         case 3 :
7548             pic16_emitcode("swap","a");
7549             pic16_emitcode("rr","a");
7550             break;
7551         case 4 :
7552             pic16_emitcode("swap","a");
7553             break;
7554         case 5 :
7555             pic16_emitcode("swap","a");
7556             pic16_emitcode("rl","a");
7557             break;
7558         case 6 :
7559             pic16_emitcode("rr","a");
7560             pic16_emitcode("rr","a");
7561             break;
7562         case 7 :
7563             pic16_emitcode("rr","a");
7564             break;
7565     }
7566 }
7567 #endif
7568
7569 /*-----------------------------------------------------------------*/
7570 /* AccLsh - left shift accumulator by known count                  */
7571 /*-----------------------------------------------------------------*/
7572 static void AccLsh (int shCount)
7573 {
7574         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7575         switch(shCount){
7576                 case 0 :
7577                         return;
7578                         break;
7579                 case 1 :
7580                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7581                         break;
7582                 case 2 :
7583                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7584                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7585                         break;
7586                 case 3 :
7587                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7588                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7589                         break;
7590                 case 4 :
7591                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7592                         break;
7593                 case 5 :
7594                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7595                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7596                         break;
7597                 case 6 :
7598                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7599                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7600                         break;
7601                 case 7 :
7602                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7603                         break;
7604         }
7605
7606         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
7607 }
7608
7609 /*-----------------------------------------------------------------*/
7610 /* AccRsh - right shift accumulator by known count                 */
7611 /*-----------------------------------------------------------------*/
7612 static void AccRsh (int shCount, int andmask)
7613 {
7614         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7615         switch(shCount){
7616                 case 0 :
7617                         return; break;
7618                 case 1 :
7619                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7620                         break;
7621                 case 2 :
7622                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7623                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7624                         break;
7625                 case 3 :
7626                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7627                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7628                         break;
7629                 case 4 :
7630                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7631                         break;
7632                 case 5 :
7633                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7634                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7635                         break;
7636                 case 6 :
7637                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7638                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7639                         break;
7640                 case 7 :
7641                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7642                         break;
7643         }
7644         
7645         if(andmask)
7646                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7647         else
7648                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7649 }
7650
7651 #if 0
7652 /*-----------------------------------------------------------------*/
7653 /* AccSRsh - signed right shift accumulator by known count                 */
7654 /*-----------------------------------------------------------------*/
7655 static void AccSRsh (int shCount)
7656 {
7657     symbol *tlbl ;
7658     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7659     if(shCount != 0){
7660         if(shCount == 1){
7661             pic16_emitcode("mov","c,acc.7");
7662             pic16_emitcode("rrc","a");
7663         } else if(shCount == 2){
7664             pic16_emitcode("mov","c,acc.7");
7665             pic16_emitcode("rrc","a");
7666             pic16_emitcode("mov","c,acc.7");
7667             pic16_emitcode("rrc","a");
7668         } else {
7669             tlbl = newiTempLabel(NULL);
7670             /* rotate right accumulator */
7671             AccRol(8 - shCount);
7672             /* and kill the higher order bits */
7673             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7674             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7675             pic16_emitcode("orl","a,#0x%02x",
7676                      (unsigned char)~SRMask[shCount]);
7677             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7678         }
7679     }
7680 }
7681 #endif
7682 /*-----------------------------------------------------------------*/
7683 /* shiftR1Left2Result - shift right one byte from left to result   */
7684 /*-----------------------------------------------------------------*/
7685 static void shiftR1Left2ResultSigned (operand *left, int offl,
7686                                 operand *result, int offr,
7687                                 int shCount)
7688 {
7689   int same;
7690
7691   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7692
7693   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7694
7695   switch(shCount) {
7696   case 1:
7697     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7698     if(same) 
7699       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7700     else {
7701       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7702       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7703     }
7704
7705     break;
7706   case 2:
7707
7708     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7709     if(same) 
7710       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7711     else {
7712       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7713       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7714     }
7715     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7716     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7717
7718     break;
7719
7720   case 3:
7721     if(same)
7722       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7723     else {
7724       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7725       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7726     }
7727
7728     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7729     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7730     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7731
7732     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7733     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7734
7735     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7736     break;
7737
7738   case 4:
7739     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7740     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
7741     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7742     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
7743     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7744     break;
7745   case 5:
7746     if(same) {
7747       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
7748     } else {
7749       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
7750       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7751     }
7752     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
7753     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
7754     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7755     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
7756     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7757     break;
7758
7759   case 6:
7760     if(same) {
7761       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7762       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7763       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7764       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7765       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7766       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7767     } else {
7768       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7769       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7770       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7771       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7772       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7773     }
7774     break;
7775
7776   case 7:
7777     if(same) {
7778       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7779       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7780       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7781       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7782     } else {
7783       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7784       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7785       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7786     }
7787
7788   default:
7789     break;
7790   }
7791 }
7792
7793 /*-----------------------------------------------------------------*/
7794 /* shiftR1Left2Result - shift right one byte from left to result   */
7795 /*-----------------------------------------------------------------*/
7796 static void shiftR1Left2Result (operand *left, int offl,
7797                                 operand *result, int offr,
7798                                 int shCount, int sign)
7799 {
7800   int same;
7801
7802   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7803
7804   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7805
7806   /* Copy the msb into the carry if signed. */
7807   if(sign) {
7808     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7809     return;
7810   }
7811
7812
7813
7814   switch(shCount) {
7815   case 1:
7816     emitCLRC;
7817     if(same) 
7818       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7819     else {
7820       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7821       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7822     }
7823     break;
7824   case 2:
7825     emitCLRC;
7826     if(same) {
7827       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7828     } else {
7829       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7830       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7831     }
7832     emitCLRC;
7833     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7834
7835     break;
7836   case 3:
7837     if(same)
7838       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7839     else {
7840       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7841       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7842     }
7843
7844     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7845     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7846     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7847     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7848     break;
7849       
7850   case 4:
7851     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7852     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7853     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7854     break;
7855
7856   case 5:
7857     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7858     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7859     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7860     emitCLRC;
7861     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7862
7863     break;
7864   case 6:
7865
7866     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
7867     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7868     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7869     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7870     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7871     break;
7872
7873   case 7:
7874
7875     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7876     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7877     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7878
7879     break;
7880
7881   default:
7882     break;
7883   }
7884 }
7885
7886 /*-----------------------------------------------------------------*/
7887 /* shiftL1Left2Result - shift left one byte from left to result    */
7888 /*-----------------------------------------------------------------*/
7889 static void shiftL1Left2Result (operand *left, int offl,
7890                                 operand *result, int offr, int shCount)
7891 {
7892   int same;
7893
7894   //    char *l;
7895   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7896
7897   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7898   DEBUGpic16_emitcode ("; ***","same =  %d",same);
7899     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7900     //    MOVA(l);
7901     /* shift left accumulator */
7902     //AccLsh(shCount); // don't comment out just yet...
7903   //    pic16_aopPut(AOP(result),"a",offr);
7904
7905   switch(shCount) {
7906   case 1:
7907     /* Shift left 1 bit position */
7908     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7909     if(same) {
7910       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7911     } else {
7912       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7913       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7914     }
7915     break;
7916   case 2:
7917     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7918     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7919     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7920     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7921     break;
7922   case 3:
7923     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7924     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7925     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7926     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7927     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7928     break;
7929   case 4:
7930     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7931     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7932     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7933     break;
7934   case 5:
7935     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7936     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7937     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7938     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7939     break;
7940   case 6:
7941     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7942     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7943     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7944     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7945     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7946     break;
7947   case 7:
7948     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7949     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7950     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7951     break;
7952
7953   default:
7954     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7955   }
7956
7957 }
7958
7959 /*-----------------------------------------------------------------*/
7960 /* movLeft2Result - move byte from left to result                  */
7961 /*-----------------------------------------------------------------*/
7962 static void movLeft2Result (operand *left, int offl,
7963                             operand *result, int offr)
7964 {
7965   char *l;
7966   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7967   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7968     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7969
7970     if (*l == '@' && (IS_AOP_PREG(result))) {
7971       pic16_emitcode("mov","a,%s",l);
7972       pic16_aopPut(AOP(result),"a",offr);
7973     } else {
7974       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7975       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7976     }
7977   }
7978 }
7979
7980 /*-----------------------------------------------------------------*/
7981 /* shiftL2Left2Result - shift left two bytes from left to result   */
7982 /*-----------------------------------------------------------------*/
7983 static void shiftL2Left2Result (operand *left, int offl,
7984                                 operand *result, int offr, int shCount)
7985 {
7986   int same = pic16_sameRegs(AOP(result), AOP(left));
7987   int i;
7988
7989   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7990
7991   if (same && (offl != offr)) { // shift bytes
7992     if (offr > offl) {
7993        for(i=1;i>-1;i--) {
7994          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7995          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7996        }
7997     } else { // just treat as different later on
7998                 same = 0;
7999     }
8000   }
8001
8002   if(same) {
8003     switch(shCount) {
8004     case 0:
8005       break;
8006     case 1:
8007     case 2:
8008     case 3:
8009
8010       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8011       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8012       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8013
8014       while(--shCount) {
8015                 emitCLRC;
8016                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8017                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8018       }
8019
8020       break;
8021     case 4:
8022     case 5:
8023       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8024       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8025       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8026       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8027       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8028       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8029       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8030       if(shCount >=5) {
8031                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8032                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8033       }
8034       break;
8035     case 6:
8036       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8037       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8038       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8039       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8040       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8041       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8042       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8043       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8044       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8045       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8046       break;
8047     case 7:
8048       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8049       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8050       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8051       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8052       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8053     }
8054
8055   } else {
8056     switch(shCount) {
8057     case 0:
8058       break;
8059     case 1:
8060     case 2:
8061     case 3:
8062       /* note, use a mov/add for the shift since the mov has a
8063          chance of getting optimized out */
8064       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8065       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8066       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8067       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8068       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8069
8070       while(--shCount) {
8071                 emitCLRC;
8072                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8073                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8074       }
8075       break;
8076
8077     case 4:
8078     case 5:
8079       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8080       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8081       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8082       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8083       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8084       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8085       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8086       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8087
8088
8089       if(shCount == 5) {
8090                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8091                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8092       }
8093       break;
8094     case 6:
8095       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8096       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8097       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8098       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8099
8100       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8101       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8102       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8103       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8104       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8105       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8106       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8107       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8108       break;
8109     case 7:
8110       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8111       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8112       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8113       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8114       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8115     }
8116   }
8117
8118 }
8119 /*-----------------------------------------------------------------*/
8120 /* shiftR2Left2Result - shift right two bytes from left to result  */
8121 /*-----------------------------------------------------------------*/
8122 static void shiftR2Left2Result (operand *left, int offl,
8123                                 operand *result, int offr,
8124                                 int shCount, int sign)
8125 {
8126   int same = pic16_sameRegs(AOP(result), AOP(left));
8127   int i;
8128   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8129
8130   if (same && (offl != offr)) { // shift right bytes
8131     if (offr < offl) {
8132        for(i=0;i<2;i++) {
8133          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8134          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8135        }
8136     } else { // just treat as different later on
8137                 same = 0;
8138     }
8139   }
8140
8141   switch(shCount) {
8142   case 0:
8143     break;
8144   case 1:
8145   case 2:
8146   case 3:
8147     if(sign)
8148       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8149     else
8150       emitCLRC;
8151
8152     if(same) {
8153       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8154       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8155     } else {
8156       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8157       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8158       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8159       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8160     }
8161
8162     while(--shCount) {
8163       if(sign)
8164                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8165       else
8166                 emitCLRC;
8167       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8168       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8169     }
8170     break;
8171   case 4:
8172   case 5:
8173     if(same) {
8174
8175       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
8176       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
8177       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8178
8179       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8180       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
8181       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8182       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8183     } else {
8184       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8185       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8186       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8187
8188       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8189       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8190       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8191       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8192       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8193     }
8194
8195     if(shCount >=5) {
8196       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8197       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8198     }
8199
8200     if(sign) {
8201       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
8202       pic16_emitpcode(POC_BTFSC, 
8203                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
8204       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8205     }
8206
8207     break;
8208
8209   case 6:
8210     if(same) {
8211
8212       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8213       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8214
8215       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8216       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8217       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8218       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8219       if(sign) {
8220         pic16_emitpcode(POC_BTFSC, 
8221                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0, PO_GPR_REGISTER));
8222         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8223       }
8224       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8225       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
8226       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8227       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8228     } else {
8229       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8230       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8231       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8232       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8233       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8234       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8235       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
8236       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8237       if(sign) {
8238         pic16_emitpcode(POC_BTFSC, 
8239                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8240         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8241       }
8242       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8243       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8244
8245         
8246     }
8247
8248     break;
8249   case 7:
8250     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8251     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8252     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8253     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
8254     if(sign) {
8255       emitSKPNC;
8256       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
8257     } else 
8258       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8259   }
8260 }
8261
8262
8263 /*-----------------------------------------------------------------*/
8264 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
8265 /*-----------------------------------------------------------------*/
8266 static void shiftLLeftOrResult (operand *left, int offl,
8267                                 operand *result, int offr, int shCount)
8268 {
8269     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8270
8271     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8272     /* shift left accumulator */
8273     AccLsh(shCount);
8274     /* or with result */
8275     /* back to result */
8276     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8277 }
8278
8279 /*-----------------------------------------------------------------*/
8280 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
8281 /*-----------------------------------------------------------------*/
8282 static void shiftRLeftOrResult (operand *left, int offl,
8283                                 operand *result, int offr, int shCount)
8284 {
8285     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8286     
8287     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8288     /* shift right accumulator */
8289     AccRsh(shCount, 1);
8290     /* or with result */
8291     /* back to result */
8292     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8293 }
8294
8295 /*-----------------------------------------------------------------*/
8296 /* genlshOne - left shift a one byte quantity by known count       */
8297 /*-----------------------------------------------------------------*/
8298 static void genlshOne (operand *result, operand *left, int shCount)
8299 {       
8300     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8301     shiftL1Left2Result(left, LSB, result, LSB, shCount);
8302 }
8303
8304 /*-----------------------------------------------------------------*/
8305 /* genlshTwo - left shift two bytes by known amount != 0           */
8306 /*-----------------------------------------------------------------*/
8307 static void genlshTwo (operand *result,operand *left, int shCount)
8308 {
8309     int size;
8310     
8311     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8312     size = pic16_getDataSize(result);
8313
8314     /* if shCount >= 8 */
8315     if (shCount >= 8) {
8316         shCount -= 8 ;
8317
8318         if (size > 1){
8319             if (shCount)
8320                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8321             else 
8322                 movLeft2Result(left, LSB, result, MSB16);
8323         }
8324         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8325     }
8326
8327     /*  1 <= shCount <= 7 */
8328     else {  
8329         if(size == 1)
8330             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
8331         else 
8332             shiftL2Left2Result(left, LSB, result, LSB, shCount);
8333     }
8334 }
8335
8336 /*-----------------------------------------------------------------*/
8337 /* shiftLLong - shift left one long from left to result            */
8338 /* offr = LSB or MSB16                                             */
8339 /*-----------------------------------------------------------------*/
8340 static void shiftLLong (operand *left, operand *result, int offr )
8341 {
8342     int size = AOP_SIZE(result);
8343     int same = pic16_sameRegs(AOP(left),AOP(result));
8344         int i;
8345
8346     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
8347
8348         if (same && (offr == MSB16)) { //shift one byte
8349                 for(i=size-1;i>=MSB16;i--) {
8350                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
8351                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
8352                 }
8353         } else {
8354                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
8355         }
8356         
8357     if (size >= LSB+offr ){
8358                 if (same) {
8359                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
8360                 } else {
8361                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
8362                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
8363                 }
8364          }
8365
8366     if(size >= MSB16+offr){
8367                 if (same) {
8368                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
8369                 } else {
8370                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
8371                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
8372                 }
8373     }
8374
8375     if(size >= MSB24+offr){
8376                 if (same) {
8377                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
8378                 } else {
8379                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
8380                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
8381                 }
8382     }
8383
8384     if(size > MSB32+offr){
8385                 if (same) {
8386                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
8387                 } else {
8388                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
8389                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
8390                 }
8391     }
8392     if(offr != LSB)
8393                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8394
8395 }
8396
8397 /*-----------------------------------------------------------------*/
8398 /* genlshFour - shift four byte by a known amount != 0             */
8399 /*-----------------------------------------------------------------*/
8400 static void genlshFour (operand *result, operand *left, int shCount)
8401 {
8402     int size;
8403
8404     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8405     size = AOP_SIZE(result);
8406
8407     /* if shifting more that 3 bytes */
8408     if (shCount >= 24 ) {
8409         shCount -= 24;
8410         if (shCount)
8411             /* lowest order of left goes to the highest
8412             order of the destination */
8413             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
8414         else
8415             movLeft2Result(left, LSB, result, MSB32);
8416
8417                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8418                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8419                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
8420
8421         return;
8422     }
8423
8424     /* more than two bytes */
8425     else if ( shCount >= 16 ) {
8426         /* lower order two bytes goes to higher order two bytes */
8427         shCount -= 16;
8428         /* if some more remaining */
8429         if (shCount)
8430             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
8431         else {
8432             movLeft2Result(left, MSB16, result, MSB32);
8433             movLeft2Result(left, LSB, result, MSB24);
8434         }
8435                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8436                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8437         return;
8438     }    
8439
8440     /* if more than 1 byte */
8441     else if ( shCount >= 8 ) {
8442         /* lower order three bytes goes to higher order  three bytes */
8443         shCount -= 8;
8444         if(size == 2){
8445             if(shCount)
8446                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8447             else
8448                 movLeft2Result(left, LSB, result, MSB16);
8449         }
8450         else{   /* size = 4 */
8451             if(shCount == 0){
8452                 movLeft2Result(left, MSB24, result, MSB32);
8453                 movLeft2Result(left, MSB16, result, MSB24);
8454                 movLeft2Result(left, LSB, result, MSB16);
8455                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8456             }
8457             else if(shCount == 1)
8458                 shiftLLong(left, result, MSB16);
8459             else{
8460                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8461                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8462                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8463                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8464             }
8465         }
8466     }
8467
8468     /* 1 <= shCount <= 7 */
8469     else if(shCount <= 3)
8470     { 
8471         shiftLLong(left, result, LSB);
8472         while(--shCount >= 1)
8473             shiftLLong(result, result, LSB);
8474     }
8475     /* 3 <= shCount <= 7, optimize */
8476     else{
8477         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8478         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8479         shiftL2Left2Result(left, LSB, result, LSB, shCount);
8480     }
8481 }
8482
8483 /*-----------------------------------------------------------------*/
8484 /* genLeftShiftLiteral - left shifting by known count              */
8485 /*-----------------------------------------------------------------*/
8486 static void genLeftShiftLiteral (operand *left,
8487                                  operand *right,
8488                                  operand *result,
8489                                  iCode *ic)
8490 {    
8491     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8492     int size;
8493
8494     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8495     pic16_freeAsmop(right,NULL,ic,TRUE);
8496
8497     pic16_aopOp(left,ic,FALSE);
8498     pic16_aopOp(result,ic,FALSE);
8499
8500     size = getSize(operandType(result));
8501
8502 #if VIEW_SIZE
8503     pic16_emitcode("; shift left ","result %d, left %d",size,
8504              AOP_SIZE(left));
8505 #endif
8506
8507     /* I suppose that the left size >= result size */
8508     if(shCount == 0){
8509         while(size--){
8510             movLeft2Result(left, size, result, size);
8511         }
8512     }
8513
8514     else if(shCount >= (size * 8))
8515         while(size--)
8516             pic16_aopPut(AOP(result),zero,size);
8517     else{
8518         switch (size) {
8519             case 1:
8520                 genlshOne (result,left,shCount);
8521                 break;
8522
8523             case 2:
8524             case 3:
8525                 genlshTwo (result,left,shCount);
8526                 break;
8527
8528             case 4:
8529                 genlshFour (result,left,shCount);
8530                 break;
8531         }
8532     }
8533     pic16_freeAsmop(left,NULL,ic,TRUE);
8534     pic16_freeAsmop(result,NULL,ic,TRUE);
8535 }
8536
8537 /*-----------------------------------------------------------------*
8538  * genMultiAsm - repeat assembly instruction for size of register.
8539  * if endian == 1, then the high byte (i.e base address + size of 
8540  * register) is used first else the low byte is used first;
8541  *-----------------------------------------------------------------*/
8542 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8543 {
8544
8545   int offset = 0;
8546
8547   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8548
8549   if(!reg)
8550     return;
8551
8552   if(!endian) {
8553     endian = 1;
8554   } else {
8555     endian = -1;
8556     offset = size-1;
8557   }
8558
8559   while(size--) {
8560     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
8561     offset += endian;
8562   }
8563
8564 }
8565 /*-----------------------------------------------------------------*/
8566 /* genLeftShift - generates code for left shifting                 */
8567 /*-----------------------------------------------------------------*/
8568 static void genLeftShift (iCode *ic)
8569 {
8570   operand *left,*right, *result;
8571   int size, offset;
8572 //  char *l;
8573   symbol *tlbl , *tlbl1;
8574   pCodeOp *pctemp;
8575
8576   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8577
8578   right = IC_RIGHT(ic);
8579   left  = IC_LEFT(ic);
8580   result = IC_RESULT(ic);
8581
8582   pic16_aopOp(right,ic,FALSE);
8583
8584   /* if the shift count is known then do it 
8585      as efficiently as possible */
8586   if (AOP_TYPE(right) == AOP_LIT) {
8587     genLeftShiftLiteral (left,right,result,ic);
8588     return ;
8589   }
8590
8591   /* shift count is unknown then we have to form
8592    * a loop. Get the loop count in WREG : Note: we take
8593    * only the lower order byte since shifting
8594    * more than 32 bits make no sense anyway, ( the
8595    * largest size of an object can be only 32 bits ) */
8596   
8597   pic16_aopOp(left,ic,FALSE);
8598   pic16_aopOp(result,ic,FALSE);
8599
8600   /* now move the left to the result if they are not the
8601    * same, and if size > 1,
8602    * and if right is not same to result (!!!) -- VR */
8603   if (!pic16_sameRegs(AOP(left),AOP(result))
8604       && (AOP_SIZE(result) > 1)) {
8605
8606     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8607
8608     size = AOP_SIZE(result);
8609     offset=0;
8610     while (size--) {
8611
8612 #if 0
8613       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8614       if (*l == '@' && (IS_AOP_PREG(result))) {
8615
8616           pic16_emitcode("mov","a,%s",l);
8617           pic16_aopPut(AOP(result),"a",offset);
8618       } else
8619 #endif
8620       {
8621         /* we don't know if left is a literal or a register, take care -- VR */
8622         mov2f(AOP(result), AOP(left), offset);
8623       }
8624       offset++;
8625     }
8626   }
8627
8628   size = AOP_SIZE(result);
8629
8630   /* if it is only one byte then */
8631   if (size == 1) {
8632     if(optimized_for_speed) {
8633       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8634       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
8635       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
8636       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8637       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8638       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8639       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8640       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
8641       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
8642       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
8643       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
8644       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8645     } else {
8646
8647       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8648
8649       tlbl = newiTempLabel(NULL);
8650
8651 #if 1
8652       /* this is already done, why change it? */
8653       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8654                 mov2f(AOP(result), AOP(left), 0);
8655       }
8656 #endif
8657
8658       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8659       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8660       pic16_emitpLabel(tlbl->key);
8661       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8662       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8663       emitSKPC;
8664       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8665     }
8666     goto release ;
8667   }
8668     
8669   if (pic16_sameRegs(AOP(left),AOP(result))) {
8670
8671     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8672     
8673     tlbl = newiTempLabel(NULL);
8674     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8675     genMultiAsm(POC_RRCF, result, size,1);
8676     pic16_emitpLabel(tlbl->key);
8677     genMultiAsm(POC_RLCF, result, size,0);
8678     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8679     emitSKPC;
8680     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8681     goto release;
8682   }
8683
8684   //tlbl = newiTempLabel(NULL);
8685   //offset = 0 ;   
8686   //tlbl1 = newiTempLabel(NULL);
8687
8688   //reAdjustPreg(AOP(result));    
8689     
8690   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
8691   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8692   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8693   //MOVA(l);
8694   //pic16_emitcode("add","a,acc");         
8695   //pic16_aopPut(AOP(result),"a",offset++);
8696   //while (--size) {
8697   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8698   //  MOVA(l);
8699   //  pic16_emitcode("rlc","a");         
8700   //  pic16_aopPut(AOP(result),"a",offset++);
8701   //}
8702   //reAdjustPreg(AOP(result));
8703
8704   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8705   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8706
8707
8708   tlbl = newiTempLabel(NULL);
8709   tlbl1= newiTempLabel(NULL);
8710
8711   size = AOP_SIZE(result);
8712   offset = 1;
8713
8714   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8715
8716   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8717
8718   /* offset should be 0, 1 or 3 */
8719   
8720   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8721   emitSKPNZ;
8722   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8723
8724   pic16_emitpcode(POC_MOVWF, pctemp);
8725
8726
8727   pic16_emitpLabel(tlbl->key);
8728
8729   emitCLRC;
8730   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
8731   while(--size)
8732     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
8733
8734   pic16_emitpcode(POC_DECFSZ,  pctemp);
8735   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8736   pic16_emitpLabel(tlbl1->key);
8737
8738   pic16_popReleaseTempReg(pctemp);
8739
8740
8741  release:
8742   pic16_freeAsmop (right,NULL,ic,TRUE);
8743   pic16_freeAsmop(left,NULL,ic,TRUE);
8744   pic16_freeAsmop(result,NULL,ic,TRUE);
8745 }
8746
8747
8748
8749 #if 0
8750 #error old code (left here for reference)
8751 /*-----------------------------------------------------------------*/
8752 /* genLeftShift - generates code for left shifting                 */
8753 /*-----------------------------------------------------------------*/
8754 static void genLeftShift (iCode *ic)
8755 {
8756   operand *left,*right, *result;
8757   int size, offset;
8758   char *l;
8759   symbol *tlbl , *tlbl1;
8760   pCodeOp *pctemp;
8761
8762   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8763
8764   right = IC_RIGHT(ic);
8765   left  = IC_LEFT(ic);
8766   result = IC_RESULT(ic);
8767
8768   pic16_aopOp(right,ic,FALSE);
8769
8770   /* if the shift count is known then do it 
8771      as efficiently as possible */
8772   if (AOP_TYPE(right) == AOP_LIT) {
8773     genLeftShiftLiteral (left,right,result,ic);
8774     return ;
8775   }
8776
8777   /* shift count is unknown then we have to form 
8778      a loop get the loop count in B : Note: we take
8779      only the lower order byte since shifting
8780      more that 32 bits make no sense anyway, ( the
8781      largest size of an object can be only 32 bits ) */  
8782
8783     
8784   pic16_aopOp(left,ic,FALSE);
8785   pic16_aopOp(result,ic,FALSE);
8786
8787   /* now move the left to the result if they are not the
8788      same */
8789   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8790       AOP_SIZE(result) > 1) {
8791
8792     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8793
8794     size = AOP_SIZE(result);
8795     offset=0;
8796     while (size--) {
8797       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8798       if (*l == '@' && (IS_AOP_PREG(result))) {
8799
8800         pic16_emitcode("mov","a,%s",l);
8801         pic16_aopPut(AOP(result),"a",offset);
8802       } else {
8803
8804         /* we don't know if left is a literal or a register, take care -- VR */
8805         mov2f(AOP(result), AOP(left), offset);
8806       }
8807       offset++;
8808     }
8809   }
8810
8811   size = AOP_SIZE(result);
8812
8813   /* if it is only one byte then */
8814   if (size == 1) {
8815     if(optimized_for_speed) {
8816       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8817       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
8818       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
8819       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8820       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8821       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8822       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8823       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
8824       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
8825       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
8826       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
8827       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8828     } else {
8829
8830       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8831
8832       tlbl = newiTempLabel(NULL);
8833       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8834                 mov2f(AOP(result), AOP(left), 0);
8835                 
8836 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8837 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8838       }
8839
8840       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8841       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8842       pic16_emitpLabel(tlbl->key);
8843       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8844       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8845       emitSKPC;
8846       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8847     }
8848     goto release ;
8849   }
8850     
8851   if (pic16_sameRegs(AOP(left),AOP(result))) {
8852
8853     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8854     
8855     tlbl = newiTempLabel(NULL);
8856     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8857     genMultiAsm(POC_RRCF, result, size,1);
8858     pic16_emitpLabel(tlbl->key);
8859     genMultiAsm(POC_RLCF, result, size,0);
8860     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8861     emitSKPC;
8862     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8863     goto release;
8864   }
8865
8866   //tlbl = newiTempLabel(NULL);
8867   //offset = 0 ;   
8868   //tlbl1 = newiTempLabel(NULL);
8869
8870   //reAdjustPreg(AOP(result));    
8871     
8872   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
8873   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8874   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8875   //MOVA(l);
8876   //pic16_emitcode("add","a,acc");         
8877   //pic16_aopPut(AOP(result),"a",offset++);
8878   //while (--size) {
8879   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8880   //  MOVA(l);
8881   //  pic16_emitcode("rlc","a");         
8882   //  pic16_aopPut(AOP(result),"a",offset++);
8883   //}
8884   //reAdjustPreg(AOP(result));
8885
8886   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8887   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8888
8889
8890   tlbl = newiTempLabel(NULL);
8891   tlbl1= newiTempLabel(NULL);
8892
8893   size = AOP_SIZE(result);
8894   offset = 1;
8895
8896   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8897
8898   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8899
8900   /* offset should be 0, 1 or 3 */
8901   
8902   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8903   emitSKPNZ;
8904   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8905
8906   pic16_emitpcode(POC_MOVWF, pctemp);
8907
8908
8909   pic16_emitpLabel(tlbl->key);
8910
8911   emitCLRC;
8912   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
8913   while(--size)
8914     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
8915
8916   pic16_emitpcode(POC_DECFSZ,  pctemp);
8917   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8918   pic16_emitpLabel(tlbl1->key);
8919
8920   pic16_popReleaseTempReg(pctemp);
8921
8922
8923  release:
8924   pic16_freeAsmop (right,NULL,ic,TRUE);
8925   pic16_freeAsmop(left,NULL,ic,TRUE);
8926   pic16_freeAsmop(result,NULL,ic,TRUE);
8927 }
8928 #endif
8929
8930 /*-----------------------------------------------------------------*/
8931 /* genrshOne - right shift a one byte quantity by known count      */
8932 /*-----------------------------------------------------------------*/
8933 static void genrshOne (operand *result, operand *left,
8934                        int shCount, int sign)
8935 {
8936     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8937     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8938 }
8939
8940 /*-----------------------------------------------------------------*/
8941 /* genrshTwo - right shift two bytes by known amount != 0          */
8942 /*-----------------------------------------------------------------*/
8943 static void genrshTwo (operand *result,operand *left,
8944                        int shCount, int sign)
8945 {
8946   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8947   /* if shCount >= 8 */
8948   if (shCount >= 8) {
8949     shCount -= 8 ;
8950     if (shCount)
8951       shiftR1Left2Result(left, MSB16, result, LSB,
8952                          shCount, sign);
8953     else
8954       movLeft2Result(left, MSB16, result, LSB);
8955
8956     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8957
8958     if(sign) {
8959       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8960       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8961     }
8962   }
8963
8964   /*  1 <= shCount <= 7 */
8965   else
8966     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
8967 }
8968
8969 /*-----------------------------------------------------------------*/
8970 /* shiftRLong - shift right one long from left to result           */
8971 /* offl = LSB or MSB16                                             */
8972 /*-----------------------------------------------------------------*/
8973 static void shiftRLong (operand *left, int offl,
8974                         operand *result, int sign)
8975 {
8976     int size = AOP_SIZE(result);
8977     int same = pic16_sameRegs(AOP(left),AOP(result));
8978     int i;
8979     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8980
8981         if (same && (offl == MSB16)) { //shift one byte right
8982                 for(i=MSB16;i<size;i++) {
8983                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8984                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8985                 }
8986         }
8987
8988     if(sign)
8989                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8990         else
8991                 emitCLRC;
8992
8993         if (same) {
8994                 if (offl == LSB)
8995                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8996         } else {
8997         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8998         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8999         }
9000
9001     if(offl == MSB16) {
9002         /* add sign of "a" */
9003         pic16_addSign(result, MSB32, sign);
9004         }
9005
9006         if (same) {
9007         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9008         } else {
9009         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9010         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9011         }
9012         
9013         if (same) {
9014         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9015         } else {
9016         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9017         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9018         }
9019
9020         if (same) {
9021         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9022         } else {
9023         if(offl == LSB){
9024                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9025                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9026         }
9027         }
9028 }
9029
9030 /*-----------------------------------------------------------------*/
9031 /* genrshFour - shift four byte by a known amount != 0             */
9032 /*-----------------------------------------------------------------*/
9033 static void genrshFour (operand *result, operand *left,
9034                         int shCount, int sign)
9035 {
9036   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9037   /* if shifting more that 3 bytes */
9038   if(shCount >= 24 ) {
9039     shCount -= 24;
9040     if(shCount)
9041       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9042     else
9043       movLeft2Result(left, MSB32, result, LSB);
9044
9045     pic16_addSign(result, MSB16, sign);
9046   }
9047   else if(shCount >= 16){
9048     shCount -= 16;
9049     if(shCount)
9050       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9051     else{
9052       movLeft2Result(left, MSB24, result, LSB);
9053       movLeft2Result(left, MSB32, result, MSB16);
9054     }
9055     pic16_addSign(result, MSB24, sign);
9056   }
9057   else if(shCount >= 8){
9058     shCount -= 8;
9059     if(shCount == 1)
9060       shiftRLong(left, MSB16, result, sign);
9061     else if(shCount == 0){
9062       movLeft2Result(left, MSB16, result, LSB);
9063       movLeft2Result(left, MSB24, result, MSB16);
9064       movLeft2Result(left, MSB32, result, MSB24);
9065       pic16_addSign(result, MSB32, sign);
9066     }
9067     else{ //shcount >= 2
9068       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9069       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9070       /* the last shift is signed */
9071       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9072       pic16_addSign(result, MSB32, sign);
9073     }
9074   }
9075   else{   /* 1 <= shCount <= 7 */
9076     if(shCount <= 2){
9077       shiftRLong(left, LSB, result, sign);
9078       if(shCount == 2)
9079         shiftRLong(result, LSB, result, sign);
9080     }
9081     else{
9082       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
9083       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
9084       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
9085     }
9086   }
9087 }
9088
9089 /*-----------------------------------------------------------------*/
9090 /* genRightShiftLiteral - right shifting by known count            */
9091 /*-----------------------------------------------------------------*/
9092 static void genRightShiftLiteral (operand *left,
9093                                   operand *right,
9094                                   operand *result,
9095                                   iCode *ic,
9096                                   int sign)
9097 {    
9098   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
9099   int lsize,res_size;
9100
9101   pic16_freeAsmop(right,NULL,ic,TRUE);
9102
9103   pic16_aopOp(left,ic,FALSE);
9104   pic16_aopOp(result,ic,FALSE);
9105
9106   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
9107
9108 #if VIEW_SIZE
9109   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
9110                  AOP_SIZE(left));
9111 #endif
9112
9113   lsize = pic16_getDataSize(left);
9114   res_size = pic16_getDataSize(result);
9115   /* test the LEFT size !!! */
9116
9117   /* I suppose that the left size >= result size */
9118   if(shCount == 0){
9119     while(res_size--)
9120       movLeft2Result(left, lsize, result, res_size);
9121   }
9122
9123   else if(shCount >= (lsize * 8)){
9124
9125     if(res_size == 1) {
9126       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
9127       if(sign) {
9128         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9129         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
9130       }
9131     } else {
9132
9133       if(sign) {
9134         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
9135         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9136         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9137         while(res_size--)
9138           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
9139
9140       } else {
9141
9142         while(res_size--)
9143           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
9144       }
9145     }
9146   } else {
9147
9148     switch (res_size) {
9149     case 1:
9150       genrshOne (result,left,shCount,sign);
9151       break;
9152
9153     case 2:
9154       genrshTwo (result,left,shCount,sign);
9155       break;
9156
9157     case 4:
9158       genrshFour (result,left,shCount,sign);
9159       break;
9160     default :
9161       break;
9162     }
9163
9164   }
9165
9166   pic16_freeAsmop(left,NULL,ic,TRUE);
9167   pic16_freeAsmop(result,NULL,ic,TRUE);
9168 }
9169
9170 /*-----------------------------------------------------------------*/
9171 /* genSignedRightShift - right shift of signed number              */
9172 /*-----------------------------------------------------------------*/
9173 static void genSignedRightShift (iCode *ic)
9174 {
9175   operand *right, *left, *result;
9176   int size, offset;
9177   //  char *l;
9178   symbol *tlbl, *tlbl1 ;
9179   pCodeOp *pctemp;
9180
9181   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
9182
9183   /* we do it the hard way put the shift count in b
9184      and loop thru preserving the sign */
9185   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9186
9187   right = IC_RIGHT(ic);
9188   left  = IC_LEFT(ic);
9189   result = IC_RESULT(ic);
9190
9191   pic16_aopOp(right,ic,FALSE);  
9192   pic16_aopOp(left,ic,FALSE);
9193   pic16_aopOp(result,ic,FALSE);
9194
9195
9196   if ( AOP_TYPE(right) == AOP_LIT) {
9197     genRightShiftLiteral (left,right,result,ic,1);
9198     return ;
9199   }
9200   /* shift count is unknown then we have to form 
9201      a loop get the loop count in B : Note: we take
9202      only the lower order byte since shifting
9203      more that 32 bits make no sense anyway, ( the
9204      largest size of an object can be only 32 bits ) */  
9205
9206   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
9207   //pic16_emitcode("inc","b");
9208   //pic16_freeAsmop (right,NULL,ic,TRUE);
9209   //pic16_aopOp(left,ic,FALSE);
9210   //pic16_aopOp(result,ic,FALSE);
9211
9212   /* now move the left to the result if they are not the
9213      same */
9214   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9215       AOP_SIZE(result) > 1) {
9216
9217     size = AOP_SIZE(result);
9218     offset=0;
9219     while (size--) { 
9220       /*
9221         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9222         if (*l == '@' && IS_AOP_PREG(result)) {
9223
9224         pic16_emitcode("mov","a,%s",l);
9225         pic16_aopPut(AOP(result),"a",offset);
9226         } else
9227         pic16_aopPut(AOP(result),l,offset);
9228       */
9229       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
9230       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
9231
9232       offset++;
9233     }
9234   }
9235
9236   /* mov the highest order bit to OVR */    
9237   tlbl = newiTempLabel(NULL);
9238   tlbl1= newiTempLabel(NULL);
9239
9240   size = AOP_SIZE(result);
9241   offset = size - 1;
9242
9243   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
9244
9245   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9246
9247   /* offset should be 0, 1 or 3 */
9248   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
9249   emitSKPNZ;
9250   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9251
9252   pic16_emitpcode(POC_MOVWF, pctemp);
9253
9254
9255   pic16_emitpLabel(tlbl->key);
9256
9257   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
9258   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
9259
9260   while(--size) {
9261     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
9262   }
9263
9264   pic16_emitpcode(POC_DECFSZ,  pctemp);
9265   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9266   pic16_emitpLabel(tlbl1->key);
9267
9268   pic16_popReleaseTempReg(pctemp);
9269 #if 0
9270   size = AOP_SIZE(result);
9271   offset = size - 1;
9272   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
9273   pic16_emitcode("rlc","a");
9274   pic16_emitcode("mov","ov,c");
9275   /* if it is only one byte then */
9276   if (size == 1) {
9277     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9278     MOVA(l);
9279     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9280     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9281     pic16_emitcode("mov","c,ov");
9282     pic16_emitcode("rrc","a");
9283     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9284     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9285     pic16_aopPut(AOP(result),"a",0);
9286     goto release ;
9287   }
9288
9289   reAdjustPreg(AOP(result));
9290   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9291   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9292   pic16_emitcode("mov","c,ov");
9293   while (size--) {
9294     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9295     MOVA(l);
9296     pic16_emitcode("rrc","a");         
9297     pic16_aopPut(AOP(result),"a",offset--);
9298   }
9299   reAdjustPreg(AOP(result));
9300   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9301   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9302
9303  release:
9304 #endif
9305
9306   pic16_freeAsmop(left,NULL,ic,TRUE);
9307   pic16_freeAsmop(result,NULL,ic,TRUE);
9308   pic16_freeAsmop(right,NULL,ic,TRUE);
9309 }
9310
9311 /*-----------------------------------------------------------------*/
9312 /* genRightShift - generate code for right shifting                */
9313 /*-----------------------------------------------------------------*/
9314 static void genRightShift (iCode *ic)
9315 {
9316     operand *right, *left, *result;
9317     sym_link *letype ;
9318     int size, offset;
9319     char *l;
9320     symbol *tlbl, *tlbl1 ;
9321
9322     /* if signed then we do it the hard way preserve the
9323     sign bit moving it inwards */
9324     letype = getSpec(operandType(IC_LEFT(ic)));
9325     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9326
9327     if (!SPEC_USIGN(letype)) {
9328         genSignedRightShift (ic);
9329         return ;
9330     }
9331
9332     /* signed & unsigned types are treated the same : i.e. the
9333     signed is NOT propagated inwards : quoting from the
9334     ANSI - standard : "for E1 >> E2, is equivalent to division
9335     by 2**E2 if unsigned or if it has a non-negative value,
9336     otherwise the result is implementation defined ", MY definition
9337     is that the sign does not get propagated */
9338
9339     right = IC_RIGHT(ic);
9340     left  = IC_LEFT(ic);
9341     result = IC_RESULT(ic);
9342
9343     pic16_aopOp(right,ic,FALSE);
9344
9345     /* if the shift count is known then do it 
9346     as efficiently as possible */
9347     if (AOP_TYPE(right) == AOP_LIT) {
9348         genRightShiftLiteral (left,right,result,ic, 0);
9349         return ;
9350     }
9351
9352     /* shift count is unknown then we have to form 
9353     a loop get the loop count in B : Note: we take
9354     only the lower order byte since shifting
9355     more that 32 bits make no sense anyway, ( the
9356     largest size of an object can be only 32 bits ) */  
9357
9358     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
9359     pic16_emitcode("inc","b");
9360     pic16_aopOp(left,ic,FALSE);
9361     pic16_aopOp(result,ic,FALSE);
9362
9363     /* now move the left to the result if they are not the
9364     same */
9365     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9366         AOP_SIZE(result) > 1) {
9367
9368         size = AOP_SIZE(result);
9369         offset=0;
9370         while (size--) {
9371             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9372             if (*l == '@' && IS_AOP_PREG(result)) {
9373
9374                 pic16_emitcode("mov","a,%s",l);
9375                 pic16_aopPut(AOP(result),"a",offset);
9376             } else
9377                 pic16_aopPut(AOP(result),l,offset);
9378             offset++;
9379         }
9380     }
9381
9382     tlbl = newiTempLabel(NULL);
9383     tlbl1= newiTempLabel(NULL);
9384     size = AOP_SIZE(result);
9385     offset = size - 1;
9386
9387     /* if it is only one byte then */
9388     if (size == 1) {
9389
9390       tlbl = newiTempLabel(NULL);
9391       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9392         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9393         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9394       }
9395
9396       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9397       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9398       pic16_emitpLabel(tlbl->key);
9399       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9400       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9401       emitSKPC;
9402       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9403
9404       goto release ;
9405     }
9406
9407     reAdjustPreg(AOP(result));
9408     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9409     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9410     CLRC;
9411     while (size--) {
9412         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9413         MOVA(l);
9414         pic16_emitcode("rrc","a");         
9415         pic16_aopPut(AOP(result),"a",offset--);
9416     }
9417     reAdjustPreg(AOP(result));
9418
9419     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9420     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9421
9422 release:
9423     pic16_freeAsmop(left,NULL,ic,TRUE);
9424     pic16_freeAsmop (right,NULL,ic,TRUE);
9425     pic16_freeAsmop(result,NULL,ic,TRUE);
9426 }
9427
9428
9429 void pic16_loadFSR0(operand *op)
9430 {
9431         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
9432 }
9433
9434 /*-----------------------------------------------------------------*/
9435 /* genUnpackBits - generates code for unpacking bits               */
9436 /*-----------------------------------------------------------------*/
9437 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
9438 {    
9439     int shCnt ;
9440     int rlen = 0 ;
9441     sym_link *etype;
9442     int offset = 0 ;
9443
9444         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9445         etype = getSpec(operandType(result));
9446
9447         /* the following call to pic16_loadFSR0 is temporary until
9448          * optimization to handle single bit assignments is added
9449          * to the function. Until then use the old safe way! -- VR */
9450         pic16_loadFSR0( left );
9451  
9452         /* read the first byte  */
9453         switch (ptype) {
9454                 case POINTER:
9455                 case IPOINTER:
9456                 case PPOINTER:
9457                 case FPOINTER:
9458                 case GPOINTER:
9459                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9460                         break;
9461                 case CPOINTER:
9462                         pic16_emitcode("clr","a");
9463                         pic16_emitcode("movc","a","@a+dptr");
9464                         break;
9465         }
9466         
9467
9468         /* if we have bitdisplacement then it fits   */
9469         /* into this byte completely or if length is */
9470         /* less than a byte                          */
9471         if ((shCnt = SPEC_BSTR(etype)) || 
9472                 (SPEC_BLEN(etype) <= 8))  {
9473
9474                 /* shift right acc */
9475                 AccRsh(shCnt, 0);
9476
9477                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9478                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
9479
9480 /* VR -- normally I would use the following, but since we use the hack,
9481  * to avoid the masking from AccRsh, why not mask it right now? */
9482
9483 /*
9484                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
9485 */
9486
9487                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9488           return ;
9489         }
9490
9491
9492
9493         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9494         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9495         exit(-1);
9496
9497     /* bit field did not fit in a byte  */
9498     rlen = SPEC_BLEN(etype) - 8;
9499     pic16_aopPut(AOP(result),"a",offset++);
9500
9501     while (1)  {
9502
9503         switch (ptype) {
9504         case POINTER:
9505         case IPOINTER:
9506             pic16_emitcode("inc","%s",rname);
9507             pic16_emitcode("mov","a,@%s",rname);
9508             break;
9509             
9510         case PPOINTER:
9511             pic16_emitcode("inc","%s",rname);
9512             pic16_emitcode("movx","a,@%s",rname);
9513             break;
9514
9515         case FPOINTER:
9516             pic16_emitcode("inc","dptr");
9517             pic16_emitcode("movx","a,@dptr");
9518             break;
9519             
9520         case CPOINTER:
9521             pic16_emitcode("clr","a");
9522             pic16_emitcode("inc","dptr");
9523             pic16_emitcode("movc","a","@a+dptr");
9524             break;
9525             
9526         case GPOINTER:
9527             pic16_emitcode("inc","dptr");
9528             pic16_emitcode("lcall","__gptrget");
9529             break;
9530         }
9531
9532         rlen -= 8;            
9533         /* if we are done */
9534         if ( rlen <= 0 )
9535             break ;
9536         
9537         pic16_aopPut(AOP(result),"a",offset++);
9538                               
9539     }
9540     
9541     if (rlen) {
9542         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
9543         pic16_aopPut(AOP(result),"a",offset);          
9544     }
9545     
9546     return ;
9547 }
9548
9549
9550 static void genDataPointerGet(operand *left,
9551                               operand *result,
9552                               iCode *ic)
9553 {
9554   int size, offset = 0, leoffset=0 ;
9555
9556         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9557         pic16_aopOp(result, ic, FALSE);
9558
9559         size = AOP_SIZE(result);
9560 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9561
9562
9563 #if 0
9564         /* The following tests may save a redudant movff instruction when
9565          * accessing unions */
9566          
9567         /* if they are the same */
9568         if (operandsEqu (left, result)) {
9569                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
9570                 goto release;
9571         }
9572 #endif
9573
9574 #if 0
9575         /* if they are the same registers */
9576         if (pic16_sameRegs(AOP(left),AOP(result))) {
9577                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
9578                 goto release;
9579         }
9580 #endif
9581
9582 #if 1
9583         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
9584                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
9585                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
9586                 goto release;
9587         }
9588 #endif
9589
9590
9591 #if 0
9592         if ( AOP_TYPE(left) == AOP_PCODE) {
9593                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
9594                                 AOP(left)->aopu.pcop->name,
9595                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
9596                                 PCOR(AOP(left)->aopu.pcop)->instance:
9597                                 PCOI(AOP(left)->aopu.pcop)->offset);
9598         }
9599 #endif
9600
9601         if(AOP(left)->aopu.pcop->type == PO_DIR)
9602                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
9603
9604         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9605
9606         while (size--) {
9607                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
9608                 
9609                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
9610                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
9611                         mov2w(AOP(left), offset); // patch 8
9612                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9613                 } else {
9614                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
9615                                 pic16_popGet(AOP(left), offset), //patch 8
9616                                 pic16_popGet(AOP(result), offset)));
9617                 }
9618
9619                 offset++;
9620                 leoffset++;
9621         }
9622
9623 release:
9624     pic16_freeAsmop(result,NULL,ic,TRUE);
9625 }
9626
9627
9628
9629 /*-----------------------------------------------------------------*/
9630 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
9631 /*-----------------------------------------------------------------*/
9632 static void genNearPointerGet (operand *left, 
9633                                operand *result, 
9634                                iCode *ic)
9635 {
9636     asmop *aop = NULL;
9637     //regs *preg = NULL ;
9638     sym_link *rtype, *retype;
9639     sym_link *ltype = operandType(left);    
9640
9641         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9642         rtype = operandType(result);
9643         retype= getSpec(rtype);
9644     
9645         pic16_aopOp(left,ic,FALSE);
9646
9647 //      pic16_DumpOp("(left)",left);
9648 //      pic16_DumpOp("(result)",result);
9649
9650         /* if left is rematerialisable and
9651          * result is not bit variable type and
9652          * the left is pointer to data space i.e
9653          * lower 128 bytes of space */
9654         if (AOP_TYPE(left) == AOP_PCODE
9655                 && !IS_BITFIELD(retype)
9656                 && DCL_TYPE(ltype) == POINTER) {
9657
9658                 genDataPointerGet (left,result,ic);
9659                 pic16_freeAsmop(left, NULL, ic, TRUE);
9660           return ;
9661         }
9662     
9663         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9664
9665         /* if the value is already in a pointer register
9666          * then don't need anything more */
9667         if (!AOP_INPREG(AOP(left))) {
9668                 /* otherwise get a free pointer register */
9669                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9670                 
9671                 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
9672                 if( (AOP_TYPE(left) == AOP_PCODE) 
9673                         && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9674                                 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
9675                 {
9676                         if(!IS_BITFIELD(retype))
9677                                 pic16_loadFSR0( left );  // patch 10
9678                 } else {
9679                         // set up FSR0 with address from left
9680                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9681                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9682                 }
9683         }
9684 //       else
9685 //      rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9686     
9687         pic16_aopOp (result,ic,FALSE);
9688     
9689       /* if bitfield then unpack the bits */
9690     if (IS_BITFIELD(retype)) 
9691         genUnpackBits (result, left, NULL, POINTER);
9692     else {
9693         /* we have can just get the values */
9694       int size = AOP_SIZE(result);
9695       int offset = 0;   
9696         
9697       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9698
9699
9700         /* fsr0 is loaded already -- VR */
9701 //      pic16_loadFSR0( left );
9702
9703 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
9704 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9705       while(size--) {
9706
9707         if(size) {
9708                 pic16_emitpcode(POC_MOVFF,
9709                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
9710                                 pic16_popGet(AOP(result), offset++)));
9711         } else {
9712                 pic16_emitpcode(POC_MOVFF,
9713                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
9714                                 pic16_popGet(AOP(result), offset++)));
9715         }
9716       }
9717 #if 0
9718 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
9719 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
9720         if(size)
9721           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9722 #endif
9723 /*
9724         while (size--) {
9725             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
9726
9727                 pic16_emitcode("mov","a,@%s",rname);
9728                 pic16_aopPut(AOP(result),"a",offset);
9729             } else {
9730                 sprintf(buffer,"@%s",rname);
9731                 pic16_aopPut(AOP(result),buffer,offset);
9732             }
9733             offset++ ;
9734             if (size)
9735                 pic16_emitcode("inc","%s",rname);
9736         }
9737 */
9738     }
9739
9740     /* now some housekeeping stuff */
9741     if (aop) {
9742         /* we had to allocate for this iCode */
9743     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9744         pic16_freeAsmop(NULL,aop,ic,TRUE);
9745     } else { 
9746         /* we did not allocate which means left
9747            already in a pointer register, then
9748            if size > 0 && this could be used again
9749            we have to point it back to where it 
9750            belongs */
9751     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9752         if (AOP_SIZE(result) > 1 &&
9753             !OP_SYMBOL(left)->remat &&
9754             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9755               ic->depth )) {
9756 //          int size = AOP_SIZE(result) - 1;
9757 //          while (size--)
9758 //              pic16_emitcode("dec","%s",rname);
9759         }
9760     }
9761
9762     /* done */
9763     pic16_freeAsmop(left,NULL,ic,TRUE);
9764     pic16_freeAsmop(result,NULL,ic,TRUE);
9765      
9766 }
9767
9768 /*-----------------------------------------------------------------*/
9769 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
9770 /*-----------------------------------------------------------------*/
9771 static void genPagedPointerGet (operand *left, 
9772                                operand *result, 
9773                                iCode *ic)
9774 {
9775     asmop *aop = NULL;
9776     regs *preg = NULL ;
9777     char *rname ;
9778     sym_link *rtype, *retype;    
9779
9780     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9781
9782     rtype = operandType(result);
9783     retype= getSpec(rtype);
9784     
9785     pic16_aopOp(left,ic,FALSE);
9786
9787   /* if the value is already in a pointer register
9788        then don't need anything more */
9789     if (!AOP_INPREG(AOP(left))) {
9790         /* otherwise get a free pointer register */
9791         aop = newAsmop(0);
9792         preg = getFreePtr(ic,&aop,FALSE);
9793         pic16_emitcode("mov","%s,%s",
9794                 preg->name,
9795                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
9796         rname = preg->name ;
9797     } else
9798         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9799     
9800     pic16_freeAsmop(left,NULL,ic,TRUE);
9801     pic16_aopOp (result,ic,FALSE);
9802
9803     /* if bitfield then unpack the bits */
9804     if (IS_BITFIELD(retype)) 
9805         genUnpackBits (result,left,rname,PPOINTER);
9806     else {
9807         /* we have can just get the values */
9808         int size = AOP_SIZE(result);
9809         int offset = 0 ;        
9810         
9811         while (size--) {
9812             
9813             pic16_emitcode("movx","a,@%s",rname);
9814             pic16_aopPut(AOP(result),"a",offset);
9815             
9816             offset++ ;
9817             
9818             if (size)
9819                 pic16_emitcode("inc","%s",rname);
9820         }
9821     }
9822
9823     /* now some housekeeping stuff */
9824     if (aop) {
9825         /* we had to allocate for this iCode */
9826         pic16_freeAsmop(NULL,aop,ic,TRUE);
9827     } else { 
9828         /* we did not allocate which means left
9829            already in a pointer register, then
9830            if size > 0 && this could be used again
9831            we have to point it back to where it 
9832            belongs */
9833         if (AOP_SIZE(result) > 1 &&
9834             !OP_SYMBOL(left)->remat &&
9835             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9836               ic->depth )) {
9837             int size = AOP_SIZE(result) - 1;
9838             while (size--)
9839                 pic16_emitcode("dec","%s",rname);
9840         }
9841     }
9842
9843     /* done */
9844     pic16_freeAsmop(result,NULL,ic,TRUE);
9845     
9846         
9847 }
9848
9849 /*-----------------------------------------------------------------*/
9850 /* genFarPointerGet - gget value from far space                    */
9851 /*-----------------------------------------------------------------*/
9852 static void genFarPointerGet (operand *left,
9853                               operand *result, iCode *ic)
9854 {
9855     int size, offset ;
9856     sym_link *retype = getSpec(operandType(result));
9857
9858     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9859
9860     pic16_aopOp(left,ic,FALSE);
9861
9862     /* if the operand is already in dptr 
9863     then we do nothing else we move the value to dptr */
9864     if (AOP_TYPE(left) != AOP_STR) {
9865         /* if this is remateriazable */
9866         if (AOP_TYPE(left) == AOP_IMMD)
9867             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9868         else { /* we need to get it byte by byte */
9869             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9870             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9871             if (options.model == MODEL_FLAT24)
9872             {
9873                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9874             }
9875         }
9876     }
9877     /* so dptr know contains the address */
9878     pic16_freeAsmop(left,NULL,ic,TRUE);
9879     pic16_aopOp(result,ic,FALSE);
9880
9881     /* if bit then unpack */
9882     if (IS_BITFIELD(retype)) 
9883         genUnpackBits(result,left,"dptr",FPOINTER);
9884     else {
9885         size = AOP_SIZE(result);
9886         offset = 0 ;
9887
9888         while (size--) {
9889             pic16_emitcode("movx","a,@dptr");
9890             pic16_aopPut(AOP(result),"a",offset++);
9891             if (size)
9892                 pic16_emitcode("inc","dptr");
9893         }
9894     }
9895
9896     pic16_freeAsmop(result,NULL,ic,TRUE);
9897 }
9898 #if 0
9899 /*-----------------------------------------------------------------*/
9900 /* genCodePointerGet - get value from code space                  */
9901 /*-----------------------------------------------------------------*/
9902 static void genCodePointerGet (operand *left,
9903                                 operand *result, iCode *ic)
9904 {
9905     int size, offset ;
9906     sym_link *retype = getSpec(operandType(result));
9907
9908     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9909
9910     pic16_aopOp(left,ic,FALSE);
9911
9912     /* if the operand is already in dptr 
9913     then we do nothing else we move the value to dptr */
9914     if (AOP_TYPE(left) != AOP_STR) {
9915         /* if this is remateriazable */
9916         if (AOP_TYPE(left) == AOP_IMMD)
9917             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9918         else { /* we need to get it byte by byte */
9919             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9920             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9921             if (options.model == MODEL_FLAT24)
9922             {
9923                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9924             }
9925         }
9926     }
9927     /* so dptr know contains the address */
9928     pic16_freeAsmop(left,NULL,ic,TRUE);
9929     pic16_aopOp(result,ic,FALSE);
9930
9931     /* if bit then unpack */
9932     if (IS_BITFIELD(retype)) 
9933         genUnpackBits(result,left,"dptr",CPOINTER);
9934     else {
9935         size = AOP_SIZE(result);
9936         offset = 0 ;
9937
9938         while (size--) {
9939             pic16_emitcode("clr","a");
9940             pic16_emitcode("movc","a,@a+dptr");
9941             pic16_aopPut(AOP(result),"a",offset++);
9942             if (size)
9943                 pic16_emitcode("inc","dptr");
9944         }
9945     }
9946
9947     pic16_freeAsmop(result,NULL,ic,TRUE);
9948 }
9949 #endif
9950 /*-----------------------------------------------------------------*/
9951 /* genGenPointerGet - gget value from generic pointer space        */
9952 /*-----------------------------------------------------------------*/
9953 static void genGenPointerGet (operand *left,
9954                               operand *result, iCode *ic)
9955 {
9956   int size, offset, lit;
9957   sym_link *retype = getSpec(operandType(result));
9958
9959         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9960         pic16_aopOp(left,ic,FALSE);
9961         pic16_aopOp(result,ic,FALSE);
9962         size = AOP_SIZE(result);
9963
9964         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9965
9966         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9967
9968                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9969                 // load FSR0 from immediate
9970                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9971
9972 //              pic16_loadFSR0( left );
9973
9974                 offset = 0;
9975                 while(size--) {
9976                         if(size) {
9977                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9978                         } else {
9979                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9980                         }
9981                         offset++;
9982                 }
9983                 goto release;
9984
9985         }
9986         else { /* we need to get it byte by byte */
9987                 // set up FSR0 with address from left
9988                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9989                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9990
9991                 offset = 0 ;
9992
9993                 while(size--) {
9994                         if(size) {
9995                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9996                         } else {
9997                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9998                         }
9999                         offset++;
10000                 }
10001                 goto release;
10002         }
10003
10004   /* if bit then unpack */
10005         if (IS_BITFIELD(retype)) 
10006                 genUnpackBits(result,left,"BAD",GPOINTER);
10007
10008         release:
10009         pic16_freeAsmop(left,NULL,ic,TRUE);
10010         pic16_freeAsmop(result,NULL,ic,TRUE);
10011
10012 }
10013
10014 /*-----------------------------------------------------------------*/
10015 /* genConstPointerGet - get value from const generic pointer space */
10016 /*-----------------------------------------------------------------*/
10017 static void genConstPointerGet (operand *left,
10018                                 operand *result, iCode *ic)
10019 {
10020   //sym_link *retype = getSpec(operandType(result));
10021   // symbol *albl = newiTempLabel(NULL);        // patch 15
10022   // symbol *blbl = newiTempLabel(NULL);        //
10023   // PIC_OPCODE poc;                            // patch 15
10024   int size;
10025   int offset = 0;
10026
10027   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10028   pic16_aopOp(left,ic,FALSE);
10029   pic16_aopOp(result,ic,TRUE);
10030   size = AOP_SIZE(result);
10031
10032   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10033
10034   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
10035 #if 0                                                                   // patch 15
10036   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
10037   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
10038   pic16_emitpLabel(albl->key);
10039
10040   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
10041     
10042   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
10043   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
10044   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
10045   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
10046   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
10047
10048   pic16_emitpLabel(blbl->key);
10049
10050   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
10051 #endif                                                                  // patch 15
10052
10053
10054   // set up table pointer
10055   if( (AOP_TYPE(left) == AOP_PCODE) 
10056       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
10057           || (AOP(left)->aopu.pcop->type == PO_DIR)))                   // patch 15 ......
10058     {
10059       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
10060       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
10061       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
10062       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
10063       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
10064       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
10065     }
10066   else
10067     {
10068       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
10069       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
10070       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
10071     }
10072
10073
10074   while(size--)
10075     {
10076       pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
10077       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
10078       offset++;
10079     }
10080     
10081   pic16_freeAsmop(left,NULL,ic,TRUE);
10082   pic16_freeAsmop(result,NULL,ic,TRUE);
10083
10084 }
10085
10086
10087 /*-----------------------------------------------------------------*/
10088 /* genPointerGet - generate code for pointer get                   */
10089 /*-----------------------------------------------------------------*/
10090 static void genPointerGet (iCode *ic)
10091 {
10092     operand *left, *result ;
10093     sym_link *type, *etype;
10094     int p_type;
10095
10096     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10097
10098     left = IC_LEFT(ic);
10099     result = IC_RESULT(ic) ;
10100
10101     /* depending on the type of pointer we need to
10102     move it to the correct pointer register */
10103     type = operandType(left);
10104     etype = getSpec(type);
10105
10106 #if 0
10107     if (IS_PTR_CONST(type))
10108 #else
10109     if (IS_CODEPTR(type))
10110 #endif
10111       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
10112
10113     /* if left is of type of pointer then it is simple */
10114     if (IS_PTR(type) && !IS_FUNC(type->next)) 
10115         p_type = DCL_TYPE(type);
10116     else {
10117         /* we have to go by the storage class */
10118         p_type = PTR_TYPE(SPEC_OCLS(etype));
10119
10120         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
10121
10122         if (SPEC_OCLS(etype)->codesp ) {
10123           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
10124           //p_type = CPOINTER ; 
10125         }
10126         else
10127             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
10128               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
10129                /*p_type = FPOINTER ;*/ 
10130             else
10131                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
10132                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
10133 /*                  p_type = PPOINTER; */
10134                 else
10135                     if (SPEC_OCLS(etype) == idata )
10136                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
10137 /*                      p_type = IPOINTER; */
10138                     else
10139                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
10140 /*                      p_type = POINTER ; */
10141     }
10142
10143     /* now that we have the pointer type we assign
10144     the pointer values */
10145     switch (p_type) {
10146
10147     case POINTER:       
10148     case IPOINTER:
10149         genNearPointerGet (left,result,ic);
10150         break;
10151
10152     case PPOINTER:
10153         genPagedPointerGet(left,result,ic);
10154         break;
10155
10156     case FPOINTER:
10157         genFarPointerGet (left,result,ic);
10158         break;
10159
10160     case CPOINTER:
10161         genConstPointerGet (left,result,ic);
10162         //pic16_emitcodePointerGet (left,result,ic);
10163         break;
10164
10165     case GPOINTER:
10166 #if 0
10167       if (IS_PTR_CONST(type))
10168         genConstPointerGet (left,result,ic);
10169       else
10170 #endif
10171         genGenPointerGet (left,result,ic);
10172       break;
10173
10174     default:
10175       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10176               "genPointerGet: illegal pointer type");
10177     
10178     }
10179
10180 }
10181
10182 /*-----------------------------------------------------------------*/
10183 /* genPackBits - generates code for packed bit storage             */
10184 /*-----------------------------------------------------------------*/
10185 static void genPackBits (sym_link    *etype , operand *result,
10186                          operand *right ,
10187                          char *rname, int p_type)
10188 {
10189   int shCnt = 0 ;
10190   int offset = 0  ;
10191   int rLen = 0 ;
10192   int blen, bstr ;   
10193   char *l ;
10194
10195         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10196         blen = SPEC_BLEN(etype);
10197         bstr = SPEC_BSTR(etype);
10198
10199         if(AOP_TYPE(right) == AOP_LIT) {
10200                 if((blen == 1) && (bstr < 8)) {
10201                   unsigned long lit;
10202                         /* it is a single bit, so use the appropriate bit instructions */
10203
10204                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
10205
10206                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10207 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10208                         if((p_type == POINTER) && (result)) {
10209                                 /* workaround to reduce the extra lfsr instruction */
10210                                 if(lit) {
10211                                         pic16_emitpcode(POC_BSF,
10212                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
10213                                 } else {
10214                                         pic16_emitpcode(POC_BCF,
10215                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
10216                                 }
10217                         } else {
10218
10219                                 if(lit) {
10220                                         pic16_emitpcode(POC_BSF,
10221                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10222                                 } else {
10223                                         pic16_emitpcode(POC_BCF,
10224                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10225                                 }
10226                         }
10227         
10228                   return;
10229                 }
10230
10231                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
10232                 offset++;
10233         } else
10234                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
10235
10236         /* if the bit lenth is less than or    */
10237         /* it exactly fits a byte then         */
10238         if((shCnt=SPEC_BSTR(etype))
10239                 || SPEC_BLEN(etype) <= 8 )  {
10240
10241                 /* shift left acc */
10242                 AccLsh(shCnt);
10243
10244                 /* using PRODL as a temporary register here */
10245                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
10246
10247                 switch (p_type) {
10248                         case FPOINTER:
10249                         case POINTER:
10250                         case GPOINTER:
10251                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10252 //                              pic16_emitcode ("mov","b,a");
10253 //                              pic16_emitcode("mov","a,@%s",rname);
10254                                 break;
10255                 }
10256 #if 1
10257                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10258                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
10259                                         (unsigned char)(0xff >> (8-bstr))) ));
10260                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
10261                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10262 #endif
10263
10264           return;
10265         }
10266
10267
10268         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10269         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10270         exit(-1);
10271
10272
10273     /* if we r done */
10274     if ( SPEC_BLEN(etype) <= 8 )
10275         return ;
10276
10277     pic16_emitcode("inc","%s",rname);
10278     rLen = SPEC_BLEN(etype) ;     
10279
10280
10281
10282     /* now generate for lengths greater than one byte */
10283     while (1) {
10284
10285         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
10286
10287         rLen -= 8 ;
10288         if (rLen <= 0 )
10289             break ;
10290
10291         switch (p_type) {
10292             case POINTER:
10293                 if (*l == '@') {
10294                     MOVA(l);
10295                     pic16_emitcode("mov","@%s,a",rname);
10296                 } else
10297                     pic16_emitcode("mov","@%s,%s",rname,l);
10298                 break;
10299
10300             case FPOINTER:
10301                 MOVA(l);
10302                 pic16_emitcode("movx","@dptr,a");
10303                 break;
10304
10305             case GPOINTER:
10306                 MOVA(l);
10307                 DEBUGpic16_emitcode(";lcall","__gptrput");
10308                 break;  
10309         }   
10310         pic16_emitcode ("inc","%s",rname);
10311     }
10312
10313     MOVA(l);
10314
10315     /* last last was not complete */
10316     if (rLen)   {
10317         /* save the byte & read byte */
10318         switch (p_type) {
10319             case POINTER:
10320                 pic16_emitcode ("mov","b,a");
10321                 pic16_emitcode("mov","a,@%s",rname);
10322                 break;
10323
10324             case FPOINTER:
10325                 pic16_emitcode ("mov","b,a");
10326                 pic16_emitcode("movx","a,@dptr");
10327                 break;
10328
10329             case GPOINTER:
10330                 pic16_emitcode ("push","b");
10331                 pic16_emitcode ("push","acc");
10332                 pic16_emitcode ("lcall","__gptrget");
10333                 pic16_emitcode ("pop","b");
10334                 break;
10335         }
10336
10337         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
10338         pic16_emitcode ("orl","a,b");
10339     }
10340
10341     if (p_type == GPOINTER)
10342         pic16_emitcode("pop","b");
10343
10344     switch (p_type) {
10345
10346     case POINTER:
10347         pic16_emitcode("mov","@%s,a",rname);
10348         break;
10349         
10350     case FPOINTER:
10351         pic16_emitcode("movx","@dptr,a");
10352         break;
10353         
10354     case GPOINTER:
10355         DEBUGpic16_emitcode(";lcall","__gptrput");
10356         break;                  
10357     }
10358 }
10359 /*-----------------------------------------------------------------*/
10360 /* genDataPointerSet - remat pointer to data space                 */
10361 /*-----------------------------------------------------------------*/
10362 static void genDataPointerSet(operand *right,
10363                               operand *result,
10364                               iCode *ic)
10365 {
10366     int size, offset = 0, resoffset=0 ;
10367
10368     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10369     pic16_aopOp(right,ic,FALSE);
10370
10371     size = AOP_SIZE(right);
10372
10373 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10374
10375 #if 0
10376     if ( AOP_TYPE(result) == AOP_PCODE) {
10377       fprintf(stderr,"genDataPointerSet   %s, %d\n",
10378               AOP(result)->aopu.pcop->name,
10379                 (AOP(result)->aopu.pcop->type == PO_DIR)?
10380               PCOR(AOP(result)->aopu.pcop)->instance:
10381               PCOI(AOP(result)->aopu.pcop)->offset);
10382     }
10383 #endif
10384
10385         if(AOP(result)->aopu.pcop->type == PO_DIR)
10386                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
10387
10388         while (size--) {
10389                 if (AOP_TYPE(right) == AOP_LIT) {
10390                   unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
10391
10392                         lit = lit >> (8*offset);
10393                         if(lit&0xff) {
10394                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
10395                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
10396                         } else {
10397                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
10398                         }
10399                 } else {
10400                         mov2w(AOP(right), offset);
10401                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
10402                 }
10403                 offset++;
10404                 resoffset++;
10405         }
10406
10407     pic16_freeAsmop(right,NULL,ic,TRUE);
10408 }
10409
10410
10411
10412 /*-----------------------------------------------------------------*/
10413 /* genNearPointerSet - pic16_emitcode for near pointer put         */
10414 /*-----------------------------------------------------------------*/
10415 static void genNearPointerSet (operand *right,
10416                                operand *result, 
10417                                iCode *ic)
10418 {
10419   asmop *aop = NULL;
10420   char *l;
10421   sym_link *retype;
10422   sym_link *ptype = operandType(result);
10423   sym_link *resetype;
10424     
10425         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10426         retype= getSpec(operandType(right));
10427         resetype = getSpec(operandType(result));
10428   
10429         pic16_aopOp(result,ic,FALSE);
10430     
10431         /* if the result is rematerializable &
10432          * in data space & not a bit variable */
10433         
10434         /* and result is not a bit variable */
10435         if (AOP_TYPE(result) == AOP_PCODE
10436 //              && AOP_TYPE(result) == AOP_IMMD
10437                 && DCL_TYPE(ptype) == POINTER
10438                 && !IS_BITFIELD(retype)
10439                 && !IS_BITFIELD(resetype)) {
10440
10441                 genDataPointerSet (right,result,ic);
10442                 pic16_freeAsmop(result,NULL,ic,TRUE);
10443           return;
10444         }
10445
10446         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10447         pic16_aopOp(right,ic,FALSE);
10448         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10449
10450         /* if the value is already in a pointer register
10451          * then don't need anything more */
10452         if (!AOP_INPREG(AOP(result))) {
10453                 /* otherwise get a free pointer register */
10454                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10455
10456                 if( (AOP_TYPE(result) == AOP_PCODE) 
10457                         && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
10458                                 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
10459                 {
10460                   if(!IS_BITFIELD(resetype))
10461                         pic16_loadFSR0( result );  // patch 10
10462                 } else {
10463                         // set up FSR0 with address of result
10464                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10465                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10466                 }
10467
10468         }
10469 //      else
10470 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10471
10472         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10473
10474         /* if bitfield then unpack the bits */
10475         if (IS_BITFIELD(resetype)) {
10476                 genPackBits (resetype, result, right, NULL, POINTER);
10477         } else {
10478                 /* we have can just get the values */
10479           int size = AOP_SIZE(right);
10480           int offset = 0 ;    
10481
10482                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10483                 while (size--) {
10484                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10485                         if (*l == '@' ) {
10486                                 //MOVA(l);
10487                                 //pic16_emitcode("mov","@%s,a",rname);
10488                                 pic16_emitcode("movf","indf0,w ;1");
10489                         } else {
10490
10491                                 if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
10492                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
10493                                         if (size) {                                                                     // 
10494                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
10495                                         } else {                                                                        // 
10496                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
10497                                         }                                                                               // 
10498                                 } else { // no literal                                                                  // 
10499                                         if(size) {                                                                      // 
10500                                                 pic16_emitpcode(POC_MOVFF,                                              // 
10501                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
10502                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));         // 
10503                                         } else {                                                                        // 
10504                                                 pic16_emitpcode(POC_MOVFF,                                              // 
10505                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
10506                                                                         pic16_popCopyReg(&pic16_pc_indf0)));            //
10507                                         }                                                                               //
10508                                 }                                                                                       // patch 10
10509                         }
10510                         offset++;
10511                 }
10512         }
10513
10514         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10515         /* now some housekeeping stuff */
10516         if (aop) {
10517                 /* we had to allocate for this iCode */
10518                 pic16_freeAsmop(NULL,aop,ic,TRUE);
10519         } else { 
10520                 /* we did not allocate which means left
10521                  * already in a pointer register, then
10522                  * if size > 0 && this could be used again
10523                  * we have to point it back to where it 
10524                  * belongs */
10525                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10526                 if (AOP_SIZE(right) > 1
10527                         && !OP_SYMBOL(result)->remat
10528                         && ( OP_SYMBOL(result)->liveTo > ic->seq
10529                                 || ic->depth )) {
10530
10531                   int size = AOP_SIZE(right) - 1;
10532
10533                         while (size--)
10534                                 pic16_emitcode("decf","fsr0,f");
10535                         //pic16_emitcode("dec","%s",rname);
10536                 }
10537         }
10538
10539         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10540         /* done */
10541 //release:
10542         pic16_freeAsmop(right,NULL,ic,TRUE);
10543         pic16_freeAsmop(result,NULL,ic,TRUE);
10544 }
10545
10546 /*-----------------------------------------------------------------*/
10547 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
10548 /*-----------------------------------------------------------------*/
10549 static void genPagedPointerSet (operand *right,
10550                                operand *result, 
10551                                iCode *ic)
10552 {
10553     asmop *aop = NULL;
10554     regs *preg = NULL ;
10555     char *rname , *l;
10556     sym_link *retype;
10557        
10558     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10559
10560     retype= getSpec(operandType(right));
10561     
10562     pic16_aopOp(result,ic,FALSE);
10563     
10564     /* if the value is already in a pointer register
10565        then don't need anything more */
10566     if (!AOP_INPREG(AOP(result))) {
10567         /* otherwise get a free pointer register */
10568         aop = newAsmop(0);
10569         preg = getFreePtr(ic,&aop,FALSE);
10570         pic16_emitcode("mov","%s,%s",
10571                 preg->name,
10572                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
10573         rname = preg->name ;
10574     } else
10575         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10576     
10577     pic16_freeAsmop(result,NULL,ic,TRUE);
10578     pic16_aopOp (right,ic,FALSE);
10579
10580     /* if bitfield then unpack the bits */
10581     if (IS_BITFIELD(retype)) 
10582         genPackBits (retype,result,right,rname,PPOINTER);
10583     else {
10584         /* we have can just get the values */
10585         int size = AOP_SIZE(right);
10586         int offset = 0 ;        
10587         
10588         while (size--) {
10589             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10590             
10591             MOVA(l);
10592             pic16_emitcode("movx","@%s,a",rname);
10593
10594             if (size)
10595                 pic16_emitcode("inc","%s",rname);
10596
10597             offset++;
10598         }
10599     }
10600     
10601     /* now some housekeeping stuff */
10602     if (aop) {
10603         /* we had to allocate for this iCode */
10604         pic16_freeAsmop(NULL,aop,ic,TRUE);
10605     } else { 
10606         /* we did not allocate which means left
10607            already in a pointer register, then
10608            if size > 0 && this could be used again
10609            we have to point it back to where it 
10610            belongs */
10611         if (AOP_SIZE(right) > 1 &&
10612             !OP_SYMBOL(result)->remat &&
10613             ( OP_SYMBOL(result)->liveTo > ic->seq ||
10614               ic->depth )) {
10615             int size = AOP_SIZE(right) - 1;
10616             while (size--)
10617                 pic16_emitcode("dec","%s",rname);
10618         }
10619     }
10620
10621     /* done */
10622     pic16_freeAsmop(right,NULL,ic,TRUE);
10623     
10624         
10625 }
10626
10627 /*-----------------------------------------------------------------*/
10628 /* genFarPointerSet - set value from far space                     */
10629 /*-----------------------------------------------------------------*/
10630 static void genFarPointerSet (operand *right,
10631                               operand *result, iCode *ic)
10632 {
10633     int size, offset ;
10634     sym_link *retype = getSpec(operandType(right));
10635
10636     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10637     pic16_aopOp(result,ic,FALSE);
10638
10639     /* if the operand is already in dptr 
10640     then we do nothing else we move the value to dptr */
10641     if (AOP_TYPE(result) != AOP_STR) {
10642         /* if this is remateriazable */
10643         if (AOP_TYPE(result) == AOP_IMMD)
10644             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
10645         else { /* we need to get it byte by byte */
10646             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
10647             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
10648             if (options.model == MODEL_FLAT24)
10649             {
10650                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
10651             }
10652         }
10653     }
10654     /* so dptr know contains the address */
10655     pic16_freeAsmop(result,NULL,ic,TRUE);
10656     pic16_aopOp(right,ic,FALSE);
10657
10658     /* if bit then unpack */
10659     if (IS_BITFIELD(retype)) 
10660         genPackBits(retype,result,right,"dptr",FPOINTER);
10661     else {
10662         size = AOP_SIZE(right);
10663         offset = 0 ;
10664
10665         while (size--) {
10666             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10667             MOVA(l);
10668             pic16_emitcode("movx","@dptr,a");
10669             if (size)
10670                 pic16_emitcode("inc","dptr");
10671         }
10672     }
10673
10674     pic16_freeAsmop(right,NULL,ic,TRUE);
10675 }
10676
10677 /*-----------------------------------------------------------------*/
10678 /* genGenPointerSet - set value from generic pointer space         */
10679 /*-----------------------------------------------------------------*/
10680 static void genGenPointerSet (operand *right,
10681                               operand *result, iCode *ic)
10682 {
10683         int i, size, offset, lit;
10684         sym_link *retype = getSpec(operandType(right));
10685
10686         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10687
10688         pic16_aopOp(result,ic,FALSE);
10689         pic16_aopOp(right,ic,FALSE);
10690         size = AOP_SIZE(right);
10691         offset = 0;
10692
10693         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10694
10695         /* if the operand is already in dptr 
10696                 then we do nothing else we move the value to dptr */
10697         if (AOP_TYPE(result) != AOP_STR) {
10698                 /* if this is remateriazable */
10699                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10700                 // WARNING: anythig until "else" is untested!
10701                 if (AOP_TYPE(result) == AOP_IMMD) {
10702                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10703                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
10704                         // load FSR0 from immediate
10705                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10706                         offset = 0;
10707                         while(size--) {
10708                                 if(size) {
10709                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10710                                 } else {
10711                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10712                                 }
10713                                 offset++;
10714                         }
10715                         goto release;
10716                 }
10717                 else { /* we need to get it byte by byte */
10718                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10719                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10720
10721                         // set up FSR0 with address of result
10722                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10723                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10724
10725                         /* hack hack! see if this the FSR. If so don't load W */
10726                         if(AOP_TYPE(right) != AOP_ACC) {
10727
10728                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10729
10730                                 if(AOP_TYPE(right) == AOP_LIT)
10731                                 {
10732                                         // copy literal
10733                                         // note: pic16_popGet handles sign extension
10734                                         for(i=0;i<size;i++) {
10735                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
10736                                                 if(i < size-1)
10737                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
10738                                                 else
10739                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10740                                         }
10741                                 } else {
10742                                         // copy regs
10743
10744                                         for(i=0;i<size;i++) {
10745                                                 if(i < size-1)
10746                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10747                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
10748                                                 else
10749                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10750                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
10751                                         }
10752                                 }
10753                                 goto release;
10754                         } 
10755                         // right = ACC
10756                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10757                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10758                         goto release;
10759         } // if (AOP_TYPE(result) != AOP_IMMD)
10760
10761         } // if (AOP_TYPE(result) != AOP_STR)
10762         /* so dptr know contains the address */
10763
10764
10765         /* if bit then unpack */
10766         if (IS_BITFIELD(retype)) 
10767                 genPackBits(retype,result,right,"dptr",GPOINTER);
10768         else {
10769                 size = AOP_SIZE(right);
10770                 offset = 0 ;
10771
10772                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
10773
10774                 // set up FSR0 with address of result
10775                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10776                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10777         
10778                 while (size--) {
10779                         if (AOP_TYPE(right) == AOP_LIT) {
10780                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10781                                 if (size) {
10782                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
10783                                 } else {
10784                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10785                                 }
10786                         } else { // no literal
10787                                 if(size) {
10788                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10789                                 } else {
10790                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10791                                 }
10792                         }
10793                         offset++;
10794                 }
10795         }
10796
10797         release:
10798         pic16_freeAsmop(right,NULL,ic,TRUE);
10799         pic16_freeAsmop(result,NULL,ic,TRUE);
10800 }
10801
10802 /*-----------------------------------------------------------------*/
10803 /* genPointerSet - stores the value into a pointer location        */
10804 /*-----------------------------------------------------------------*/
10805 static void genPointerSet (iCode *ic)
10806 {    
10807     operand *right, *result ;
10808     sym_link *type, *etype;
10809     int p_type;
10810
10811     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10812
10813     right = IC_RIGHT(ic);
10814     result = IC_RESULT(ic) ;
10815
10816     /* depending on the type of pointer we need to
10817     move it to the correct pointer register */
10818     type = operandType(result);
10819     etype = getSpec(type);
10820     /* if left is of type of pointer then it is simple */
10821     if (IS_PTR(type) && !IS_FUNC(type->next)) {
10822         p_type = DCL_TYPE(type);
10823     }
10824     else {
10825         /* we have to go by the storage class */
10826         p_type = PTR_TYPE(SPEC_OCLS(etype));
10827
10828 /*      if (SPEC_OCLS(etype)->codesp ) { */
10829 /*          p_type = CPOINTER ;  */
10830 /*      } */
10831 /*      else */
10832 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10833 /*              p_type = FPOINTER ; */
10834 /*          else */
10835 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10836 /*                  p_type = PPOINTER ; */
10837 /*              else */
10838 /*                  if (SPEC_OCLS(etype) == idata ) */
10839 /*                      p_type = IPOINTER ; */
10840 /*                  else */
10841 /*                      p_type = POINTER ; */
10842     }
10843
10844     /* now that we have the pointer type we assign
10845     the pointer values */
10846     switch (p_type) {
10847
10848     case POINTER:
10849     case IPOINTER:
10850         genNearPointerSet (right,result,ic);
10851         break;
10852
10853     case PPOINTER:
10854         genPagedPointerSet (right,result,ic);
10855         break;
10856
10857     case FPOINTER:
10858         genFarPointerSet (right,result,ic);
10859         break;
10860
10861     case GPOINTER:
10862         genGenPointerSet (right,result,ic);
10863         break;
10864
10865     default:
10866       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10867               "genPointerSet: illegal pointer type");
10868     }
10869 }
10870
10871 /*-----------------------------------------------------------------*/
10872 /* genIfx - generate code for Ifx statement                        */
10873 /*-----------------------------------------------------------------*/
10874 static void genIfx (iCode *ic, iCode *popIc)
10875 {
10876   operand *cond = IC_COND(ic);
10877   int isbit =0;
10878
10879   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10880
10881   pic16_aopOp(cond,ic,FALSE);
10882
10883   /* get the value into acc */
10884   if (AOP_TYPE(cond) != AOP_CRY)
10885     pic16_toBoolean(cond);
10886   else
10887     isbit = 1;
10888   /* the result is now in the accumulator */
10889   pic16_freeAsmop(cond,NULL,ic,TRUE);
10890
10891   /* if there was something to be popped then do it */
10892   if (popIc)
10893     genIpop(popIc);
10894
10895   /* if the condition is  a bit variable */
10896   if (isbit && IS_ITEMP(cond) && 
10897       SPIL_LOC(cond)) {
10898     genIfxJump(ic,SPIL_LOC(cond)->rname);
10899     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10900   }
10901   else {
10902     if (isbit && !IS_ITEMP(cond))
10903       genIfxJump(ic,OP_SYMBOL(cond)->rname);
10904     else
10905       genIfxJump(ic,"a");
10906   }
10907   ic->generated = 1;
10908
10909 }
10910
10911 /*-----------------------------------------------------------------*/
10912 /* genAddrOf - generates code for address of                       */
10913 /*-----------------------------------------------------------------*/
10914 static void genAddrOf (iCode *ic)
10915 {
10916   operand *result, *left;
10917   int size;
10918   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
10919   pCodeOp *pcop0, *pcop1, *pcop2;
10920
10921         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10922
10923         pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10924         pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10925
10926         sym = OP_SYMBOL( left );
10927
10928         size = AOP_SIZE(IC_RESULT(ic));
10929
10930
10931         if(sym->onStack) {
10932                 DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
10933         
10934                 return;
10935         }
10936         
10937 //      if(pic16_debug_verbose) {
10938 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10939 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10940 //      }
10941         
10942         /* Assume that what we want the address of is in data space
10943          * since there is no stack on the PIC, yet! -- VR */
10944         /* low */
10945         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10946
10947         /* high */
10948         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10949         
10950         /* upper */
10951         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10952         
10953
10954         if (size == 3) {
10955                 pic16_emitpcode(POC_MOVLW, pcop0);
10956                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10957                 pic16_emitpcode(POC_MOVLW, pcop1);
10958                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10959                 pic16_emitpcode(POC_MOVLW, pcop2);
10960                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10961         } else
10962         if (size == 2) {
10963                 pic16_emitpcode(POC_MOVLW, pcop0);
10964                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10965                 pic16_emitpcode(POC_MOVLW, pcop1);
10966                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10967         } else {
10968                 pic16_emitpcode(POC_MOVLW, pcop0);
10969                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10970         }
10971
10972         pic16_freeAsmop(result,NULL,ic,TRUE);
10973         pic16_freeAsmop(left, NULL, ic, FALSE);
10974 }
10975
10976
10977 #if 0
10978 /*-----------------------------------------------------------------*/
10979 /* genFarFarAssign - assignment when both are in far space         */
10980 /*-----------------------------------------------------------------*/
10981 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10982 {
10983     int size = AOP_SIZE(right);
10984     int offset = 0;
10985     char *l ;
10986     /* first push the right side on to the stack */
10987     while (size--) {
10988         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10989         MOVA(l);
10990         pic16_emitcode ("push","acc");
10991     }
10992     
10993     pic16_freeAsmop(right,NULL,ic,FALSE);
10994     /* now assign DPTR to result */
10995     pic16_aopOp(result,ic,FALSE);
10996     size = AOP_SIZE(result);
10997     while (size--) {
10998         pic16_emitcode ("pop","acc");
10999         pic16_aopPut(AOP(result),"a",--offset);
11000     }
11001     pic16_freeAsmop(result,NULL,ic,FALSE);
11002         
11003 }
11004 #endif
11005
11006 /*-----------------------------------------------------------------*/
11007 /* genAssign - generate code for assignment                        */
11008 /*-----------------------------------------------------------------*/
11009 static void genAssign (iCode *ic)
11010 {
11011   operand *result, *right;
11012   int size, offset,know_W;
11013   unsigned long lit = 0L;
11014
11015   result = IC_RESULT(ic);
11016   right  = IC_RIGHT(ic) ;
11017
11018   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11019   
11020   /* if they are the same */
11021   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
11022     return ;
11023
11024   pic16_aopOp(right,ic,FALSE);
11025   pic16_aopOp(result,ic,TRUE);
11026
11027   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11028
11029   /* if they are the same registers */
11030   if (pic16_sameRegs(AOP(right),AOP(result)))
11031     goto release;
11032
11033   /* if the result is a bit */
11034   if (AOP_TYPE(result) == AOP_CRY) {
11035     /* if the right size is a literal then
11036        we know what the value is */
11037     if (AOP_TYPE(right) == AOP_LIT) {
11038           
11039       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
11040                   pic16_popGet(AOP(result),0));
11041
11042       if (((int) operandLitValue(right))) 
11043         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
11044                        AOP(result)->aopu.aop_dir,
11045                        AOP(result)->aopu.aop_dir);
11046       else
11047         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
11048                        AOP(result)->aopu.aop_dir,
11049                        AOP(result)->aopu.aop_dir);
11050       goto release;
11051     }
11052
11053     /* the right is also a bit variable */
11054     if (AOP_TYPE(right) == AOP_CRY) {
11055       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
11056       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
11057       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
11058
11059       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
11060                      AOP(result)->aopu.aop_dir,
11061                      AOP(result)->aopu.aop_dir);
11062       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
11063                      AOP(right)->aopu.aop_dir,
11064                      AOP(right)->aopu.aop_dir);
11065       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
11066                      AOP(result)->aopu.aop_dir,
11067                      AOP(result)->aopu.aop_dir);
11068       goto release ;
11069     }
11070
11071     /* we need to or */
11072     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
11073     pic16_toBoolean(right);
11074     emitSKPZ;
11075     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
11076     //pic16_aopPut(AOP(result),"a",0);
11077     goto release ;
11078   }
11079
11080   /* bit variables done */
11081   /* general case */
11082   size = AOP_SIZE(result);
11083   offset = 0 ;
11084
11085   if(AOP_TYPE(right) == AOP_LIT) {
11086         if(!IS_FLOAT(operandType( right )))
11087                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11088         else {
11089            union {
11090               unsigned long lit_int;
11091               float lit_float;
11092             } info;
11093         
11094                 /* take care if literal is a float */
11095                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
11096                 lit = info.lit_int;
11097         }
11098   }
11099
11100 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
11101 //                      sizeof(unsigned long int), sizeof(float));
11102
11103   if(AOP_TYPE(right) != AOP_LIT
11104         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))) {
11105         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
11106         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
11107
11108         // set up table pointer
11109         if( (AOP_TYPE(right) == AOP_PCODE)
11110                 && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE)
11111                 || (AOP(right)->aopu.pcop->type == PO_DIR)))
11112         {
11113                 fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
11114                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
11115                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11116                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
11117                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11118                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
11119                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11120         } else {
11121                 fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
11122                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
11123                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
11124                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
11125                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
11126                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
11127                                 pic16_popCopyReg(&pic16_pc_tblptru)));
11128         }
11129
11130         size = min(AOP_SIZE(right), AOP_SIZE(result));
11131         while(size--) {
11132                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11133                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
11134                         pic16_popGet(AOP(result),offset)));
11135                 offset++;
11136         }
11137
11138         if(AOP_SIZE(result) > AOP_SIZE(right)) {
11139                 size = AOP_SIZE(result) - AOP_SIZE(right);
11140                 while(size--) {
11141                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
11142                         offset++;
11143                 }
11144         }
11145         goto release;
11146   }
11147
11148
11149
11150 #if 0
11151 /* VR - What is this?! */
11152   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
11153     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11154     if(aopIdx(AOP(result),0) == 4) {
11155
11156       /* this is a workaround to save value of right into wreg too,
11157        * value of wreg is going to be used later */
11158       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11159       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11160       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11161       goto release;
11162     } else
11163 //      assert(0);
11164       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
11165   }
11166 #endif
11167
11168   know_W=-1;
11169   while (size--) {
11170   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11171     if(AOP_TYPE(right) == AOP_LIT) {
11172       if(lit&0xff) {
11173         if(know_W != (lit&0xff))
11174           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
11175         know_W = lit&0xff;
11176         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11177       } else
11178         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
11179
11180       lit >>= 8;
11181
11182     } else if (AOP_TYPE(right) == AOP_CRY) {
11183       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
11184       if(offset == 0) {
11185         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
11186         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
11187       }
11188     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
11189         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11190         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11191     } else {
11192   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11193
11194 #if 1
11195         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
11196            normally should work, but mind that the W register live range
11197            is not checked, so if the code generator assumes that the W
11198            is already loaded after such a pair, wrong code will be generated.
11199            
11200            Checking the live range is the next step.
11201            This is experimental code yet and has not been fully tested yet.
11202            USE WITH CARE. Revert to old code by setting 0 to the condition above.
11203            Vangelis Rokas 030603 (vrokas@otenet.gr) */
11204            
11205         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
11206 #else   
11207         /* This is the old code, which is assumed(?!) that works fine(!?) */
11208
11209         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11210         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11211 #endif
11212     }
11213             
11214     offset++;
11215   }
11216
11217     
11218  release:
11219   pic16_freeAsmop (right,NULL,ic,FALSE);
11220   pic16_freeAsmop (result,NULL,ic,TRUE);
11221 }   
11222
11223 /*-----------------------------------------------------------------*/
11224 /* genJumpTab - generates code for jump table                       */
11225 /*-----------------------------------------------------------------*/
11226 static void genJumpTab (iCode *ic)
11227 {
11228     symbol *jtab;
11229     char *l;
11230
11231     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11232
11233     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
11234     /* get the condition into accumulator */
11235     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
11236     MOVA(l);
11237     /* multiply by three */
11238     pic16_emitcode("add","a,acc");
11239     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
11240
11241     jtab = newiTempLabel(NULL);
11242     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
11243     pic16_emitcode("jmp","@a+dptr");
11244     pic16_emitcode("","%05d_DS_:",jtab->key+100);
11245
11246     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
11247     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
11248     emitSKPNC;
11249     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
11250     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
11251     pic16_emitpLabel(jtab->key);
11252
11253     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
11254
11255     /* now generate the jump labels */
11256     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
11257          jtab = setNextItem(IC_JTLABELS(ic))) {
11258         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
11259         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
11260         
11261     }
11262
11263 }
11264
11265 /*-----------------------------------------------------------------*/
11266 /* genMixedOperation - gen code for operators between mixed types  */
11267 /*-----------------------------------------------------------------*/
11268 /*
11269   TSD - Written for the PIC port - but this unfortunately is buggy.
11270   This routine is good in that it is able to efficiently promote 
11271   types to different (larger) sizes. Unfortunately, the temporary
11272   variables that are optimized out by this routine are sometimes
11273   used in other places. So until I know how to really parse the 
11274   iCode tree, I'm going to not be using this routine :(.
11275 */
11276 static int genMixedOperation (iCode *ic)
11277 {
11278 #if 0
11279   operand *result = IC_RESULT(ic);
11280   sym_link *ctype = operandType(IC_LEFT(ic));
11281   operand *right = IC_RIGHT(ic);
11282   int ret = 0;
11283   int big,small;
11284   int offset;
11285
11286   iCode *nextic;
11287   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
11288
11289   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11290
11291   nextic = ic->next;
11292   if(!nextic)
11293     return 0;
11294
11295   nextright = IC_RIGHT(nextic);
11296   nextleft  = IC_LEFT(nextic);
11297   nextresult = IC_RESULT(nextic);
11298
11299   pic16_aopOp(right,ic,FALSE);
11300   pic16_aopOp(result,ic,FALSE);
11301   pic16_aopOp(nextright,  nextic, FALSE);
11302   pic16_aopOp(nextleft,   nextic, FALSE);
11303   pic16_aopOp(nextresult, nextic, FALSE);
11304
11305   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
11306
11307     operand *t = right;
11308     right = nextright;
11309     nextright = t; 
11310
11311     pic16_emitcode(";remove right +","");
11312
11313   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
11314 /*
11315     operand *t = right;
11316     right = nextleft;
11317     nextleft = t; 
11318 */
11319     pic16_emitcode(";remove left +","");
11320   } else
11321     return 0;
11322
11323   big = AOP_SIZE(nextleft);
11324   small = AOP_SIZE(nextright);
11325
11326   switch(nextic->op) {
11327
11328   case '+':
11329     pic16_emitcode(";optimize a +","");
11330     /* if unsigned or not an integral type */
11331     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
11332       pic16_emitcode(";add a bit to something","");
11333     } else {
11334
11335       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
11336
11337       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
11338         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
11339         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
11340       } else
11341         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
11342
11343       offset = 0;
11344       while(--big) {
11345
11346         offset++;
11347
11348         if(--small) {
11349           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
11350             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11351             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11352           }
11353
11354           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11355           emitSKPNC;
11356           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
11357                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
11358                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
11359           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11360           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
11361
11362         } else {
11363           pic16_emitcode("rlf","known_zero,w");
11364
11365           /*
11366             if right is signed
11367               btfsc  right,7
11368                addlw ff
11369           */
11370           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
11371             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11372             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11373           } else {
11374             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11375           }
11376         }
11377       }
11378       ret = 1;
11379     }
11380   }
11381   ret = 1;
11382
11383 release:
11384   pic16_freeAsmop(right,NULL,ic,TRUE);
11385   pic16_freeAsmop(result,NULL,ic,TRUE);
11386   pic16_freeAsmop(nextright,NULL,ic,TRUE);
11387   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
11388   if(ret)
11389     nextic->generated = 1;
11390
11391   return ret;
11392 #else
11393   return 0;
11394 #endif
11395 }
11396 /*-----------------------------------------------------------------*/
11397 /* genCast - gen code for casting                                  */
11398 /*-----------------------------------------------------------------*/
11399 static void genCast (iCode *ic)
11400 {
11401   operand *result = IC_RESULT(ic);
11402   sym_link *ctype = operandType(IC_LEFT(ic));
11403   sym_link *rtype = operandType(IC_RIGHT(ic));
11404   operand *right = IC_RIGHT(ic);
11405   int size, offset ;
11406
11407         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11408         /* if they are equivalent then do nothing */
11409         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
11410                 return ;
11411
11412         pic16_aopOp(right,ic,FALSE) ;
11413         pic16_aopOp(result,ic,FALSE);
11414
11415         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11416
11417         /* if the result is a bit */
11418         if (AOP_TYPE(result) == AOP_CRY) {
11419         
11420                 /* if the right size is a literal then
11421                  * we know what the value is */
11422                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11423
11424                 if (AOP_TYPE(right) == AOP_LIT) {
11425                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
11426                                 pic16_popGet(AOP(result),0));
11427
11428                         if (((int) operandLitValue(right))) 
11429                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
11430                                         AOP(result)->aopu.aop_dir,
11431                                         AOP(result)->aopu.aop_dir);
11432                         else
11433                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
11434                                         AOP(result)->aopu.aop_dir,
11435                                         AOP(result)->aopu.aop_dir);
11436                         goto release;
11437                 }
11438
11439                 /* the right is also a bit variable */
11440                 if (AOP_TYPE(right) == AOP_CRY) {
11441                         emitCLRC;
11442                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
11443
11444                         pic16_emitcode("clrc","");
11445                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
11446                                 AOP(right)->aopu.aop_dir,
11447                                 AOP(right)->aopu.aop_dir);
11448                         pic16_aopPut(AOP(result),"c",0);
11449                         goto release ;
11450                 }
11451
11452                 /* we need to or */
11453                 if (AOP_TYPE(right) == AOP_REG) {
11454                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
11455                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
11456                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
11457                 }
11458                 pic16_toBoolean(right);
11459                 pic16_aopPut(AOP(result),"a",0);
11460                 goto release ;
11461         }
11462
11463         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
11464           int offset = 1;
11465
11466                 size = AOP_SIZE(result);
11467
11468                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11469
11470                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
11471                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
11472                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
11473
11474                 while (size--)
11475                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
11476
11477                 goto release;
11478         }
11479
11480         /* if they are the same size : or less */
11481         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
11482
11483                 /* if they are in the same place */
11484                 if (pic16_sameRegs(AOP(right),AOP(result)))
11485                         goto release;
11486
11487                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11488 #if 0
11489                 if (IS_PTR_CONST(rtype))
11490 #else
11491                 if (IS_CODEPTR(rtype))
11492 #endif
11493                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
11494
11495 #if 0
11496                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
11497 #else
11498                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
11499 #endif
11500                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
11501
11502 #if 0
11503                 if(AOP_TYPE(right) == AOP_IMMD) {
11504                   pCodeOp *pcop0, *pcop1, *pcop2;
11505                   symbol *sym = OP_SYMBOL( right );
11506
11507                         size = AOP_SIZE(result);
11508                         /* low */
11509                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11510                         /* high */
11511                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11512                         /* upper */
11513                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11514         
11515                         if (size == 3) {
11516                                 pic16_emitpcode(POC_MOVLW, pcop0);
11517                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11518                                 pic16_emitpcode(POC_MOVLW, pcop1);
11519                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
11520                                 pic16_emitpcode(POC_MOVLW, pcop2);
11521                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
11522                         } else
11523                         if (size == 2) {
11524                                 pic16_emitpcode(POC_MOVLW, pcop0);
11525                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11526                                 pic16_emitpcode(POC_MOVLW, pcop1);
11527                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11528                         } else {
11529                                 pic16_emitpcode(POC_MOVLW, pcop0);
11530                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11531                         }
11532                 } else
11533 #endif
11534                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11535                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
11536                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11537                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
11538                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11539                         if(AOP_SIZE(result) <2)
11540                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
11541                 } else {
11542                         /* if they in different places then copy */
11543                         size = AOP_SIZE(result);
11544                         offset = 0 ;
11545                         while (size--) {
11546                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11547                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11548                                 offset++;
11549                         }
11550                 }
11551                 goto release;
11552         }
11553
11554         /* if the result is of type pointer */
11555         if (IS_PTR(ctype)) {
11556           int p_type;
11557           sym_link *type = operandType(right);
11558           sym_link *etype = getSpec(type);
11559
11560                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
11561
11562                 /* pointer to generic pointer */
11563                 if (IS_GENPTR(ctype)) {
11564                   char *l = zero;
11565             
11566                         if (IS_PTR(type)) 
11567                                 p_type = DCL_TYPE(type);
11568                         else {
11569                 /* we have to go by the storage class */
11570                 p_type = PTR_TYPE(SPEC_OCLS(etype));
11571
11572 /*              if (SPEC_OCLS(etype)->codesp )  */
11573 /*                  p_type = CPOINTER ;  */
11574 /*              else */
11575 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11576 /*                      p_type = FPOINTER ; */
11577 /*                  else */
11578 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11579 /*                          p_type = PPOINTER; */
11580 /*                      else */
11581 /*                          if (SPEC_OCLS(etype) == idata ) */
11582 /*                              p_type = IPOINTER ; */
11583 /*                          else */
11584 /*                              p_type = POINTER ; */
11585             }
11586                 
11587             /* the first two bytes are known */
11588       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
11589             size = GPTRSIZE - 1; 
11590             offset = 0 ;
11591             while (size--) {
11592               if(offset < AOP_SIZE(right)) {
11593       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
11594                 if ((AOP_TYPE(right) == AOP_PCODE) && 
11595                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11596                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11597                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11598                 } else { 
11599                   pic16_aopPut(AOP(result),
11600                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11601                          offset);
11602                 }
11603               } else 
11604                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
11605               offset++;
11606             }
11607             /* the last byte depending on type */
11608             switch (p_type) {
11609             case IPOINTER:
11610             case POINTER:
11611                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
11612                 break;
11613             case FPOINTER:
11614               pic16_emitcode(";BUG!? ","%d",__LINE__);
11615                 l = one;
11616                 break;
11617             case CPOINTER:
11618               pic16_emitcode(";BUG!? ","%d",__LINE__);
11619                 l = "#0x02";
11620                 break;                          
11621             case PPOINTER:
11622               pic16_emitcode(";BUG!? ","%d",__LINE__);
11623                 l = "#0x03";
11624                 break;
11625                 
11626             default:
11627                 /* this should never happen */
11628                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11629                        "got unknown pointer type");
11630                 exit(1);
11631             }
11632             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
11633             goto release ;
11634         }
11635         
11636         /* just copy the pointers */
11637         size = AOP_SIZE(result);
11638         offset = 0 ;
11639         while (size--) {
11640             pic16_aopPut(AOP(result),
11641                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11642                    offset);
11643             offset++;
11644         }
11645         goto release ;
11646     }
11647     
11648
11649
11650     /* so we now know that the size of destination is greater
11651     than the size of the source.
11652     Now, if the next iCode is an operator then we might be
11653     able to optimize the operation without performing a cast.
11654     */
11655     if(genMixedOperation(ic))
11656       goto release;
11657
11658     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11659     
11660     /* we move to result for the size of source */
11661     size = AOP_SIZE(right);
11662     offset = 0 ;
11663     while (size--) {
11664       pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
11665 //      pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
11666 //      pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
11667       offset++;
11668     }
11669
11670     /* now depending on the sign of the destination */
11671     size = AOP_SIZE(result) - AOP_SIZE(right);
11672     /* if unsigned or not an integral type */
11673     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
11674       while (size--)
11675         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
11676     } else {
11677       /* we need to extend the sign :( */
11678
11679       if(size == 1) {
11680         /* Save one instruction of casting char to int */
11681         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
11682         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11683         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
11684       } else {
11685         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
11686
11687         if(offset)
11688           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11689         else
11690           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11691         
11692         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
11693
11694         while (size--)
11695           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
11696       }
11697     }
11698
11699 release:
11700     pic16_freeAsmop(right,NULL,ic,TRUE);
11701     pic16_freeAsmop(result,NULL,ic,TRUE);
11702
11703 }
11704
11705 /*-----------------------------------------------------------------*/
11706 /* genDjnz - generate decrement & jump if not zero instrucion      */
11707 /*-----------------------------------------------------------------*/
11708 static int genDjnz (iCode *ic, iCode *ifx)
11709 {
11710     symbol *lbl, *lbl1;
11711     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11712
11713     if (!ifx)
11714         return 0;
11715     
11716     /* if the if condition has a false label
11717        then we cannot save */
11718     if (IC_FALSE(ifx))
11719         return 0;
11720
11721     /* if the minus is not of the form 
11722        a = a - 1 */
11723     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
11724         !IS_OP_LITERAL(IC_RIGHT(ic)))
11725         return 0;
11726
11727     if (operandLitValue(IC_RIGHT(ic)) != 1)
11728         return 0;
11729
11730     /* if the size of this greater than one then no
11731        saving */
11732     if (getSize(operandType(IC_RESULT(ic))) > 1)
11733         return 0;
11734
11735     /* otherwise we can save BIG */
11736     lbl = newiTempLabel(NULL);
11737     lbl1= newiTempLabel(NULL);
11738
11739     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11740     
11741     if (IS_AOP_PREG(IC_RESULT(ic))) {
11742         pic16_emitcode("dec","%s",
11743                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11744         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11745         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
11746     } else {    
11747
11748
11749       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
11750       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
11751
11752       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11753       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
11754
11755     }
11756 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
11757 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
11758 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
11759 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
11760
11761     
11762     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11763     ifx->generated = 1;
11764     return 1;
11765 }
11766
11767 /*-----------------------------------------------------------------*/
11768 /* genReceive - generate code for a receive iCode                  */
11769 /*-----------------------------------------------------------------*/
11770 static void genReceive (iCode *ic)
11771 {    
11772         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11773
11774 #if 0
11775         fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
11776                 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
11777 #endif
11778 //      pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
11779
11780         if (isOperandInFarSpace(IC_RESULT(ic)) &&
11781                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
11782                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
11783
11784           int size = getSize(operandType(IC_RESULT(ic)));
11785           int offset =  pic16_fReturnSizePic - size;
11786
11787                 assert( 0 );
11788                 while (size--) {
11789                         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
11790                                         fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
11791                         offset++;
11792                 }
11793
11794                 DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
11795
11796                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11797                 size = AOP_SIZE(IC_RESULT(ic));
11798                 offset = 0;
11799                 while (size--) {
11800                         pic16_emitcode ("pop","acc");
11801                         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
11802                 }
11803         } else {
11804                 DEBUGpic16_emitcode ("; ***","2 %s  %d",__FUNCTION__,__LINE__);
11805
11806                 _G.accInUse++;
11807                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11808                 _G.accInUse--;
11809                 assignResultValue(IC_RESULT(ic), 0);
11810         }
11811
11812         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11813 }
11814
11815 /*-----------------------------------------------------------------*/
11816 /* genDummyRead - generate code for dummy read of volatiles        */
11817 /*-----------------------------------------------------------------*/
11818 static void
11819 genDummyRead (iCode * ic)
11820 {
11821   pic16_emitcode ("; genDummyRead","");
11822   pic16_emitcode ("; not implemented","");
11823
11824   ic = ic;
11825 }
11826
11827 /*-----------------------------------------------------------------*/
11828 /* genpic16Code - generate code for pic16 based controllers        */
11829 /*-----------------------------------------------------------------*/
11830 /*
11831  * At this point, ralloc.c has gone through the iCode and attempted
11832  * to optimize in a way suitable for a PIC. Now we've got to generate
11833  * PIC instructions that correspond to the iCode.
11834  *
11835  * Once the instructions are generated, we'll pass through both the
11836  * peep hole optimizer and the pCode optimizer.
11837  *-----------------------------------------------------------------*/
11838
11839 void genpic16Code (iCode *lic)
11840 {
11841     iCode *ic;
11842     int cln = 0;
11843
11844     lineHead = lineCurr = NULL;
11845
11846     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
11847     pic16_addpBlock(pb);
11848
11849 #if 0
11850     /* if debug information required */
11851     if (options.debug && currFunc) {
11852       if (currFunc) {
11853         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
11854       }
11855     }
11856 #endif
11857
11858     for (ic = lic ; ic ; ic = ic->next ) {
11859
11860       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
11861         if ( cln != ic->lineno ) {
11862             if ( options.debug ) {
11863               debugFile->writeCLine (ic);
11864             }
11865             
11866             if(!options.noCcodeInAsm) {
11867                 pic16_addpCode2pBlock(pb,
11868                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
11869                                 printCLine(ic->filename, ic->lineno)));
11870             }
11871
11872             cln = ic->lineno ;
11873         }
11874         
11875         if(options.iCodeInAsm) {
11876                 char *l;
11877                 /* insert here code to print iCode as comment */
11878                 l = Safe_strdup(printILine(ic));
11879                 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
11880         }
11881         
11882         /* if the result is marked as
11883            spilt and rematerializable or code for
11884            this has already been generated then
11885            do nothing */
11886         if (resultRemat(ic) || ic->generated ) 
11887             continue ;
11888         
11889         /* depending on the operation */
11890         switch (ic->op) {
11891         case '!' :
11892             pic16_genNot(ic);
11893             break;
11894             
11895         case '~' :
11896             pic16_genCpl(ic);
11897             break;
11898             
11899         case UNARYMINUS:
11900             genUminus (ic);
11901             break;
11902             
11903         case IPUSH:
11904             genIpush (ic);
11905             break;
11906             
11907         case IPOP:
11908             /* IPOP happens only when trying to restore a 
11909                spilt live range, if there is an ifx statement
11910                following this pop then the if statement might
11911                be using some of the registers being popped which
11912                would destroy the contents of the register so
11913                we need to check for this condition and handle it */
11914             if (ic->next            && 
11915                 ic->next->op == IFX &&
11916                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
11917                 genIfx (ic->next,ic);
11918             else
11919                 genIpop (ic);
11920             break; 
11921             
11922         case CALL:
11923             genCall (ic);
11924             break;
11925             
11926         case PCALL:
11927             genPcall (ic);
11928             break;
11929             
11930         case FUNCTION:
11931             genFunction (ic);
11932             break;
11933             
11934         case ENDFUNCTION:
11935             genEndFunction (ic);
11936             break;
11937             
11938         case RETURN:
11939             genRet (ic);
11940             break;
11941             
11942         case LABEL:
11943             genLabel (ic);
11944             break;
11945             
11946         case GOTO:
11947             genGoto (ic);
11948             break;
11949             
11950         case '+' :
11951             pic16_genPlus (ic) ;
11952             break;
11953             
11954         case '-' :
11955             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11956                 pic16_genMinus (ic);
11957             break;
11958             
11959         case '*' :
11960             genMult (ic);
11961             break;
11962             
11963         case '/' :
11964             genDiv (ic) ;
11965             break;
11966             
11967         case '%' :
11968             genMod (ic);
11969             break;
11970             
11971         case '>' :
11972             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
11973             break;
11974             
11975         case '<' :
11976             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11977             break;
11978             
11979         case LE_OP:
11980         case GE_OP:
11981         case NE_OP:
11982             
11983             /* note these two are xlated by algebraic equivalence
11984                during parsing SDCC.y */
11985             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11986                    "got '>=' or '<=' shouldn't have come here");
11987             break;      
11988             
11989         case EQ_OP:
11990             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11991             break;          
11992             
11993         case AND_OP:
11994             genAndOp (ic);
11995             break;
11996             
11997         case OR_OP:
11998             genOrOp (ic);
11999             break;
12000             
12001         case '^' :
12002             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
12003             break;
12004             
12005         case '|' :
12006                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
12007             break;
12008             
12009         case BITWISEAND:
12010             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
12011             break;
12012             
12013         case INLINEASM:
12014             genInline (ic);
12015             break;
12016             
12017         case RRC:
12018             genRRC (ic);
12019             break;
12020             
12021         case RLC:
12022             genRLC (ic);
12023             break;
12024             
12025         case GETHBIT:
12026             genGetHbit (ic);
12027             break;
12028             
12029         case LEFT_OP:
12030             genLeftShift (ic);
12031             break;
12032             
12033         case RIGHT_OP:
12034             genRightShift (ic);
12035             break;
12036             
12037         case GET_VALUE_AT_ADDRESS:
12038             genPointerGet(ic);
12039             break;
12040             
12041         case '=' :
12042             if (POINTER_SET(ic))
12043                 genPointerSet(ic);
12044             else
12045                 genAssign(ic);
12046             break;
12047             
12048         case IFX:
12049             genIfx (ic,NULL);
12050             break;
12051             
12052         case ADDRESS_OF:
12053             genAddrOf (ic);
12054             break;
12055             
12056         case JUMPTABLE:
12057             genJumpTab (ic);
12058             break;
12059             
12060         case CAST:
12061             genCast (ic);
12062             break;
12063             
12064         case RECEIVE:
12065             genReceive(ic);
12066             break;
12067             
12068         case SEND:
12069             addSet(&_G.sendSet,ic);
12070             break;
12071
12072         case DUMMY_READ_VOLATILE:
12073           genDummyRead (ic);
12074           break;
12075
12076         default :
12077             ic = ic;
12078         }
12079     }
12080
12081
12082     /* now we are ready to call the
12083        peep hole optimizer */
12084     if (!options.nopeep) {
12085       peepHole (&lineHead);
12086     }
12087     /* now do the actual printing */
12088     printLine (lineHead,codeOutFile);
12089
12090 #ifdef PCODE_DEBUG
12091     DFPRINTF((stderr,"printing pBlock\n\n"));
12092     pic16_printpBlock(stdout,pb);
12093 #endif
12094
12095     return;
12096 }
12097