* src/SDCCmain.c (linkEdit): modifications only for pic16 port,
[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)
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 int aopIdx (asmop *aop, int offset);
62
63 int pic16_labelOffset=0;
64 extern int pic16_debug_verbose;
65 static int optimized_for_speed = 0;
66 /*
67   hack hack
68
69 */
70
71 /* max_key keeps track of the largest label number used in 
72    a function. This is then used to adjust the label offset
73    for the next function.
74 */
75 static int max_key=0;
76 static int GpsuedoStkPtr=0;
77
78 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
79 unsigned int pic16aopLiteral (value *val, int offset);
80 const char *pic16_AopType(short type);
81 static iCode *ifxForOp ( operand *op, iCode *ic );
82
83 void pic16_pushpCodeOp(pCodeOp *pcop);
84 void pic16_poppCodeOp(pCodeOp *pcop);
85
86 static bool is_LitOp(operand *op);
87 static bool is_LitAOp(asmop *aop);
88
89
90 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
91
92 /* this is the down and dirty file with all kinds of 
93    kludgy & hacky stuff. This is what it is all about
94    CODE GENERATION for a specific MCU . some of the
95    routines may be reusable, will have to see */
96
97 static char *zero = "#0x00";
98 static char *one  = "#0x01";
99 static char *spname = "sp";
100
101
102 /*
103  * Function return value policy (MSB-->LSB):
104  *  8 bits      -> WREG
105  * 16 bits      -> PRODL:WREG
106  * 24 bits      -> PRODH:PRODL:WREG
107  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
108  * >32 bits     -> on stack, and FSR0 points to the beginning
109  *
110  */
111  
112
113 char *fReturnpic16[] = {"temp1","temp2","temp3","temp4" };
114 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
115 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
116 static char **fReturn = fReturnpic16;
117
118 static char *accUse[] = {"WREG"};
119
120 //static short rbank = -1;
121
122 static struct {
123     short r0Pushed;
124     short r1Pushed;
125     short accInUse;
126     short inLine;
127     short debugLine;
128     short nRegsSaved;
129     set *sendSet;
130     int interruptvector;
131 } _G;
132
133 /* Resolved ifx structure. This structure stores information
134    about an iCode ifx that makes it easier to generate code.
135 */
136 typedef struct resolvedIfx {
137   symbol *lbl;     /* pointer to a label */
138   int condition;   /* true or false ifx */
139   int generated;   /* set true when the code associated with the ifx
140                     * is generated */
141 } resolvedIfx;
142
143 extern int pic16_ptrRegReq ;
144 extern int pic16_nRegs;
145 extern FILE *codeOutFile;
146 static void saverbank (int, iCode *,bool);
147
148 static lineNode *lineHead = NULL;
149 static lineNode *lineCurr = NULL;
150
151 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
152 0xE0, 0xC0, 0x80, 0x00};
153 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
154 0x07, 0x03, 0x01, 0x00};
155
156 static  pBlock *pb;
157
158 /*-----------------------------------------------------------------*/
159 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
160 /*                 exponent of 2 is returned, otherwise -1 is      */
161 /*                 returned.                                       */
162 /* note that this is similar to the function `powof2' in SDCCsymt  */
163 /* if(n == 2^y)                                                    */
164 /*   return y;                                                     */
165 /* return -1;                                                      */
166 /*-----------------------------------------------------------------*/
167 static int my_powof2 (unsigned long num)
168 {
169   if(num) {
170     if( (num & (num-1)) == 0) {
171       int nshifts = -1;
172       while(num) {
173         num>>=1;
174         nshifts++;
175       }
176       return nshifts;
177     }
178   }
179
180   return -1;
181 }
182
183 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
184 {
185   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
186                        line_no,
187                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
188                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
189                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
190                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
191                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
192                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
193                        ((result) ? AOP_SIZE(result) : 0));
194 }
195
196 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
197 {
198
199   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
200                        line_no,
201                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
202                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
203                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
204                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
205                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
206                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
207
208 }
209
210 void pic16_emitpcomment (char *fmt, ...)
211 {
212     va_list ap;
213     char lb[INITIAL_INLINEASM];  
214     char *lbp = lb;
215
216     va_start(ap,fmt);   
217
218     lb[0] = ';';
219     vsprintf(lb+1,fmt,ap);
220
221     while (isspace(*lbp)) lbp++;
222
223     if (lbp && *lbp) 
224         lineCurr = (lineCurr ?
225                     connectLine(lineCurr,newLineNode(lb)) :
226                     (lineHead = newLineNode(lb)));
227     lineCurr->isInline = _G.inLine;
228     lineCurr->isDebug  = _G.debugLine;
229
230     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
231     va_end(ap);
232
233 //      fprintf(stderr, "%s\n", lb);
234 }
235
236 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
237 {
238     va_list ap;
239     char lb[INITIAL_INLINEASM];  
240     char *lbp = lb;
241
242     if(!pic16_debug_verbose)
243       return;
244
245     va_start(ap,fmt);   
246
247     if (inst && *inst) {
248         if (fmt && *fmt)
249             sprintf(lb,"%s\t",inst);
250         else
251             sprintf(lb,"%s",inst);
252         vsprintf(lb+(strlen(lb)),fmt,ap);
253     }  else
254         vsprintf(lb,fmt,ap);
255
256     while (isspace(*lbp)) lbp++;
257
258     if (lbp && *lbp) 
259         lineCurr = (lineCurr ?
260                     connectLine(lineCurr,newLineNode(lb)) :
261                     (lineHead = newLineNode(lb)));
262     lineCurr->isInline = _G.inLine;
263     lineCurr->isDebug  = _G.debugLine;
264
265     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
266     va_end(ap);
267
268 //      fprintf(stderr, "%s\n", lb);
269 }
270
271 void pic16_emitpLabel(int key)
272 {
273   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
274 }
275
276 void pic16_emitpLabelFORCE(int key)
277 {
278   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
279 }
280
281 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
282 {
283
284   if(pcop)
285     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
286   else
287     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
288     
289 //    fprintf(stderr, "%s\n", pcop->name);
290 }
291
292 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
293 {
294
295   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
296
297 }
298
299
300 #if 1
301 #define pic16_emitcode  DEBUGpic16_emitcode
302 #else
303 /*-----------------------------------------------------------------*/
304 /* pic16_emitcode - writes the code into a file : for now it is simple    */
305 /*-----------------------------------------------------------------*/
306 void pic16_emitcode (char *inst,char *fmt, ...)
307 {
308     va_list ap;
309     char lb[INITIAL_INLINEASM];  
310     char *lbp = lb;
311
312     va_start(ap,fmt);   
313
314     if (inst && *inst) {
315         if (fmt && *fmt)
316             sprintf(lb,"%s\t",inst);
317         else
318             sprintf(lb,"%s",inst);
319         vsprintf(lb+(strlen(lb)),fmt,ap);
320     }  else
321         vsprintf(lb,fmt,ap);
322
323     while (isspace(*lbp)) lbp++;
324
325     if (lbp && *lbp) 
326         lineCurr = (lineCurr ?
327                     connectLine(lineCurr,newLineNode(lb)) :
328                     (lineHead = newLineNode(lb)));
329     lineCurr->isInline = _G.inLine;
330     lineCurr->isDebug  = _G.debugLine;
331
332 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
333
334 //    if(pic16_debug_verbose)
335 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
336
337     va_end(ap);
338 }
339 #endif
340
341
342 /*-----------------------------------------------------------------*/
343 /* pic16_emitDebuggerSymbol - associate the current code location  */
344 /*   with a debugger symbol                                        */
345 /*-----------------------------------------------------------------*/
346 void
347 pic16_emitDebuggerSymbol (char * debugSym)
348 {
349   _G.debugLine = 1;
350   pic16_emitcode (";", "%s ==.", debugSym);
351   _G.debugLine = 0;
352 }
353
354
355 /*-----------------------------------------------------------------*/
356 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
357 /*-----------------------------------------------------------------*/
358 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
359 {
360     bool r0iu = FALSE , r1iu = FALSE;
361     bool r0ou = FALSE , r1ou = FALSE;
362
363     fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
364
365     (*aopp)->type = AOP_STK;    
366     return NULL;
367     /* the logic: if r0 & r1 used in the instruction
368     then we are in trouble otherwise */
369
370     /* first check if r0 & r1 are used by this
371     instruction, in which case we are in trouble */
372     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
373         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
374     {
375         goto endOfWorld;      
376     }
377
378     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
379     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
380
381     /* if no usage of r0 then return it */
382     if (!r0iu && !r0ou) {
383         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
384         (*aopp)->type = AOP_R0;
385         
386         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
387     }
388
389     /* if no usage of r1 then return it */
390     if (!r1iu && !r1ou) {
391         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
392         (*aopp)->type = AOP_R1;
393
394         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
395     }    
396
397     /* now we know they both have usage */
398     /* if r0 not used in this instruction */
399     if (!r0iu) {
400         /* push it if not already pushed */
401         if (!_G.r0Pushed) {
402           //pic16_emitcode ("push","%s",
403           //          pic16_regWithIdx(R0_IDX)->dname);
404             _G.r0Pushed++ ;
405         }
406         
407         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
408         (*aopp)->type = AOP_R0;
409
410         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
411     }
412
413     /* if r1 not used then */
414
415     if (!r1iu) {
416         /* push it if not already pushed */
417         if (!_G.r1Pushed) {
418           //pic16_emitcode ("push","%s",
419           //          pic16_regWithIdx(R1_IDX)->dname);
420             _G.r1Pushed++ ;
421         }
422         
423         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
424         (*aopp)->type = AOP_R1;
425         return pic16_regWithIdx(R1_IDX);
426     }
427
428 endOfWorld :
429     /* I said end of world but not quite end of world yet */
430     /* if this is a result then we can push it on the stack*/
431     if (result) {
432         (*aopp)->type = AOP_STK;    
433         return NULL;
434     }
435
436     /* other wise this is true end of the world */
437     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
438            "getFreePtr should never reach here");
439     exit(0);
440 }
441
442 /*-----------------------------------------------------------------*/
443 /* newAsmop - creates a new asmOp                                  */
444 /*-----------------------------------------------------------------*/
445 static asmop *newAsmop (short type)
446 {
447     asmop *aop;
448
449     aop = Safe_calloc(1,sizeof(asmop));
450     aop->type = type;
451     return aop;
452 }
453
454 static void genSetDPTR(int n)
455 {
456     if (!n)
457     {
458         pic16_emitcode(";", "Select standard DPTR");
459         pic16_emitcode("mov", "dps, #0x00");
460     }
461     else
462     {
463         pic16_emitcode(";", "Select alternate DPTR");
464         pic16_emitcode("mov", "dps, #0x01");
465     }
466 }
467
468 /*-----------------------------------------------------------------*/
469 /* resolveIfx - converts an iCode ifx into a form more useful for  */
470 /*              generating code                                    */
471 /*-----------------------------------------------------------------*/
472 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
473 {
474
475   DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
476
477   if(!resIfx) 
478     return;
479
480
481   resIfx->condition = 1;    /* assume that the ifx is true */
482   resIfx->generated = 0;    /* indicate that the ifx has not been used */
483
484   if(!ifx) {
485     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
486
487 #if 1
488     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
489                         __FUNCTION__,__LINE__,resIfx->lbl->key);
490 #endif
491
492   } else {
493     if(IC_TRUE(ifx)) {
494       resIfx->lbl = IC_TRUE(ifx);
495     } else {
496       resIfx->lbl = IC_FALSE(ifx);
497       resIfx->condition = 0;
498     }
499
500 #if 1
501     if(IC_TRUE(ifx)) 
502       DEBUGpic16_emitcode("; ***","ifx true is non-null");
503     if(IC_FALSE(ifx)) 
504       DEBUGpic16_emitcode("; ***","ifx false is non-null");
505 #endif
506   }
507
508   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
509
510 }
511 #if 0
512 /*-----------------------------------------------------------------*/
513 /* pointerCode - returns the code for a pointer type               */
514 /*-----------------------------------------------------------------*/
515 static int pointerCode (sym_link *etype)
516 {
517
518     return PTR_TYPE(SPEC_OCLS(etype));
519
520 }
521 #endif
522
523 /*-----------------------------------------------------------------*/
524 /* aopForSym - for a true symbol                                   */
525 /*-----------------------------------------------------------------*/
526 static asmop *aopForSym (iCode *ic, operand *op, bool result)
527 {
528     symbol *sym=OP_SYMBOL(op);
529     asmop *aop;
530     memmap *space= SPEC_OCLS(sym->etype);
531
532     DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
533
534 //    sym = OP_SYMBOL(op);
535
536     /* if already has one */
537     if (sym->aop) {
538             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
539         return sym->aop;
540     }
541
542     /* if symbol was initially placed onStack then we must re-place it
543      * to direct memory, since pic16 does not have a specific stack */
544     if(sym->onStack) {
545         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
546 #if 0
547         sym->onStack = 0;
548         SPEC_OCLS( sym->etype ) = data;
549         space = data;
550 #endif
551     }
552
553
554 #if 0
555     /* assign depending on the storage class */
556     /* if it is on the stack or indirectly addressable */
557     /* space we need to assign either r0 or r1 to it   */    
558     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
559
560         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
561                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
562         
563 //        sym->aop = aop = newAsmop(0);
564 //        aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
565 //        aop->size = getSize(sym->type);
566
567         fprintf(stderr, "%s:%d\t%s\n", __FILE__, __LINE__, __FUNCTION__);
568
569         sym->aop = aop = newAsmop (AOP_REG);
570 //        aop->aopu.aop_dir = sym->name;        //sym->rname ;
571         aop->aopu.aop_reg[0] = pic16_regWithIdx(IDX_PLUSW2);    //pic16_pc_plusw2.r;
572         aop->size = getSize(sym->type);
573         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
574         
575         /* initialise for stack access via frame pointer */
576         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
577         
578         
579 //      if(IC_LEFT(ic))pic16_allocDirReg( IC_LEFT(ic) );
580 //      else if(IC_RIGHT(ic))pic16_allocDirReg(IC_RIGHT(ic));
581         
582         return (aop);
583
584         /* now assign the address of the variable to 
585         the pointer register */
586         if (aop->type != AOP_STK) {
587
588             if (sym->onStack) {
589                     if ( _G.accInUse )
590                         pic16_emitcode("push","acc");
591
592                     pic16_emitcode("mov","a,_bp");
593                     pic16_emitcode("add","a,#0x%02x",
594                              ((sym->stack < 0) ?
595                               ((char)(sym->stack - _G.nRegsSaved )) :
596                               ((char)sym->stack)) & 0xff);
597                     pic16_emitcode("mov","%s,a",
598                              aop->aopu.aop_ptr->name);
599
600                     if ( _G.accInUse )
601                         pic16_emitcode("pop","acc");
602             } else
603                 pic16_emitcode("mov","%s,#%s",
604                          aop->aopu.aop_ptr->name,
605                          sym->rname);
606             aop->paged = space->paged;
607         } else
608             aop->aopu.aop_stk = sym->stack;
609         return aop;
610     }
611 #endif
612
613 #if 0
614     if (sym->onStack && options.stack10bit)
615     {
616         /* It's on the 10 bit stack, which is located in
617          * far data space.
618          */
619          
620       //DEBUGpic16_emitcode(";","%d",__LINE__);
621
622         if ( _G.accInUse )
623                 pic16_emitcode("push","acc");
624
625         pic16_emitcode("mov","a,_bp");
626         pic16_emitcode("add","a,#0x%02x",
627                  ((sym->stack < 0) ?
628                    ((char)(sym->stack - _G.nRegsSaved )) :
629                    ((char)sym->stack)) & 0xff);
630         
631         genSetDPTR(1);
632         pic16_emitcode ("mov","dpx1,#0x40");
633         pic16_emitcode ("mov","dph1,#0x00");
634         pic16_emitcode ("mov","dpl1, a");
635         genSetDPTR(0);
636         
637         if ( _G.accInUse )
638             pic16_emitcode("pop","acc");
639             
640         sym->aop = aop = newAsmop(AOP_DPTR2);
641         aop->size = getSize(sym->type); 
642         return aop;
643     }
644 #endif
645     //DEBUGpic16_emitcode(";","%d",__LINE__);
646     /* if in bit space */
647     if (IN_BITSPACE(space)) {
648         sym->aop = aop = newAsmop (AOP_CRY);
649         aop->aopu.aop_dir = sym->rname ;
650         aop->size = getSize(sym->type);
651         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
652         return aop;
653     }
654     /* if it is in direct space */
655     if (IN_DIRSPACE(space)) {
656         sym->aop = aop = newAsmop (AOP_DIR);
657         aop->aopu.aop_dir = sym->rname ;
658         aop->size = getSize(sym->type);
659         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
660         pic16_allocDirReg( IC_LEFT(ic) );
661         return aop;
662     }
663
664 #if 0                                                                                           // patch 14
665     /* special case for a function */
666     if (IS_FUNC(sym->type)) {   
667         sym->aop = aop = newAsmop(AOP_IMMD);    
668         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
669         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
670         strcpy(aop->aopu.aop_immd,sym->rname);
671         aop->size = FPTRSIZE; 
672         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
673         return aop;
674     }
675 #endif                                                                                          // patch 14
676
677
678     /* only remaining is far space */
679     /* in which case DPTR gets the address */
680     sym->aop = aop = newAsmop(AOP_PCODE);
681
682 /* change the next if to 1 to revert to good old immediate code */
683         if(IN_CODESPACE(space)) {
684                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
685                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
686                 PCOI(aop->aopu.pcop)->index = 0;
687         } else {
688                 /* try to allocate via direct register */
689                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
690 //              aop->size = getSize( sym->type );
691         }
692
693         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
694                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
695
696 #if 0
697         if(!pic16_allocDirReg (IC_LEFT(ic)))
698                 return NULL;
699 #endif
700
701         if(IN_DIRSPACE( space ))
702                 aop->size = PTRSIZE;
703         else if(IN_CODESPACE( space ))
704                 aop->size = FPTRSIZE;
705         else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
706         else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
707         else {
708                 assert( 0 );
709         }
710
711     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
712
713     /* if it is in code space */
714     if (IN_CODESPACE(space))
715         aop->code = 1;
716
717     return aop;     
718 }
719
720 /*-----------------------------------------------------------------*/
721 /* aopForRemat - rematerialzes an object                           */
722 /*-----------------------------------------------------------------*/
723 static asmop *aopForRemat (operand *op) // x symbol *sym)
724 {
725   symbol *sym = OP_SYMBOL(op);
726   iCode *ic = NULL, *oldic;
727   asmop *aop = newAsmop(AOP_PCODE);
728   int val = 0;
729   int offset = 0;
730   int viaimmd=0;
731
732
733         ic = sym->rematiCode;
734
735         DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
736         
737         if(IS_OP_POINTER(op)) {
738                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
739         }
740
741         for (;;) {
742                 oldic = ic;
743
744 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
745         
746                 if (ic->op == '+') {
747                         val += (int) operandLitValue(IC_RIGHT(ic));
748                 } else if (ic->op == '-') {
749                         val -= (int) operandLitValue(IC_RIGHT(ic));
750                 } else
751                         break;
752                 
753                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
754         }
755
756         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
757
758         if(!op->isaddr)viaimmd++; else viaimmd=0;
759                 
760 /* set the following if to 1 to revert to good old immediate code */
761         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))
762                 || viaimmd) {
763
764                 DEBUGpic16_emitcode("%s:%d immediate", __FILE__, __LINE__);
765
766                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
767
768 #if 0
769                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
770 #else
771                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
772 #endif
773
774                 PCOI(aop->aopu.pcop)->index = val;
775         } else {
776                 DEBUGpic16_emitcode("%s:%d dir", __FILE__, __LINE__);
777
778                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
779                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
780 //              aop->size = AOP_SIZE( IC_LEFT(ic) );
781         }
782
783
784         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
785                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
786 #if 0
787                 val, IS_PTR_CONST(operandType(op)));
788 #else
789                 val, IS_CODEPTR(operandType(op)));
790 #endif
791
792 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
793
794         pic16_allocDirReg (IC_LEFT(ic));
795
796         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
797                 aop->code = 1;
798
799   return aop;        
800 }
801
802 static int aopIdx (asmop *aop, int offset)
803 {
804   if(!aop)
805     return -1;
806
807   if(aop->type !=  AOP_REG)
808     return -2;
809         
810   return aop->aopu.aop_reg[offset]->rIdx;
811
812 }
813 /*-----------------------------------------------------------------*/
814 /* regsInCommon - two operands have some registers in common       */
815 /*-----------------------------------------------------------------*/
816 static bool regsInCommon (operand *op1, operand *op2)
817 {
818     symbol *sym1, *sym2;
819     int i;
820
821     /* if they have registers in common */
822     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
823         return FALSE ;
824
825     sym1 = OP_SYMBOL(op1);
826     sym2 = OP_SYMBOL(op2);
827
828     if (sym1->nRegs == 0 || sym2->nRegs == 0)
829         return FALSE ;
830
831     for (i = 0 ; i < sym1->nRegs ; i++) {
832         int j;
833         if (!sym1->regs[i])
834             continue ;
835
836         for (j = 0 ; j < sym2->nRegs ;j++ ) {
837             if (!sym2->regs[j])
838                 continue ;
839
840             if (sym2->regs[j] == sym1->regs[i])
841                 return TRUE ;
842         }
843     }
844
845     return FALSE ;
846 }
847
848 /*-----------------------------------------------------------------*/
849 /* operandsEqu - equivalent                                        */
850 /*-----------------------------------------------------------------*/
851 static bool operandsEqu ( operand *op1, operand *op2)
852 {
853     symbol *sym1, *sym2;
854
855     /* if they not symbols */
856     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
857         return FALSE;
858
859     sym1 = OP_SYMBOL(op1);
860     sym2 = OP_SYMBOL(op2);
861
862     /* if both are itemps & one is spilt
863        and the other is not then false */
864     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
865         sym1->isspilt != sym2->isspilt )
866         return FALSE ;
867
868     /* if they are the same */
869     if (sym1 == sym2)
870         return TRUE ;
871
872     if (sym1->rname[0] && sym2->rname[0]
873         && strcmp (sym1->rname, sym2->rname) == 0)
874         return TRUE;
875
876
877     /* if left is a tmp & right is not */
878     if (IS_ITEMP(op1)  && 
879         !IS_ITEMP(op2) &&
880         sym1->isspilt  &&
881         (sym1->usl.spillLoc == sym2))
882         return TRUE;
883
884     if (IS_ITEMP(op2)  && 
885         !IS_ITEMP(op1) &&
886         sym2->isspilt  &&
887         sym1->level > 0 &&
888         (sym2->usl.spillLoc == sym1))
889         return TRUE ;
890
891     return FALSE ;
892 }
893
894 /*-----------------------------------------------------------------*/
895 /* pic16_sameRegs - two asmops have the same registers                   */
896 /*-----------------------------------------------------------------*/
897 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
898 {
899     int i;
900
901     if (aop1 == aop2)
902         return TRUE ;
903
904     if (aop1->type != AOP_REG ||
905         aop2->type != AOP_REG )
906         return FALSE ;
907
908     if (aop1->size != aop2->size )
909         return FALSE ;
910
911     for (i = 0 ; i < aop1->size ; i++ )
912         if (aop1->aopu.aop_reg[i] !=
913             aop2->aopu.aop_reg[i] )
914             return FALSE ;
915
916     return TRUE ;
917 }
918
919 /*-----------------------------------------------------------------*/
920 /* pic16_aopOp - allocates an asmop for an operand  :                    */
921 /*-----------------------------------------------------------------*/
922 void pic16_aopOp (operand *op, iCode *ic, bool result)
923 {
924     asmop *aop;
925     symbol *sym;
926     int i;
927
928     if (!op)
929         return ;
930
931 //      DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
932
933     /* if this a literal */
934     if (IS_OP_LITERAL(op)) {
935         op->aop = aop = newAsmop(AOP_LIT);
936         aop->aopu.aop_lit = op->operand.valOperand;
937         aop->size = getSize(operandType(op));
938         return;
939     }
940
941     {
942       sym_link *type = operandType(op);
943 #if 0
944       if(IS_PTR_CONST(type))
945 #else
946       if(IS_CODEPTR(type))
947 #endif
948         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
949     }
950
951     /* if already has a asmop then continue */
952     if (op->aop)
953         return ;
954
955     /* if the underlying symbol has a aop */
956     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
957       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
958         op->aop = OP_SYMBOL(op)->aop;
959         return;
960     }
961
962     /* if this is a true symbol */
963     if (IS_TRUE_SYMOP(op)) {    
964         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
965       op->aop = aopForSym(ic, op, result);
966       return ;
967     }
968
969     /* this is a temporary : this has
970     only four choices :
971     a) register
972     b) spillocation
973     c) rematerialize 
974     d) conditional   
975     e) can be a return use only */
976
977     sym = OP_SYMBOL(op);
978
979         DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
980     /* if the type is a conditional */
981     if (sym->regType == REG_CND) {
982         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
983         aop->size = 0;
984         return;
985     }
986
987     /* if it is spilt then two situations
988     a) is rematerialize 
989     b) has a spill location */
990     if (sym->isspilt || sym->nRegs == 0) {
991
992       DEBUGpic16_emitcode(";","%d",__LINE__);
993         /* rematerialize it NOW */
994         if (sym->remat) {
995
996             sym->aop = op->aop = aop =
997                                       aopForRemat (op);
998             aop->size = getSize(sym->type);
999             //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1000             return;
1001         }
1002
1003 #if 1
1004         if (sym->accuse) {
1005             int i;
1006             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1007             aop->size = getSize(sym->type);
1008             for ( i = 0 ; i < 1 ; i++ ) {
1009                 aop->aopu.aop_str[i] = accUse[i];
1010 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1011             }
1012             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1013             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1014             return;  
1015         }
1016 #endif
1017
1018 #if 1
1019         if (sym->ruonly ) {
1020           /*
1021           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1022           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1023           //pic16_allocDirReg (IC_LEFT(ic));
1024           aop->size = getSize(sym->type);
1025           */
1026
1027           unsigned i;
1028
1029           aop = op->aop = sym->aop = newAsmop(AOP_STR);
1030           aop->size = getSize(sym->type);
1031           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1032             aop->aopu.aop_str[i] = fReturn[i];
1033
1034           DEBUGpic16_emitcode(";","%d",__LINE__);
1035           return;
1036         }
1037 #endif
1038         /* else spill location  */
1039         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1040             /* force a new aop if sizes differ */
1041             sym->usl.spillLoc->aop = NULL;
1042         }
1043         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1044                             __FUNCTION__,__LINE__,
1045                             sym->usl.spillLoc->rname,
1046                             sym->rname, sym->usl.spillLoc->offset);
1047
1048         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1049         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1050         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1051                                           getSize(sym->type), 
1052                                           sym->usl.spillLoc->offset, op);
1053         aop->size = getSize(sym->type);
1054
1055         return;
1056     }
1057
1058     {
1059       sym_link *type = operandType(op);
1060 #if 0
1061       if(IS_PTR_CONST(type)) 
1062 #else
1063       if(IS_CODEPTR(type)) 
1064 #endif
1065         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1066     }
1067
1068     /* must be in a register */
1069     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1070     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1071     aop->size = sym->nRegs;
1072     for ( i = 0 ; i < sym->nRegs ;i++)
1073         aop->aopu.aop_reg[i] = sym->regs[i];
1074 }
1075
1076 /*-----------------------------------------------------------------*/
1077 /* pic16_freeAsmop - free up the asmop given to an operand               */
1078 /*----------------------------------------------------------------*/
1079 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1080 {   
1081     asmop *aop ;
1082
1083     if (!op)
1084         aop = aaop;
1085     else 
1086         aop = op->aop;
1087
1088     if (!aop)
1089         return ;
1090
1091     if (aop->freed)
1092         goto dealloc; 
1093
1094     aop->freed = 1;
1095
1096     /* depending on the asmop type only three cases need work AOP_RO
1097        , AOP_R1 && AOP_STK */
1098 #if 0
1099     switch (aop->type) {
1100         case AOP_R0 :
1101             if (_G.r0Pushed ) {
1102                 if (pop) {
1103                     pic16_emitcode ("pop","ar0");     
1104                     _G.r0Pushed--;
1105                 }
1106             }
1107             bitVectUnSetBit(ic->rUsed,R0_IDX);
1108             break;
1109
1110         case AOP_R1 :
1111             if (_G.r1Pushed ) {
1112                 if (pop) {
1113                     pic16_emitcode ("pop","ar1");
1114                     _G.r1Pushed--;
1115                 }
1116             }
1117             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1118             break;
1119
1120         case AOP_STK :
1121         {
1122             int sz = aop->size;    
1123             int stk = aop->aopu.aop_stk + aop->size;
1124             bitVectUnSetBit(ic->rUsed,R0_IDX);
1125             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1126
1127             getFreePtr(ic,&aop,FALSE);
1128             
1129             if (options.stack10bit)
1130             {
1131                 /* I'm not sure what to do here yet... */
1132                 /* #STUB */
1133                 fprintf(stderr, 
1134                         "*** Warning: probably generating bad code for "
1135                         "10 bit stack mode.\n");
1136             }
1137             
1138             if (stk) {
1139                 pic16_emitcode ("mov","a,_bp");
1140                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1141                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1142             } else {
1143                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1144             }
1145
1146             while (sz--) {
1147                 pic16_emitcode("pop","acc");
1148                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1149                 if (!sz) break;
1150                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1151             }
1152             op->aop = aop;
1153             pic16_freeAsmop(op,NULL,ic,TRUE);
1154             if (_G.r0Pushed) {
1155                 pic16_emitcode("pop","ar0");
1156                 _G.r0Pushed--;
1157             }
1158
1159             if (_G.r1Pushed) {
1160                 pic16_emitcode("pop","ar1");
1161                 _G.r1Pushed--;
1162             }       
1163         }
1164     }
1165 #endif
1166
1167 dealloc:
1168     /* all other cases just dealloc */
1169     if (op ) {
1170         op->aop = NULL;
1171         if (IS_SYMOP(op)) {
1172             OP_SYMBOL(op)->aop = NULL;    
1173             /* if the symbol has a spill */
1174             if (SPIL_LOC(op))
1175                 SPIL_LOC(op)->aop = NULL;
1176         }
1177     }
1178 }
1179
1180 /*-----------------------------------------------------------------*/
1181 /* pic16_aopGet - for fetching value of the aop                          */
1182 /*-----------------------------------------------------------------*/
1183 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1184 {
1185     char *s = buffer ;
1186     char *rs;
1187
1188     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1189
1190     /* offset is greater than size then zero */
1191     if (offset > (aop->size - 1) &&
1192         aop->type != AOP_LIT)
1193         return zero;
1194
1195     /* depending on type */
1196     switch (aop->type) {
1197         
1198     case AOP_IMMD:
1199         if (bit16) 
1200             sprintf (s,"%s",aop->aopu.aop_immd);
1201         else
1202             if (offset) 
1203                 sprintf(s,"(%s >> %d)",
1204                         aop->aopu.aop_immd,
1205                         offset*8);
1206             else
1207                 sprintf(s,"%s",
1208                         aop->aopu.aop_immd);
1209         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1210         rs = Safe_calloc(1,strlen(s)+1);
1211         strcpy(rs,s);   
1212         return rs;
1213         
1214     case AOP_DIR:
1215       if (offset) {
1216         sprintf(s,"(%s + %d)",
1217                 aop->aopu.aop_dir,
1218                 offset);
1219         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1220       } else
1221             sprintf(s,"%s",aop->aopu.aop_dir);
1222         rs = Safe_calloc(1,strlen(s)+1);
1223         strcpy(rs,s);   
1224         return rs;
1225         
1226     case AOP_REG:
1227       //if (dname) 
1228       //    return aop->aopu.aop_reg[offset]->dname;
1229       //else
1230             return aop->aopu.aop_reg[offset]->name;
1231         
1232     case AOP_CRY:
1233       //pic16_emitcode(";","%d",__LINE__);
1234       return aop->aopu.aop_dir;
1235         
1236     case AOP_ACC:
1237         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1238 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1239 //        assert( 0 );
1240         return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1241
1242     case AOP_LIT:
1243         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1244         rs = Safe_calloc(1,strlen(s)+1);
1245         strcpy(rs,s);   
1246         return rs;
1247         
1248     case AOP_STR:
1249         aop->coff = offset ;
1250         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1251             dname)
1252             return "acc";
1253         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1254         
1255         return aop->aopu.aop_str[offset];
1256         
1257     case AOP_PCODE:
1258       {
1259         pCodeOp *pcop = aop->aopu.pcop;
1260         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1261         if(pcop->name) {
1262           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1263           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1264           sprintf(s,"%s", pcop->name);
1265         } else
1266           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1267
1268       }
1269       rs = Safe_calloc(1,strlen(s)+1);
1270       strcpy(rs,s);   
1271       return rs;
1272
1273       case AOP_STK:
1274 //        pCodeOp *pcop = aop->aop
1275         break;
1276
1277     }
1278
1279     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1280     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1281            "aopget got unsupported aop->type");
1282     exit(0);
1283 }
1284
1285
1286 /*-----------------------------------------------------------------*/
1287 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1288 /*-----------------------------------------------------------------*/
1289 pCodeOp *pic16_popGetTempReg(void)
1290 {
1291   pCodeOp *pcop;
1292   symbol *cfunc;
1293
1294 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1295
1296         cfunc = currFunc;
1297         currFunc = NULL;
1298
1299         pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1300         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1301                 PCOR(pcop)->r->wasUsed=1;
1302                 PCOR(pcop)->r->isFree=0;
1303
1304                 /* push value on stack */
1305                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1306         }
1307
1308         currFunc = cfunc;
1309
1310   return pcop;
1311 }
1312
1313 /*-----------------------------------------------------------------*/
1314 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1315 /*-----------------------------------------------------------------*/
1316 void pic16_popReleaseTempReg(pCodeOp *pcop)
1317 {
1318         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1319
1320         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1321                 PCOR(pcop)->r->isFree = 1;
1322                 
1323                 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1324         }
1325 }
1326 /*-----------------------------------------------------------------*/
1327 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1328 /*-----------------------------------------------------------------*/
1329 pCodeOp *pic16_popGetLabel(unsigned int key)
1330 {
1331
1332   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1333
1334   if(key>max_key)
1335     max_key = key;
1336
1337   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1338 }
1339
1340 /*-----------------------------------------------------------------*/
1341 /* pic16_popCopyReg - copy a pcode operator                              */
1342 /*-----------------------------------------------------------------*/
1343 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1344 {
1345   pCodeOpReg *pcor;
1346
1347   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1348   pcor->pcop.type = pc->pcop.type;
1349   if(pc->pcop.name) {
1350     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1351       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1352   } else
1353     pcor->pcop.name = NULL;
1354
1355   pcor->r = pc->r;
1356   pcor->rIdx = pc->rIdx;
1357   pcor->r->wasUsed=1;
1358
1359 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1360
1361   return PCOP(pcor);
1362 }
1363
1364 /*-----------------------------------------------------------------*/
1365 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1366 /*-----------------------------------------------------------------*/
1367 pCodeOp *pic16_popGetLit(unsigned int lit)
1368 {
1369   return pic16_newpCodeOpLit(lit);
1370 }
1371
1372 /*-----------------------------------------------------------------*/
1373 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1374 /*-----------------------------------------------------------------*/
1375 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1376 {
1377   return pic16_newpCodeOpLit2(lit, arg2);
1378 }
1379
1380
1381 /*-----------------------------------------------------------------*/
1382 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1383 /*-----------------------------------------------------------------*/
1384 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1385 {
1386   return pic16_newpCodeOpImmd(name, offset,index, 0);
1387 }
1388
1389
1390 /*-----------------------------------------------------------------*/
1391 /* pic16_popGet - asm operator to pcode operator conversion              */
1392 /*-----------------------------------------------------------------*/
1393 pCodeOp *pic16_popGetWithString(char *str)
1394 {
1395   pCodeOp *pcop;
1396
1397
1398   if(!str) {
1399     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1400     exit (1);
1401   }
1402
1403   pcop = pic16_newpCodeOp(str,PO_STR);
1404
1405   return pcop;
1406 }
1407
1408 /*-----------------------------------------------------------------*/
1409 /* pic16_popRegFromString -                                        */
1410 /*-----------------------------------------------------------------*/
1411 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1412 {
1413
1414   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1415   pcop->type = PO_DIR;
1416
1417   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1418   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1419
1420   if(!str)
1421     str = "BAD_STRING";
1422
1423   pcop->name = Safe_calloc(1,strlen(str)+1);
1424   strcpy(pcop->name,str);
1425
1426   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1427
1428   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1429   if(PCOR(pcop)->r == NULL) {
1430 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1431 //              __FUNCTION__, __LINE__, str, size, offset);
1432     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1433
1434         //fprintf(stderr, "allocating new register -> %s\n", str);
1435
1436 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d - had to alloc by reg name",__LINE__,pcop->name,size,offset);
1437   } else {
1438 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d",__LINE__,pcop->name,size,offset);
1439   }
1440   PCOR(pcop)->instance = offset;
1441
1442   return pcop;
1443 }
1444
1445 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1446 {
1447   pCodeOp *pcop;
1448
1449 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1450
1451         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1452         PCOR(pcop)->rIdx = rIdx;
1453         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1454
1455         PCOR(pcop)->r->isFree = 0;
1456         PCOR(pcop)->r->wasUsed = 1;
1457
1458         pcop->type = PCOR(pcop)->r->pc_type;
1459
1460   return pcop;
1461 }
1462
1463 /*---------------------------------------------------------------------------------*/
1464 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1465 /*                 VR 030601                                                       */
1466 /*---------------------------------------------------------------------------------*/
1467 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1468 {
1469   pCodeOpReg2 *pcop2;
1470   pCodeOp *temp;
1471   
1472         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1473
1474         /* comment the following check, so errors to throw up */
1475 //      if(!pcop2)return NULL;
1476
1477         temp = pic16_popGet(aop_dst, offset);
1478         pcop2->pcop2 = temp;
1479         
1480   return PCOP(pcop2);
1481 }
1482
1483
1484
1485 /*--------------------------------------------------------------------------------.-*/
1486 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1487 /*                  VR 030601 , adapted by Hans Dorn                                */
1488 /*--------------------------------------------------------------------------------.-*/
1489 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1490 {
1491   pCodeOpReg2 *pcop2;
1492  
1493         pcop2 = (pCodeOpReg2 *)src;
1494         pcop2->pcop2 = dst;
1495         
1496         return PCOP(pcop2);
1497 }
1498
1499
1500
1501 /*---------------------------------------------------------------------------------*/
1502 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1503 /*                     movff instruction                                           */
1504 /*---------------------------------------------------------------------------------*/
1505 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1506 {
1507   pCodeOpReg2 *pcop2;
1508
1509         if(!noalloc) {
1510                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1511                 pcop2->pcop2 = pic16_popCopyReg(dst);
1512         } else {
1513                 /* the pCodeOp may be already allocated */
1514                 pcop2 = (pCodeOpReg2 *)(src);
1515                 pcop2->pcop2 = (pCodeOp *)(dst);
1516         }
1517
1518   return PCOP(pcop2);
1519 }
1520
1521
1522 /*-----------------------------------------------------------------*/
1523 /* pic16_popGet - asm operator to pcode operator conversion              */
1524 /*-----------------------------------------------------------------*/
1525 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1526 {
1527   //char *s = buffer ;
1528   char *rs;
1529   pCodeOp *pcop;
1530
1531     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1532     /* offset is greater than
1533     size then zero */
1534
1535 //    if (offset > (aop->size - 1) &&
1536 //        aop->type != AOP_LIT)
1537 //      return NULL;  //zero;
1538
1539     /* depending on type */
1540     switch (aop->type) {
1541         
1542     case AOP_R0:
1543     case AOP_R1:
1544     case AOP_DPTR:
1545     case AOP_DPTR2:
1546         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1547         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1548         assert( 0 );
1549         return NULL;
1550
1551
1552
1553     case AOP_IMMD:
1554       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1555       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1556
1557     case AOP_ACC:
1558       {
1559         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1560
1561         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1562
1563         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1564         
1565         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1566         PCOR(pcop)->rIdx = rIdx;
1567         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1568         PCOR(pcop)->r->wasUsed=1;
1569         PCOR(pcop)->r->isFree=0;
1570
1571         PCOR(pcop)->instance = offset;
1572         pcop->type = PCOR(pcop)->r->pc_type;
1573 //      rs = aop->aopu.aop_reg[offset]->name;
1574 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1575         return pcop;
1576
1577
1578 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1579 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1580
1581 //      assert( 0 );
1582       }
1583         
1584     case AOP_DIR:
1585       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1586       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1587         
1588     case AOP_REG:
1589       {
1590         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1591
1592         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1593         
1594         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1595 //      pcop->type = PO_GPR_REGISTER;
1596         PCOR(pcop)->rIdx = rIdx;
1597         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1598         PCOR(pcop)->r->wasUsed=1;
1599         PCOR(pcop)->r->isFree=0;
1600
1601         PCOR(pcop)->instance = offset;
1602         pcop->type = PCOR(pcop)->r->pc_type;
1603         rs = aop->aopu.aop_reg[offset]->name;
1604         DEBUGpic16_emitcode(";","%d regiser idx = %d name = %s",__LINE__,rIdx,rs);
1605         return pcop;
1606       }
1607
1608     case AOP_CRY:
1609         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1610
1611       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1612       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1613       //if(PCOR(pcop)->r == NULL)
1614       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1615       return pcop;
1616         
1617     case AOP_LIT:
1618         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1619       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1620
1621     case AOP_STR:
1622       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1623       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1624
1625       /*
1626       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1627       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1628       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1629       pcop->type = PCOR(pcop)->r->pc_type;
1630       pcop->name = PCOR(pcop)->r->name;
1631
1632       return pcop;
1633       */
1634
1635     case AOP_PCODE:
1636       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1637                           __LINE__, 
1638                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1639       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1640 #if 1
1641         switch( aop->aopu.pcop->type ) {
1642                 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1643                 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1644                 default:
1645                         assert( 0 );    /* should never reach here */;
1646         }
1647 #else
1648       PCOI(pcop)->offset = offset;
1649 #endif
1650       return pcop;
1651     }
1652
1653     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1654            "pic16_popGet got unsupported aop->type");
1655     exit(0);
1656 }
1657 /*-----------------------------------------------------------------*/
1658 /* pic16_aopPut - puts a string for a aop                                */
1659 /*-----------------------------------------------------------------*/
1660 void pic16_aopPut (asmop *aop, char *s, int offset)
1661 {
1662     char *d = buffer ;
1663     symbol *lbl ;
1664
1665     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1666
1667     if (aop->size && offset > ( aop->size - 1)) {
1668         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1669                "pic16_aopPut got offset > aop->size");
1670         exit(0);
1671     }
1672
1673     /* will assign value to value */
1674     /* depending on where it is ofcourse */
1675     switch (aop->type) {
1676     case AOP_DIR:
1677       if (offset) {
1678         sprintf(d,"(%s + %d)",
1679                 aop->aopu.aop_dir,offset);
1680         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1681
1682       } else
1683             sprintf(d,"%s",aop->aopu.aop_dir);
1684         
1685         if (strcmp(d,s)) {
1686           DEBUGpic16_emitcode(";","%d",__LINE__);
1687           if(strcmp(s,"W"))
1688             pic16_emitcode("movf","%s,w",s);
1689           pic16_emitcode("movwf","%s",d);
1690
1691           if(strcmp(s,"W")) {
1692             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1693             if(offset >= aop->size) {
1694               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1695               break;
1696             } else
1697               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1698           }
1699
1700           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1701
1702
1703         }
1704         break;
1705         
1706     case AOP_REG:
1707       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1708         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1709           /*
1710             if (*s == '@'           ||
1711                 strcmp(s,"r0") == 0 ||
1712                 strcmp(s,"r1") == 0 ||
1713                 strcmp(s,"r2") == 0 ||
1714                 strcmp(s,"r3") == 0 ||
1715                 strcmp(s,"r4") == 0 ||
1716                 strcmp(s,"r5") == 0 ||
1717                 strcmp(s,"r6") == 0 || 
1718                 strcmp(s,"r7") == 0 )
1719                 pic16_emitcode("mov","%s,%s  ; %d",
1720                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1721             else
1722           */
1723
1724           if(strcmp(s,"W")==0 )
1725             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
1726
1727           pic16_emitcode("movwf","%s",
1728                    aop->aopu.aop_reg[offset]->name);
1729
1730           if(strcmp(s,zero)==0) {
1731             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1732
1733           } else if(strcmp(s,"W")==0) {
1734             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1735             pcop->type = PO_GPR_REGISTER;
1736
1737             PCOR(pcop)->rIdx = -1;
1738             PCOR(pcop)->r = NULL;
1739
1740             DEBUGpic16_emitcode(";","%d",__LINE__);
1741             pcop->name = Safe_strdup(s);
1742             pic16_emitpcode(POC_MOVFW,pcop);
1743             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1744           } else if(strcmp(s,one)==0) {
1745             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1746             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1747           } else {
1748             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1749           }
1750         }
1751         break;
1752         
1753     case AOP_DPTR:
1754     case AOP_DPTR2:
1755     
1756     if (aop->type == AOP_DPTR2)
1757     {
1758         genSetDPTR(1);
1759     }
1760     
1761         if (aop->code) {
1762             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1763                    "pic16_aopPut writting to code space");
1764             exit(0);
1765         }
1766         
1767         while (offset > aop->coff) {
1768             aop->coff++;
1769             pic16_emitcode ("inc","dptr");
1770         }
1771         
1772         while (offset < aop->coff) {
1773             aop->coff-- ;
1774             pic16_emitcode("lcall","__decdptr");
1775         }
1776         
1777         aop->coff = offset;
1778         
1779         /* if not in accumulater */
1780         MOVA(s);        
1781         
1782         pic16_emitcode ("movx","@dptr,a");
1783         
1784     if (aop->type == AOP_DPTR2)
1785     {
1786         genSetDPTR(0);
1787     }
1788         break;
1789         
1790     case AOP_R0:
1791     case AOP_R1:
1792         while (offset > aop->coff) {
1793             aop->coff++;
1794             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1795         }
1796         while (offset < aop->coff) {
1797             aop->coff-- ;
1798             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1799         }
1800         aop->coff = offset;
1801         
1802         if (aop->paged) {
1803             MOVA(s);           
1804             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1805             
1806         } else
1807             if (*s == '@') {
1808                 MOVA(s);
1809                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1810             } else
1811                 if (strcmp(s,"r0") == 0 ||
1812                     strcmp(s,"r1") == 0 ||
1813                     strcmp(s,"r2") == 0 ||
1814                     strcmp(s,"r3") == 0 ||
1815                     strcmp(s,"r4") == 0 ||
1816                     strcmp(s,"r5") == 0 ||
1817                     strcmp(s,"r6") == 0 || 
1818                     strcmp(s,"r7") == 0 ) {
1819                     char buffer[10];
1820                     sprintf(buffer,"a%s",s);
1821                     pic16_emitcode("mov","@%s,%s",
1822                              aop->aopu.aop_ptr->name,buffer);
1823                 } else
1824                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1825         
1826         break;
1827         
1828     case AOP_STK:
1829         if (strcmp(s,"a") == 0)
1830             pic16_emitcode("push","acc");
1831         else
1832             pic16_emitcode("push","%s",s);
1833         
1834         break;
1835         
1836     case AOP_CRY:
1837         /* if bit variable */
1838         if (!aop->aopu.aop_dir) {
1839             pic16_emitcode("clr","a");
1840             pic16_emitcode("rlc","a");
1841         } else {
1842             if (s == zero) 
1843                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1844             else
1845                 if (s == one)
1846                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1847                 else
1848                     if (!strcmp(s,"c"))
1849                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1850                     else {
1851                         lbl = newiTempLabel(NULL);
1852                         
1853                         if (strcmp(s,"a")) {
1854                             MOVA(s);
1855                         }
1856                         pic16_emitcode("clr","c");
1857                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1858                         pic16_emitcode("cpl","c");
1859                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
1860                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1861                     }
1862         }
1863         break;
1864         
1865     case AOP_STR:
1866         aop->coff = offset;
1867         if (strcmp(aop->aopu.aop_str[offset],s))
1868             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1869         break;
1870         
1871     case AOP_ACC:
1872         aop->coff = offset;
1873         if (!offset && (strcmp(s,"acc") == 0))
1874             break;
1875         
1876         if (strcmp(aop->aopu.aop_str[offset],s))
1877             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1878         break;
1879
1880     default :
1881         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1882                "pic16_aopPut got unsupported aop->type");
1883         exit(0);    
1884     }    
1885
1886 }
1887
1888 /*-----------------------------------------------------------------*/
1889 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1890 /*-----------------------------------------------------------------*/
1891 static void mov2w (asmop *aop, int offset)
1892 {
1893
1894 //  if(!aop)
1895 //    return;
1896
1897         DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1898
1899         if(is_LitAOp(aop))
1900                 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1901         else
1902                 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1903
1904 }
1905
1906
1907 /* push pcop into stack */
1908 void pic16_pushpCodeOp(pCodeOp *pcop)
1909 {
1910 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1911         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
1912 }
1913
1914 /* pop pcop from stack */
1915 void pic16_poppCodeOp(pCodeOp *pcop)
1916 {
1917         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
1918 }
1919
1920
1921 /*-----------------------------------------------------------------*/
1922 /* pushw - pushes wreg to stack                                    */
1923 /*-----------------------------------------------------------------*/
1924 void pushw(void)
1925 {
1926         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1927         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
1928 }
1929
1930                 
1931 /*-----------------------------------------------------------------*/
1932 /* pushaop - pushes aop to stack                                   */
1933 /*-----------------------------------------------------------------*/
1934 void pushaop(asmop *aop, int offset)
1935 {
1936         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1937         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
1938 }
1939
1940 /*-----------------------------------------------------------------*/
1941 /* popaop - pops aop from stack                                    */
1942 /*-----------------------------------------------------------------*/
1943 void popaop(asmop *aop, int offset)
1944 {
1945         DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
1946         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
1947 }
1948
1949 void popaopidx(asmop *aop, int offset, int index)
1950 {
1951   int ofs=1;
1952
1953         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1954
1955         if(STACK_MODEL_LARGE)ofs++;
1956
1957         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
1958         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
1959 }
1960
1961 /*-----------------------------------------------------------------*/
1962 /* reAdjustPreg - points a register back to where it should        */
1963 /*-----------------------------------------------------------------*/
1964 static void reAdjustPreg (asmop *aop)
1965 {
1966     int size ;
1967
1968     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1969     aop->coff = 0;
1970     if ((size = aop->size) <= 1)
1971         return ;
1972     size-- ;
1973     switch (aop->type) {
1974         case AOP_R0 :
1975         case AOP_R1 :
1976             while (size--)
1977                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1978             break;          
1979         case AOP_DPTR :
1980         case AOP_DPTR2:
1981             if (aop->type == AOP_DPTR2)
1982             {
1983                 genSetDPTR(1);
1984             } 
1985             while (size--)
1986             {
1987                 pic16_emitcode("lcall","__decdptr");
1988             }
1989                 
1990             if (aop->type == AOP_DPTR2)
1991             {
1992                 genSetDPTR(0);
1993             }                
1994             break;  
1995
1996     }   
1997
1998 }
1999
2000
2001 #if 0
2002 /*-----------------------------------------------------------------*/
2003 /* opIsGptr: returns non-zero if the passed operand is             */   
2004 /* a generic pointer type.                                         */
2005 /*-----------------------------------------------------------------*/ 
2006 static int opIsGptr(operand *op)
2007 {
2008     sym_link *type = operandType(op);
2009     
2010     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2011     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2012     {
2013         return 1;
2014     }
2015     return 0;        
2016 }
2017 #endif
2018
2019 /*-----------------------------------------------------------------*/
2020 /* pic16_getDataSize - get the operand data size                         */
2021 /*-----------------------------------------------------------------*/
2022 int pic16_getDataSize(operand *op)
2023 {
2024     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2025
2026
2027     return AOP_SIZE(op);
2028
2029     // tsd- in the pic port, the genptr size is 1, so this code here
2030     // fails. ( in the 8051 port, the size was 4).
2031 #if 0
2032     int size;
2033     size = AOP_SIZE(op);
2034     if (size == GPTRSIZE)
2035     {
2036         sym_link *type = operandType(op);
2037         if (IS_GENPTR(type))
2038         {
2039             /* generic pointer; arithmetic operations
2040              * should ignore the high byte (pointer type).
2041              */
2042             size--;
2043     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2044         }
2045     }
2046     return size;
2047 #endif
2048 }
2049
2050 /*-----------------------------------------------------------------*/
2051 /* pic16_outAcc - output Acc                                             */
2052 /*-----------------------------------------------------------------*/
2053 void pic16_outAcc(operand *result)
2054 {
2055   int size,offset;
2056   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2057   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2058
2059
2060   size = pic16_getDataSize(result);
2061   if(size){
2062     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2063     size--;
2064     offset = 1;
2065     /* unsigned or positive */
2066     while(size--)
2067       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2068   }
2069
2070 }
2071
2072 /*-----------------------------------------------------------------*/
2073 /* pic16_outBitC - output a bit C                                  */
2074 /*                 Move to result the value of Carry flag -- VR    */
2075 /*-----------------------------------------------------------------*/
2076 void pic16_outBitC(operand *result)
2077 {
2078   int i;
2079
2080     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2081     /* if the result is bit */
2082     if (AOP_TYPE(result) == AOP_CRY) {
2083         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2084         pic16_aopPut(AOP(result),"c",0);
2085     } else {
2086
2087         i = AOP_SIZE(result);
2088         while(i--) {
2089                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2090         }
2091         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2092         
2093 /*
2094         pic16_emitcode("clr","a  ; %d", __LINE__);
2095         pic16_emitcode("rlc","a");
2096         pic16_outAcc(result);
2097 */
2098     }
2099 }
2100
2101 /*-----------------------------------------------------------------*/
2102 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2103 /*-----------------------------------------------------------------*/
2104 void pic16_toBoolean(operand *oper)
2105 {
2106     int size = AOP_SIZE(oper) - 1;
2107     int offset = 1;
2108
2109     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2110
2111     if ( AOP_TYPE(oper) != AOP_ACC) {
2112       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2113     }
2114     while (size--) {
2115       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2116     }
2117 }
2118
2119
2120 #if !defined(GEN_Not)
2121 /*-----------------------------------------------------------------*/
2122 /* genNot - generate code for ! operation                          */
2123 /*-----------------------------------------------------------------*/
2124 static void pic16_genNot (iCode *ic)
2125 {
2126   symbol *tlbl;
2127   int size;
2128
2129   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2130   /* assign asmOps to operand & result */
2131   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2132   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2133
2134   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2135   /* if in bit space then a special case */
2136   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2137     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2138       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2139       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2140     } else {
2141       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2142       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2143       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2144     }
2145     goto release;
2146   }
2147
2148   size = AOP_SIZE(IC_LEFT(ic));
2149   if(size == 1) {
2150     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2151     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2152     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2153     goto release;
2154   }
2155   pic16_toBoolean(IC_LEFT(ic));
2156
2157   tlbl = newiTempLabel(NULL);
2158   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2159   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2160   pic16_outBitC(IC_RESULT(ic));
2161
2162  release:    
2163   /* release the aops */
2164   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2165   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2166 }
2167 #endif
2168
2169
2170 #if !defined(GEN_Cpl)
2171 /*-----------------------------------------------------------------*/
2172 /* genCpl - generate code for complement                           */
2173 /*-----------------------------------------------------------------*/
2174 static void pic16_genCpl (iCode *ic)
2175 {
2176     int offset = 0;
2177     int size ;
2178
2179
2180     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2181     /* assign asmOps to operand & result */
2182     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2183     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2184
2185     /* if both are in bit space then 
2186     a special case */
2187     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2188         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2189
2190         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2191         pic16_emitcode("cpl","c"); 
2192         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2193         goto release; 
2194     } 
2195
2196     size = AOP_SIZE(IC_RESULT(ic));
2197     while (size--) {
2198 /*
2199         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2200         MOVA(l);       
2201         pic16_emitcode("cpl","a");
2202         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2203 */
2204         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2205               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2206         } else {
2207                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2208                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2209         }
2210         offset++;
2211
2212     }
2213
2214
2215 release:
2216     /* release the aops */
2217     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2218     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2219 }
2220 #endif
2221
2222 /*-----------------------------------------------------------------*/
2223 /* genUminusFloat - unary minus for floating points                */
2224 /*-----------------------------------------------------------------*/
2225 static void genUminusFloat(operand *op,operand *result)
2226 {
2227     int size ,offset =0 ;
2228     char *l;
2229
2230     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2231     /* for this we just need to flip the 
2232     first it then copy the rest in place */
2233     size = AOP_SIZE(op) - 1;
2234     l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2235
2236     MOVA(l);    
2237
2238     pic16_emitcode("cpl","acc.7");
2239     pic16_aopPut(AOP(result),"a",3);    
2240
2241     while(size--) {
2242         pic16_aopPut(AOP(result),
2243                pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2244                offset);
2245         offset++;
2246     }          
2247 }
2248
2249 /*-----------------------------------------------------------------*/
2250 /* genUminus - unary minus code generation                         */
2251 /*-----------------------------------------------------------------*/
2252 static void genUminus (iCode *ic)
2253 {
2254   int size, i;
2255   sym_link *optype, *rtype;
2256
2257         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2258         
2259         /* assign asmops */
2260         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2261         pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2262
2263         /* if both in bit space then special case */
2264         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2265                 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2266
2267                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2268                 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2269                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2270                 
2271                 goto release; 
2272         } 
2273
2274         optype = operandType(IC_LEFT(ic));
2275         rtype = operandType(IC_RESULT(ic));
2276
2277         /* if float then do float stuff */
2278         if (IS_FLOAT(optype)) {
2279                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2280                 goto release;
2281         }
2282
2283         /* otherwise subtract from zero by taking the 2's complement */
2284         size = AOP_SIZE(IC_LEFT(ic));
2285
2286         for(i=0; i<size; i++) {
2287                 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2288                         pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2289                 else {
2290                         pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2291                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2292                 }
2293         }
2294
2295         pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2296         for(i=1; i<size; i++) {
2297                 emitSKPNZ;
2298                 pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2299         }
2300
2301 release:
2302         /* release the aops */
2303         pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2304         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2305 }
2306
2307 /*-----------------------------------------------------------------*/
2308 /* saveRegisters - will look for a call and save the registers     */
2309 /*-----------------------------------------------------------------*/
2310 static void saveRegisters(iCode *lic) 
2311 {
2312     int i;
2313     iCode *ic;
2314     bitVect *rsave;
2315     sym_link *dtype;
2316
2317     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2318     /* look for call */
2319     for (ic = lic ; ic ; ic = ic->next) 
2320         if (ic->op == CALL || ic->op == PCALL)
2321             break;
2322
2323     if (!ic) {
2324         fprintf(stderr,"found parameter push with no function call\n");
2325         return ;
2326     }
2327
2328     /* if the registers have been saved already then
2329     do nothing */
2330     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2331         return ;
2332
2333     /* find the registers in use at this time 
2334     and push them away to safety */
2335     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2336                           ic->rUsed);
2337
2338     ic->regsSaved = 1;
2339     if (options.useXstack) {
2340         if (bitVectBitValue(rsave,R0_IDX))
2341             pic16_emitcode("mov","b,r0");
2342         pic16_emitcode("mov","r0,%s",spname);
2343         for (i = 0 ; i < pic16_nRegs ; i++) {
2344             if (bitVectBitValue(rsave,i)) {
2345                 if (i == R0_IDX)
2346                     pic16_emitcode("mov","a,b");
2347                 else
2348                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2349                 pic16_emitcode("movx","@r0,a");
2350                 pic16_emitcode("inc","r0");
2351             }
2352         }
2353         pic16_emitcode("mov","%s,r0",spname);
2354         if (bitVectBitValue(rsave,R0_IDX))
2355             pic16_emitcode("mov","r0,b");           
2356     }// else
2357     //for (i = 0 ; i < pic16_nRegs ; i++) {
2358     //    if (bitVectBitValue(rsave,i))
2359     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2360     //}
2361
2362     dtype = operandType(IC_LEFT(ic));
2363     if (currFunc && dtype && 
2364         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2365         IFFUNC_ISISR(currFunc->type) &&
2366         !ic->bankSaved) 
2367
2368         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2369
2370 }
2371 /*-----------------------------------------------------------------*/
2372 /* unsaveRegisters - pop the pushed registers                      */
2373 /*-----------------------------------------------------------------*/
2374 static void unsaveRegisters (iCode *ic)
2375 {
2376     int i;
2377     bitVect *rsave;
2378
2379     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2380     /* find the registers in use at this time 
2381     and push them away to safety */
2382     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2383                           ic->rUsed);
2384     
2385     if (options.useXstack) {
2386         pic16_emitcode("mov","r0,%s",spname);   
2387         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2388             if (bitVectBitValue(rsave,i)) {
2389                 pic16_emitcode("dec","r0");
2390                 pic16_emitcode("movx","a,@r0");
2391                 if (i == R0_IDX)
2392                     pic16_emitcode("mov","b,a");
2393                 else
2394                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2395             }       
2396
2397         }
2398         pic16_emitcode("mov","%s,r0",spname);
2399         if (bitVectBitValue(rsave,R0_IDX))
2400             pic16_emitcode("mov","r0,b");
2401     } //else
2402     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2403     //    if (bitVectBitValue(rsave,i))
2404     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2405     //}
2406
2407 }  
2408
2409 #if 0  // patch 14
2410 /*-----------------------------------------------------------------*/
2411 /* pushSide -                                                      */
2412 /*-----------------------------------------------------------------*/
2413 static void pushSide(operand * oper, int size)
2414 {
2415         int offset = 0;
2416     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2417         while (size--) {
2418                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2419                 if (AOP_TYPE(oper) != AOP_REG &&
2420                     AOP_TYPE(oper) != AOP_DIR &&
2421                     strcmp(l,"a") ) {
2422                         pic16_emitcode("mov","a,%s",l);
2423                         pic16_emitcode("push","acc");
2424                 } else
2425                         pic16_emitcode("push","%s",l);
2426         }
2427 }
2428 #endif // patch 14
2429
2430 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2431 {
2432 //              (AOP(left)->aopu.pcop->type == PO_DIR)?
2433
2434         if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2435                 pic16_emitpcode(POC_MOVFW, src);
2436                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2437         } else {
2438                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2439                         src, pic16_popGet(AOP(op), offset)));
2440         }
2441 }
2442
2443
2444 /*-----------------------------------------------------------------*/
2445 /* assignResultValue - assign results to oper, rescall==1 is       */
2446 /*                     called from genCall() or genPCall()         */
2447 /*-----------------------------------------------------------------*/
2448 static void assignResultValue(operand * oper, int rescall)
2449 {
2450   int size = AOP_SIZE(oper);
2451
2452         DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2453         DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2454
2455         if(rescall) {
2456                 /* assign result from a call/pcall function() */
2457                 
2458                 /* function results are stored in a special order,
2459                  * see top of file with Function return policy, or manual */
2460
2461                 if(size <= 4) {
2462                         /* 8-bits, result in WREG */
2463                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2464                         
2465                         if(size>1) {
2466                                 /* 16-bits, result in PRODL:WREG */
2467                                 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2468                         }
2469                         
2470                         if(size>2) {
2471                                 /* 24-bits, result in PRODH:PRODL:WREG */
2472                                 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2473                         }
2474                         
2475                         if(size>3) {
2476                                 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2477                                 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2478                         }
2479                 } else {
2480                         /* >32-bits, result on stack, and FSR0 points to beginning.
2481                          * Fix stack when done */
2482                          /* FIXME FIXME */
2483                         while (size--) {
2484 //                              DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2485 //                              DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2486                 
2487                                 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2488                                 GpsuedoStkPtr++;
2489                         }
2490                         
2491                         /* fix stack */
2492                         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2493                         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2494                         if(STACK_MODEL_LARGE) {
2495                                 emitSKPNC;
2496                                 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2497                         }
2498                 }                       
2499         } else {        
2500                 if(!GpsuedoStkPtr) {
2501 //                      DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2502                         /* The last byte in the assignment is in W */
2503                         size--;
2504                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2505                         GpsuedoStkPtr++;
2506                 }
2507
2508                 while (size--) {
2509 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2510 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2511                 
2512                         popaopidx(AOP(oper), size, GpsuedoStkPtr);
2513                         GpsuedoStkPtr++;
2514
2515 #if 0
2516 #if STACK_SUPPORT
2517                 if(!USE_STACK)
2518                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2519 #else
2520                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2521 #endif
2522 #endif
2523
2524                 }
2525         }
2526                 
2527 }
2528
2529
2530 /*-----------------------------------------------------------------*/
2531 /* genIpush - genrate code for pushing this gets a little complex  */
2532 /*-----------------------------------------------------------------*/
2533 static void genIpush (iCode *ic)
2534 {
2535
2536   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2537 #if 0
2538     int size, offset = 0 ;
2539     char *l;
2540
2541
2542     /* if this is not a parm push : ie. it is spill push 
2543     and spill push is always done on the local stack */
2544     if (!ic->parmPush) {
2545
2546         /* and the item is spilt then do nothing */
2547         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2548             return ;
2549
2550         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2551         size = AOP_SIZE(IC_LEFT(ic));
2552         /* push it on the stack */
2553         while(size--) {
2554             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2555             if (*l == '#') {
2556                 MOVA(l);
2557                 l = "acc";
2558             }
2559             pic16_emitcode("push","%s",l);
2560         }
2561         return ;        
2562     }
2563
2564     /* this is a paramter push: in this case we call
2565     the routine to find the call and save those
2566     registers that need to be saved */   
2567     saveRegisters(ic);
2568
2569     /* then do the push */
2570     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2571
2572
2573         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2574     size = AOP_SIZE(IC_LEFT(ic));
2575
2576     while (size--) {
2577         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2578         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2579             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2580             strcmp(l,"a") ) {
2581             pic16_emitcode("mov","a,%s",l);
2582             pic16_emitcode("push","acc");
2583         } else
2584             pic16_emitcode("push","%s",l);
2585     }       
2586
2587     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2588 #endif
2589 }
2590
2591 /*-----------------------------------------------------------------*/
2592 /* genIpop - recover the registers: can happen only for spilling   */
2593 /*-----------------------------------------------------------------*/
2594 static void genIpop (iCode *ic)
2595 {
2596   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2597 #if 0
2598     int size,offset ;
2599
2600
2601     /* if the temp was not pushed then */
2602     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2603         return ;
2604
2605     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2606     size = AOP_SIZE(IC_LEFT(ic));
2607     offset = (size-1);
2608     while (size--) 
2609         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2610                                    FALSE,TRUE));
2611
2612     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2613 #endif
2614 }
2615
2616 /*-----------------------------------------------------------------*/
2617 /* unsaverbank - restores the resgister bank from stack            */
2618 /*-----------------------------------------------------------------*/
2619 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2620 {
2621   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2622 #if 0
2623     int i;
2624     asmop *aop ;
2625     regs *r = NULL;
2626
2627     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2628     if (popPsw) {
2629         if (options.useXstack) {
2630             aop = newAsmop(0);
2631             r = getFreePtr(ic,&aop,FALSE);
2632             
2633             
2634             pic16_emitcode("mov","%s,_spx",r->name);
2635             pic16_emitcode("movx","a,@%s",r->name);
2636             pic16_emitcode("mov","psw,a");
2637             pic16_emitcode("dec","%s",r->name);
2638             
2639         }else
2640             pic16_emitcode ("pop","psw");
2641     }
2642
2643     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2644         if (options.useXstack) {       
2645             pic16_emitcode("movx","a,@%s",r->name);
2646             //pic16_emitcode("mov","(%s+%d),a",
2647             //       regspic16[i].base,8*bank+regspic16[i].offset);
2648             pic16_emitcode("dec","%s",r->name);
2649
2650         } else 
2651           pic16_emitcode("pop",""); //"(%s+%d)",
2652         //regspic16[i].base,8*bank); //+regspic16[i].offset);
2653     }
2654
2655     if (options.useXstack) {
2656
2657         pic16_emitcode("mov","_spx,%s",r->name);
2658         pic16_freeAsmop(NULL,aop,ic,TRUE);
2659
2660     }
2661 #endif 
2662 }
2663
2664 /*-----------------------------------------------------------------*/
2665 /* saverbank - saves an entire register bank on the stack          */
2666 /*-----------------------------------------------------------------*/
2667 static void saverbank (int bank, iCode *ic, bool pushPsw)
2668 {
2669   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2670 #if 0
2671     int i;
2672     asmop *aop ;
2673     regs *r = NULL;
2674
2675     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2676     if (options.useXstack) {
2677
2678         aop = newAsmop(0);
2679         r = getFreePtr(ic,&aop,FALSE);  
2680         pic16_emitcode("mov","%s,_spx",r->name);
2681
2682     }
2683
2684     for (i = 0 ; i < pic16_nRegs ;i++) {
2685         if (options.useXstack) {
2686             pic16_emitcode("inc","%s",r->name);
2687             //pic16_emitcode("mov","a,(%s+%d)",
2688             //         regspic16[i].base,8*bank+regspic16[i].offset);
2689             pic16_emitcode("movx","@%s,a",r->name);           
2690         } else 
2691           pic16_emitcode("push","");// "(%s+%d)",
2692                      //regspic16[i].base,8*bank+regspic16[i].offset);
2693     }
2694     
2695     if (pushPsw) {
2696         if (options.useXstack) {
2697             pic16_emitcode("mov","a,psw");
2698             pic16_emitcode("movx","@%s,a",r->name);     
2699             pic16_emitcode("inc","%s",r->name);
2700             pic16_emitcode("mov","_spx,%s",r->name);       
2701             pic16_freeAsmop (NULL,aop,ic,TRUE);
2702             
2703         } else
2704             pic16_emitcode("push","psw");
2705         
2706         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2707     }
2708     ic->bankSaved = 1;
2709 #endif
2710 }
2711
2712
2713
2714 /*-----------------------------------------------------------------*/
2715 /* genCall - generates a call statement                            */
2716 /*-----------------------------------------------------------------*/
2717 static void genCall (iCode *ic)
2718 {
2719   sym_link *dtype;   
2720   int stackParms=0;
2721   
2722         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2723
2724         /* if caller saves & we have not saved then */
2725         if (!ic->regsSaved)
2726                 saveRegisters(ic);
2727
2728         /* if we are calling a function that is not using
2729          * the same register bank then we need to save the
2730          * destination registers on the stack */
2731         dtype = operandType(IC_LEFT(ic));
2732         if (currFunc && dtype && 
2733                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2734                 IFFUNC_ISISR(currFunc->type) &&
2735                 !ic->bankSaved) 
2736
2737                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2738
2739         /* if send set is not empty the assign */
2740         if (_G.sendSet) {
2741           iCode *sic;
2742
2743                 /* For the Pic port, there is no data stack.
2744                  * So parameters passed to functions are stored
2745                  * in registers. (The pCode optimizer will get
2746                  * rid of most of these :). */
2747
2748           int psuedoStkPtr=-1; 
2749           int firstTimeThruLoop = 1;
2750
2751                 _G.sendSet = reverseSet(_G.sendSet);
2752
2753                 /* First figure how many parameters are getting passed */
2754                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2755                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2756                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2757                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2758                 }
2759
2760                 stackParms = psuedoStkPtr;
2761
2762                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2763                   int size, offset = 0;
2764
2765                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2766                         size = AOP_SIZE(IC_LEFT(sic));
2767
2768                         while (size--) {
2769                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2770                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2771                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2772
2773                                 if(!firstTimeThruLoop) {
2774                                         /* If this is not the first time we've been through the loop
2775                                          * then we need to save the parameter in a temporary
2776                                          * register. The last byte of the last parameter is
2777                                          * passed in W. */
2778
2779                                         pushw();
2780                                         --psuedoStkPtr;         // sanity check
2781                                 }
2782                         
2783                                 firstTimeThruLoop=0;
2784
2785                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2786                                 offset++;
2787                         }
2788                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2789                 }
2790                 _G.sendSet = NULL;
2791         }
2792
2793         /* make the call */
2794         pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2795                         OP_SYMBOL(IC_LEFT(ic))->rname :
2796                         OP_SYMBOL(IC_LEFT(ic))->name));
2797
2798         GpsuedoStkPtr=0;
2799         /* if we need assign a result value */
2800         if ((IS_ITEMP(IC_RESULT(ic)) && 
2801                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2802                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2803                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2804
2805                 _G.accInUse++;
2806                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2807                 _G.accInUse--;
2808
2809                 assignResultValue(IC_RESULT(ic), 1);
2810
2811                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2812                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2813                 
2814                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2815         }
2816
2817         if(stackParms>0) {
2818                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2819                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2820                 if(STACK_MODEL_LARGE) {
2821                         emitSKPNC;
2822                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2823                 }
2824         }
2825
2826         /* adjust the stack for parameters if required */
2827 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2828
2829         if (ic->parmBytes) {
2830           int i;
2831
2832                 if (ic->parmBytes > 3) {
2833                         pic16_emitcode("mov","a,%s",spname);
2834                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2835                         pic16_emitcode("mov","%s,a",spname);
2836                 } else 
2837                         for ( i = 0 ; i <  ic->parmBytes ;i++)
2838                                 pic16_emitcode("dec","%s",spname);
2839         }
2840
2841 #if 0
2842         /* if register bank was saved then pop them */
2843         if (ic->bankSaved)
2844                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2845
2846         /* if we hade saved some registers then unsave them */
2847         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2848                 unsaveRegisters (ic);
2849 #endif
2850 }
2851
2852
2853
2854 /*-----------------------------------------------------------------*/   // patch 14
2855 /* genPcall - generates a call by pointer statement                */
2856 /*-----------------------------------------------------------------*/
2857
2858 // new version, created from genCall
2859
2860 static void genPcall (iCode *ic)
2861 {
2862   sym_link *dtype;   
2863   int stackParms=0;
2864   symbol *retlbl = newiTempLabel(NULL);
2865   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
2866   
2867         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2868
2869         /* if caller saves & we have not saved then */
2870         if (!ic->regsSaved)
2871                 saveRegisters(ic);
2872
2873         /* if we are calling a function that is not using
2874          * the same register bank then we need to save the
2875          * destination registers on the stack */
2876         dtype = operandType(IC_LEFT(ic));
2877         if (currFunc && dtype && 
2878                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2879                 IFFUNC_ISISR(currFunc->type) &&
2880                 !ic->bankSaved) 
2881
2882                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2883
2884         /* if send set is not empty the assign */
2885         if (_G.sendSet) {
2886           iCode *sic;
2887
2888                 /* For the Pic port, there is no data stack.
2889                  * So parameters passed to functions are stored
2890                  * in registers. (The pCode optimizer will get
2891                  * rid of most of these :). */
2892
2893           int psuedoStkPtr=-1; 
2894           int firstTimeThruLoop = 1;
2895
2896                 _G.sendSet = reverseSet(_G.sendSet);
2897
2898                 /* First figure how many parameters are getting passed */
2899                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2900                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2901                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2902                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2903                 }
2904
2905                 stackParms = psuedoStkPtr;
2906
2907                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2908                   int size, offset = 0;
2909
2910                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2911                         size = AOP_SIZE(IC_LEFT(sic));
2912
2913                         while (size--) {
2914                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2915                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2916                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2917
2918                                 if(!firstTimeThruLoop) {
2919                                         /* If this is not the first time we've been through the loop
2920                                          * then we need to save the parameter in a temporary
2921                                          * register. The last byte of the last parameter is
2922                                          * passed in W. */
2923
2924                                         pushw();
2925                                         --psuedoStkPtr;         // sanity check
2926                                 }
2927                         
2928                                 firstTimeThruLoop=0;
2929
2930                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2931                                 offset++;
2932                         }
2933                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2934                 }
2935                 _G.sendSet = NULL;
2936         }
2937
2938         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2939
2940         // push return address
2941         // push $ on return stack, then replace with retlbl
2942
2943         pic16_emitpcodeNULLop(POC_PUSH);
2944
2945         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
2946         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
2947         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
2948         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
2949         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
2950         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
2951
2952         /* make the call by writing the pointer into pc */
2953         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
2954         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
2955
2956         // note: MOVFF to PCL not allowed
2957         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
2958         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
2959
2960
2961 //      pic16_emitpcode(POC_GOTO, pic16_popGetLabel(retlbl->key));
2962 //      pic16_emitpcodeNULLop(POC_NOP);
2963 //      pic16_emitpcodeNULLop(POC_NOP);
2964
2965         /* return address is here: (X) */
2966         pic16_emitpLabelFORCE(retlbl->key);
2967
2968 //      pic16_emitpcodeNULLop(POC_NOP);
2969
2970         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2971
2972         GpsuedoStkPtr=0;
2973         /* if we need assign a result value */
2974         if ((IS_ITEMP(IC_RESULT(ic)) && 
2975                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2976                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2977                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2978
2979                 _G.accInUse++;
2980                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2981                 _G.accInUse--;
2982
2983                 assignResultValue(IC_RESULT(ic), 1);
2984
2985                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2986                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2987                 
2988                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2989         }
2990
2991         if(stackParms>0) {
2992                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2993                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2994                 if(STACK_MODEL_LARGE) {
2995                         emitSKPNC;
2996                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2997                 }
2998         }
2999
3000         /* adjust the stack for parameters if required */
3001 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3002
3003         if (ic->parmBytes) {
3004           int i;
3005
3006                 if (ic->parmBytes > 3) {
3007                         pic16_emitcode("mov","a,%s",spname);
3008                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3009                         pic16_emitcode("mov","%s,a",spname);
3010                 } else 
3011                         for ( i = 0 ; i <  ic->parmBytes ;i++)
3012                                 pic16_emitcode("dec","%s",spname);
3013         }
3014
3015         /* if register bank was saved then pop them */
3016         if (ic->bankSaved)
3017                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3018
3019         /* if we hade saved some registers then unsave them */
3020         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3021                 unsaveRegisters (ic);
3022 }
3023
3024
3025 #if 0                                                                           // patch 14
3026 // old version, kept for reference
3027
3028 /*-----------------------------------------------------------------*/
3029 /* genPcall - generates a call by pointer statement                */
3030 /*-----------------------------------------------------------------*/
3031 static void genPcall (iCode *ic)
3032 {
3033     sym_link *dtype;
3034     symbol *rlbl = newiTempLabel(NULL);
3035
3036
3037     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3038     /* if caller saves & we have not saved then */
3039     if (!ic->regsSaved)
3040         saveRegisters(ic);
3041
3042     /* if we are calling a function that is not using
3043     the same register bank then we need to save the
3044     destination registers on the stack */
3045     dtype = operandType(IC_LEFT(ic));
3046     if (currFunc && dtype && 
3047         IFFUNC_ISISR(currFunc->type) &&
3048         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3049         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3050
3051
3052     /* push the return address on to the stack */
3053     pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
3054     pic16_emitcode("push","acc");    
3055     pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
3056     pic16_emitcode("push","acc");
3057     
3058     if (options.model == MODEL_FLAT24)
3059     {
3060         pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
3061         pic16_emitcode("push","acc");    
3062     }
3063
3064     /* now push the calling address */
3065     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3066
3067     pushSide(IC_LEFT(ic), FPTRSIZE);
3068
3069     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
3070
3071     /* if send set is not empty the assign */
3072     if (_G.sendSet) {
3073         iCode *sic ;
3074
3075         for (sic = setFirstItem(_G.sendSet) ; sic ; 
3076              sic = setNextItem(_G.sendSet)) {
3077             int size, offset = 0;
3078             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3079             size = AOP_SIZE(IC_LEFT(sic));
3080             while (size--) {
3081                 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
3082                                 FALSE,FALSE);
3083                 if (strcmp(l,fReturn[offset]))
3084                     pic16_emitcode("mov","%s,%s",
3085                              fReturn[offset],
3086                              l);
3087                 offset++;
3088             }
3089             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3090         }
3091         _G.sendSet = NULL;
3092     }
3093
3094     pic16_emitcode("ret","");
3095     pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
3096
3097
3098     /* if we need assign a result value */
3099     if ((IS_ITEMP(IC_RESULT(ic)) &&
3100          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3101           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
3102         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3103
3104         _G.accInUse++;
3105         pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3106         _G.accInUse--;
3107         
3108         assignResultValue(IC_RESULT(ic), 1);
3109
3110         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3111     }
3112
3113     /* adjust the stack for parameters if 
3114     required */
3115     if (ic->parmBytes) {
3116         int i;
3117         if (ic->parmBytes > 3) {
3118             pic16_emitcode("mov","a,%s",spname);
3119             pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3120             pic16_emitcode("mov","%s,a",spname);
3121         } else 
3122             for ( i = 0 ; i <  ic->parmBytes ;i++)
3123                 pic16_emitcode("dec","%s",spname);
3124
3125     }
3126
3127     /* if register bank was saved then unsave them */
3128     if (currFunc && dtype && 
3129         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3130         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3131
3132     /* if we hade saved some registers then
3133     unsave them */
3134     if (ic->regsSaved)
3135         unsaveRegisters (ic);
3136
3137 }
3138 #endif                                                                          // patch 14
3139
3140
3141 /*-----------------------------------------------------------------*/
3142 /* resultRemat - result  is rematerializable                       */
3143 /*-----------------------------------------------------------------*/
3144 static int resultRemat (iCode *ic)
3145 {
3146   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3147   if (SKIP_IC(ic) || ic->op == IFX)
3148     return 0;
3149
3150   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3151     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3152     if (sym->remat && !POINTER_SET(ic)) 
3153       return 1;
3154   }
3155
3156   return 0;
3157 }
3158
3159 #if defined(__BORLANDC__) || defined(_MSC_VER)
3160 #define STRCASECMP stricmp
3161 #else
3162 #define STRCASECMP strcasecmp
3163 #endif
3164
3165 #if 0
3166 /*-----------------------------------------------------------------*/
3167 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3168 /*-----------------------------------------------------------------*/
3169 static bool inExcludeList(char *s)
3170 {
3171   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3172     int i =0;
3173     
3174     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3175     if (options.excludeRegs[i] &&
3176     STRCASECMP(options.excludeRegs[i],"none") == 0)
3177         return FALSE ;
3178
3179     for ( i = 0 ; options.excludeRegs[i]; i++) {
3180         if (options.excludeRegs[i] &&
3181         STRCASECMP(s,options.excludeRegs[i]) == 0)
3182             return TRUE;
3183     }
3184     return FALSE ;
3185 }
3186 #endif
3187
3188 /*-----------------------------------------------------------------*/
3189 /* genFunction - generated code for function entry                 */
3190 /*-----------------------------------------------------------------*/
3191 static void genFunction (iCode *ic)
3192 {
3193   symbol *sym;
3194   sym_link *ftype;
3195   
3196         DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3197
3198         pic16_labelOffset += (max_key+4);
3199         max_key=0;
3200         GpsuedoStkPtr=0;
3201         _G.nRegsSaved = 0;
3202
3203         ftype = operandType(IC_LEFT(ic));
3204         sym = OP_SYMBOL(IC_LEFT(ic));
3205
3206         if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3207                 /* create an absolute section at the interrupt vector:
3208                  * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3209           symbol *asym;
3210           char asymname[128];
3211           pBlock *apb;
3212
3213                 {
3214                   int i, found=-1;
3215
3216                         sym = OP_SYMBOL( IC_LEFT(ic));
3217                         for(i=0;i<=2;i++) {
3218                                 if(interrupts[i]->name
3219                                         && !STRCASECMP(interrupts[i]->name, sym->name)) {
3220                                         found = i;
3221                                         break;
3222                                 }
3223                         }
3224                         
3225                         if(found == -1) {
3226                                 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3227                                         __FILE__, __LINE__, sym->name);
3228                                 assert( 0 );
3229                         }
3230                         _G.interruptvector = found;
3231                 }
3232
3233                 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3234                 asym = newSymbol(asymname, 0);
3235
3236                 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3237                 pic16_addpBlock( apb );
3238
3239                 pic16_addpCode2pBlock(apb,
3240                         pic16_newpCodeCharP(";-----------------------------------------"));
3241
3242
3243                 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3244
3245                 pic16_addpCode2pBlock(apb,
3246                         pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3247                 
3248                 /* mark the end of this tiny function */
3249                 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3250
3251                 {
3252                   absSym *abSym;
3253
3254                         abSym = Safe_calloc(1, sizeof(absSym));
3255                         abSym->name = Safe_strdup( asymname );
3256
3257                         switch( _G.interruptvector ) {
3258                                 case 0: abSym->address = 0x000000; break;
3259                                 case 1: abSym->address = 0x000008; break;
3260                                 case 2: abSym->address = 0x000018; break;
3261                         }
3262
3263                         /* relocate interrupt vectors if needed */
3264                         abSym->address += pic16_options.ivt_loc;
3265
3266                         addSet(&absSymSet, abSym);
3267                 }
3268         }
3269
3270
3271         /* create the function header */
3272         pic16_emitcode(";","-----------------------------------------");
3273         pic16_emitcode(";"," function %s",sym->name);
3274         pic16_emitcode(";","-----------------------------------------");
3275
3276         pic16_emitcode("","%s:",sym->rname);
3277         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3278
3279
3280         {
3281           absSym *ab;
3282
3283                 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
3284                         if(!strcmp(ab->name, sym->name)) {
3285                                 pic16_pBlockConvert2Absolute(pb);
3286                                 break;
3287                         }
3288
3289         }
3290
3291
3292         if(IFFUNC_ISNAKED(ftype)) {
3293                 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3294                 return;
3295         }
3296         
3297         /* if critical function then turn interrupts off */
3298         if (IFFUNC_ISCRITICAL(ftype))
3299                 pic16_emitcode("clr","ea");
3300
3301         /* if this is an interrupt service routine then
3302          * save acc, b, dpl, dph  */
3303         if (IFFUNC_ISISR(sym->type)) {
3304           int i;
3305                 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3306                 if(!(_G.interruptvector == 1)) {
3307
3308                         /* do not save WREG,STATUS,BSR for high priority interrupts
3309                          * because they are stored in the hardware shadow registers already */
3310                          
3311                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3312                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3313                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3314                 }
3315
3316                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3317                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3318                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3319                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3320
3321 //                pic16_pBlockConvert2ISR(pb);
3322                 
3323                 /* if any registers used */
3324                 if (sym->regsUsed) {
3325                         /* save the registers used */
3326                         DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3327                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3328                                 if (bitVectBitValue(sym->regsUsed,i)) {
3329 #if 0
3330                                         fprintf(stderr, "%s:%d function %s uses register %s\n",
3331                                                         __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3332                                                         pic16_regWithIdx(i)->name);
3333 #endif
3334
3335                                         pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3336                                         _G.nRegsSaved++;
3337
3338                                         if(!pic16_regWithIdx(i)->wasUsed) {
3339                                                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3340                                                         __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3341
3342                                                 pic16_regWithIdx(i)->wasUsed = 1;
3343                                         }
3344                                 }
3345                         }
3346                 }
3347         } else {
3348                 /* emit code to setup stack frame if user enabled,
3349                  * and function is not main() */
3350          
3351 //              fprintf(stderr, "function name: %s\n", sym->name);
3352                 if(strcmp(sym->name, "main")) {
3353                         if(/*!options.ommitFramePtr || */sym->regsUsed) {
3354                         /* setup the stack frame */
3355                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3356                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3357                                 if(STACK_MODEL_LARGE)
3358                                         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3359                         }
3360                 }
3361
3362                 /* if callee-save to be used for this function
3363                 * then save the registers being used in this function */
3364 //              if (IFFUNC_CALLEESAVES(sym->type))
3365                 {
3366                   int i;
3367
3368 //                      fprintf(stderr, "%s:%d function sym->regsUsed= %d\n", __FILE__, __LINE__, sym->regsUsed->size);
3369
3370 //                      pic16_emitpcomment("entry regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3371
3372                         /* if any registers used */
3373                         if (sym->regsUsed) {
3374                                 /* save the registers used */
3375                                 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3376                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3377                                         if (bitVectBitValue(sym->regsUsed,i)) {
3378
3379 #if 0
3380                                                 fprintf(stderr, "%s:%d function %s uses register %s (wasUsed: %d, %p)\n",
3381                                                                 __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3382                                                                 pic16_regWithIdx(i)->name,
3383                                                                 pic16_regWithIdx(i)->wasUsed,
3384                                                                 pic16_regWithIdx(i));
3385 #endif
3386
3387                                                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3388
3389 //                                              pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3390 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
3391 //                                                      &pic16_pc_postdec1, 0));
3392
3393                                                 _G.nRegsSaved++;
3394
3395                                                 if(!pic16_regWithIdx(i)->wasUsed) {
3396                                                         fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3397                                                                 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3398
3399                                                         pic16_regWithIdx(i)->wasUsed = 1;
3400                                                 }
3401                                         
3402                                         }
3403                                 }
3404                         }
3405                 }
3406         }
3407
3408
3409         
3410 #if 0
3411         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3412
3413                 if (options.useXstack) {
3414                         pic16_emitcode("mov","r0,%s",spname);
3415                         pic16_emitcode("mov","a,_bp");
3416                         pic16_emitcode("movx","@r0,a");
3417                         pic16_emitcode("inc","%s",spname);
3418                 } else {
3419                         /* set up the stack */
3420                         pic16_emitcode ("push","_bp");     /* save the callers stack  */
3421                 }
3422                 pic16_emitcode ("mov","_bp,%s",spname);
3423         }
3424 #endif
3425         DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3426
3427         /* adjust the stack for the function */
3428         if (sym->stack) {
3429           int i = sym->stack;
3430
3431                 if (i > 127 ) 
3432                         werror(W_STACK_OVERFLOW,sym->name);
3433
3434                 if (i > 3 && sym->recvSize < 4) {              
3435                         pic16_emitcode ("mov","a,sp");
3436                         pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3437                         pic16_emitcode ("mov","sp,a");
3438                 } else
3439                         while(i--)
3440                                 pic16_emitcode("inc","sp");
3441         }
3442
3443         if (sym->xstack) {
3444                 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3445
3446                 pic16_emitcode ("mov","a,_spx");
3447                 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3448                 pic16_emitcode ("mov","_spx,a");
3449         }
3450     
3451 }
3452
3453 /*-----------------------------------------------------------------*/
3454 /* genEndFunction - generates epilogue for functions               */
3455 /*-----------------------------------------------------------------*/
3456 static void genEndFunction (iCode *ic)
3457 {
3458     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3459
3460     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3461
3462     if(IFFUNC_ISNAKED(sym->type)) {
3463         DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3464         return;
3465     }
3466
3467 #if 0
3468     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3469     {
3470         pic16_emitcode ("mov","%s,_bp",spname);
3471     }
3472 #endif
3473
3474     /* if use external stack but some variables were
3475     added to the local stack then decrement the
3476     local stack */
3477     if (options.useXstack && sym->stack) {      
3478         pic16_emitcode("mov","a,sp");
3479         pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3480         pic16_emitcode("mov","sp,a");
3481     }
3482
3483
3484 #if 0
3485     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3486         if (options.useXstack) {
3487             pic16_emitcode("mov","r0,%s",spname);
3488             pic16_emitcode("movx","a,@r0");
3489             pic16_emitcode("mov","_bp,a");
3490             pic16_emitcode("dec","%s",spname);
3491         }
3492         else
3493         {
3494             pic16_emitcode ("pop","_bp");
3495         }
3496     }
3497 #endif
3498
3499         if (IFFUNC_ISISR(sym->type)) {
3500                 /* now we need to restore the registers */
3501                 /* if any registers used */
3502                 if (sym->regsUsed) {
3503                   int i;
3504
3505                         /* restore registers used */
3506                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3507                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3508                                 if (bitVectBitValue(sym->regsUsed,i)) {
3509
3510 //                                      fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3511 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3512 //                                                      pic16_regWithIdx(i)->name);
3513
3514                                         pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3515
3516 //                                      pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3517 //                                                      &pic16_pc_preinc1,
3518 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3519
3520                                 }
3521                         }
3522                 }
3523         
3524                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3525                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3526                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3527                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3528
3529                 if(!(_G.interruptvector == 1)) {
3530                         /* do not restore interrupt vector for WREG,STATUS,BSR
3531                          * for high priority interrupt, see genFunction */
3532                          
3533                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3534                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3535                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3536                 }
3537         
3538                 _G.interruptvector = 0;         /* sanity check */
3539
3540 //              pic16_pBlockConvert2ISR(pb);
3541
3542
3543                 /* if debug then send end of function */
3544 /*      if (options.debug && currFunc)  */
3545                 if (currFunc) {
3546                         debugFile->writeEndFunction (currFunc, ic, 1);
3547                 }
3548         
3549                 pic16_emitpcodeNULLop(POC_RETFIE);
3550         } else {
3551                 if (IFFUNC_ISCRITICAL(sym->type))
3552                         pic16_emitcode("setb","ea");
3553         
3554
3555 //              pic16_emitpcomment("exit regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3556
3557                 /* if any registers used */
3558                 if (sym->regsUsed) {
3559                   int i;
3560                         /* save the registers used */
3561                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3562                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3563                                 if (bitVectBitValue(sym->regsUsed,i)) {
3564         
3565 //                                      fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3566 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3567 //                                                      pic16_regWithIdx(i)->name);
3568         
3569                                         pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3570                                         
3571 //                                      pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3572 //                                              &pic16_pc_preinc1,
3573 //                                              PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3574
3575                                         _G.nRegsSaved--;
3576                                 }
3577                         }
3578                 }
3579         
3580 //              pic16_emitpcomment("%s: _G.nRegsSaved upon exit from function: %d\n", __FUNCTION__, _G.nRegsSaved);
3581                 /* if debug then send end of function */
3582                 if (currFunc) {
3583                         debugFile->writeEndFunction (currFunc, ic, 1);
3584                 }
3585
3586                 /* insert code to restore stack frame, if user enabled it
3587                  * and function is not main() */
3588          
3589
3590                 if(strcmp(sym->name, "main")) {
3591                         if(/*!options.ommitFramePtr ||*/ sym->regsUsed) {
3592                                 /* restore stack frame */
3593                                 if(STACK_MODEL_LARGE)
3594                                         pic16_emitpcode(POC_MOVFF,
3595                                                 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3596                                 pic16_emitpcode(POC_MOVFF,
3597                                                 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3598                         }
3599                 }
3600
3601                 pic16_emitcode ("return","");
3602                 pic16_emitpcodeNULLop(POC_RETURN);
3603
3604                 /* Mark the end of a function */
3605                 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3606         }
3607
3608 }
3609
3610
3611 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3612 {
3613
3614         if(is_LitOp(op)) {
3615                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12
3616
3617                 if(dest->type != PO_WREG)
3618                         pic16_emitpcode(POC_MOVWF, dest);
3619         } else {
3620                 if(dest->type == PO_WREG && (offset == 0)) {
3621                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3622                         return;
3623                 }
3624                 
3625                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3626                         pic16_popGet(AOP(op), offset), dest));
3627         }
3628 }
3629
3630 /*-----------------------------------------------------------------*/
3631 /* genRet - generate code for return statement                     */
3632 /*-----------------------------------------------------------------*/
3633 static void genRet (iCode *ic)
3634 {
3635   int size;
3636   operand *left;
3637
3638         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3639         /* if we have no return value then
3640          * just generate the "ret" */
3641         
3642         if (!IC_LEFT(ic)) 
3643                 goto jumpret;       
3644     
3645         /* we have something to return then
3646          * move the return value into place */
3647         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3648         size = AOP_SIZE(IC_LEFT(ic));
3649
3650         if(size <= 4) {
3651                 if(size>3) {
3652                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3653 //                      pic16_emitpcode(POC_MOVFF,
3654 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3655                 }
3656                 if(size>2) {
3657                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3658 //                      pic16_emitpcode(POC_MOVFF,
3659 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3660                 }
3661                 if(size>1) {
3662                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3663 //                      pic16_emitpcode(POC_MOVFF,
3664 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3665                 }
3666
3667 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3668
3669                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3670 //              pic16_emitpcode(POC_MOVFF,
3671 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3672
3673         } else {
3674                 /* >32-bits, setup stack and FSR0 */
3675                 while (size--) {
3676 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3677 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3678
3679                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3680
3681 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3682                         GpsuedoStkPtr++;
3683                 }
3684                         
3685                 /* setup FSR0 */
3686                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3687                         pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3688
3689                 if(STACK_MODEL_LARGE) {
3690                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3691                                 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3692                 } else {
3693                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3694                 }
3695         }
3696                                 
3697 #if 0
3698         /* old code, left here for reference -- VR */    
3699         while (size--) {
3700           char *l ;
3701
3702                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3703                         /* #NOCHANGE */
3704                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3705                         pic16_emitpcomment("push %s",l);
3706                         pushed++;
3707                 } else {
3708                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3709                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3710                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3711                         
3712                         if (strcmp(fReturn[offset],l)) {
3713                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3714                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3715                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3716                                 } else {
3717                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3718                                 }
3719                                 
3720                                 if(size) {
3721                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3722                                 }
3723                                 offset++;
3724                         }
3725                 }
3726         }    
3727
3728         if (pushed) {
3729                 while(pushed) {
3730                         pushed--;
3731                         if (strcmp(fReturn[pushed],"a"))
3732                                 pic16_emitcode("pop",fReturn[pushed]);
3733                         else
3734                                 pic16_emitcode("pop","acc");
3735                 }
3736         }
3737 #endif
3738
3739
3740         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3741     
3742 jumpret:
3743         /* generate a jump to the return label
3744          * if the next is not the return statement */
3745         if (!(ic->next && ic->next->op == LABEL
3746                 && IC_LABEL(ic->next) == returnLabel)) {
3747         
3748                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3749                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3750         }
3751 }
3752
3753 /*-----------------------------------------------------------------*/
3754 /* genLabel - generates a label                                    */
3755 /*-----------------------------------------------------------------*/
3756 static void genLabel (iCode *ic)
3757 {
3758
3759
3760     /* special case never generate */
3761     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3762     if (IC_LABEL(ic) == entryLabel)
3763         return ;
3764
3765     pic16_emitpLabel(IC_LABEL(ic)->key);
3766     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3767 }
3768
3769 /*-----------------------------------------------------------------*/
3770 /* genGoto - generates a goto                                      */
3771 /*-----------------------------------------------------------------*/
3772 //tsd
3773 static void genGoto (iCode *ic)
3774 {
3775   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3776   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3777 }
3778
3779
3780 /*-----------------------------------------------------------------*/
3781 /* genMultbits :- multiplication of bits                           */
3782 /*-----------------------------------------------------------------*/
3783 static void genMultbits (operand *left, 
3784                          operand *right, 
3785                          operand *result)
3786 {
3787   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3788
3789   if(!pic16_sameRegs(AOP(result),AOP(right)))
3790     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3791
3792   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3793   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3794   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3795
3796 }
3797
3798
3799 /*-----------------------------------------------------------------*/
3800 /* genMultOneByte : 8 bit multiplication & division                */
3801 /*-----------------------------------------------------------------*/
3802 static void genMultOneByte (operand *left,
3803                             operand *right,
3804                             operand *result)
3805 {
3806
3807   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3808   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3809   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3810
3811   /* (if two literals, the value is computed before) */
3812   /* if one literal, literal on the right */
3813   if (AOP_TYPE(left) == AOP_LIT){
3814     operand *t = right;
3815     right = left;
3816     left = t;
3817   }
3818
3819         /* size is already checked in genMult == 1 */
3820 //      size = AOP_SIZE(result);
3821
3822         if (AOP_TYPE(right) == AOP_LIT){
3823                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3824                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3825                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3826                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3827         } else {
3828                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3829                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3830                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3831                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3832         }
3833         
3834         pic16_genMult8X8_8 (left, right,result);
3835 }
3836
3837 /*-----------------------------------------------------------------*/
3838 /* genMultOneWord : 16 bit multiplication                          */
3839 /*-----------------------------------------------------------------*/
3840 static void genMultOneWord (operand *left,
3841                             operand *right,
3842                             operand *result)
3843 {
3844
3845         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3846         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3847         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3848
3849         /* (if two literals, the value is computed before)
3850          * if one literal, literal on the right */
3851         if (AOP_TYPE(left) == AOP_LIT){
3852           operand *t = right;
3853                 right = left;
3854                 left = t;
3855         }
3856
3857         /* size is checked already == 2 */
3858 //      size = AOP_SIZE(result);
3859
3860         if (AOP_TYPE(right) == AOP_LIT) {
3861                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3862                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3863                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3864                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3865         } else {
3866                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3867                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3868                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3869                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3870         }
3871         
3872         pic16_genMult16X16_16(left, right,result);
3873 }
3874
3875 /*-----------------------------------------------------------------*/
3876 /* genMultOneLong : 32 bit multiplication                          */
3877 /*-----------------------------------------------------------------*/
3878 static void genMultOneLong (operand *left,
3879                             operand *right,
3880                             operand *result)
3881 {
3882
3883         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3884         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3885         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3886
3887         /* (if two literals, the value is computed before)
3888          * if one literal, literal on the right */
3889         if (AOP_TYPE(left) == AOP_LIT){
3890           operand *t = right;
3891                 right = left;
3892                 left = t;
3893         }
3894
3895         /* size is checked already == 4 */
3896 //      size = AOP_SIZE(result);
3897
3898         if (AOP_TYPE(right) == AOP_LIT) {
3899                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3900                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3901                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3902                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3903         } else {
3904                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3905                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3906                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3907                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3908         }
3909         
3910         pic16_genMult32X32_32(left, right,result);
3911 }
3912
3913
3914
3915 /*-----------------------------------------------------------------*/
3916 /* genMult - generates code for multiplication                     */
3917 /*-----------------------------------------------------------------*/
3918 static void genMult (iCode *ic)
3919 {
3920   operand *left = IC_LEFT(ic);
3921   operand *right = IC_RIGHT(ic);
3922   operand *result= IC_RESULT(ic);   
3923
3924         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3925         /* assign the amsops */
3926         pic16_aopOp (left,ic,FALSE);
3927         pic16_aopOp (right,ic,FALSE);
3928         pic16_aopOp (result,ic,TRUE);
3929
3930         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3931
3932         /* special cases first *
3933         * both are bits */
3934         if (AOP_TYPE(left) == AOP_CRY
3935                 && AOP_TYPE(right)== AOP_CRY) {
3936                 genMultbits(left,right,result);
3937           goto release ;
3938         }
3939
3940         /* if both are of size == 1 */
3941         if(AOP_SIZE(left) == 1
3942                 && AOP_SIZE(right) == 1) {
3943                 genMultOneByte(left,right,result);
3944           goto release ;
3945         }
3946
3947         /* if both are of size == 2 */
3948         if(AOP_SIZE(left) == 2
3949                 && AOP_SIZE(right) == 2) {
3950                 genMultOneWord(left, right, result);
3951           goto release;
3952         }
3953         
3954         /* if both are of size == 4 */
3955         if(AOP_SIZE(left) == 4
3956                 && AOP_SIZE(right) == 4) {
3957                 genMultOneLong(left, right, result);
3958           goto release;
3959         }
3960         
3961         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
3962
3963
3964         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
3965         /* should have been converted to function call */
3966         assert(0) ;
3967
3968 release :
3969         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3970         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3971         pic16_freeAsmop(result,NULL,ic,TRUE); 
3972 }
3973
3974 /*-----------------------------------------------------------------*/
3975 /* genDivbits :- division of bits                                  */
3976 /*-----------------------------------------------------------------*/
3977 static void genDivbits (operand *left, 
3978                         operand *right, 
3979                         operand *result)
3980 {
3981
3982     char *l;
3983
3984     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3985     /* the result must be bit */    
3986     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3987     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3988
3989     MOVA(l);    
3990
3991     pic16_emitcode("div","ab");
3992     pic16_emitcode("rrc","a");
3993     pic16_aopPut(AOP(result),"c",0);
3994 }
3995
3996 /*-----------------------------------------------------------------*/
3997 /* genDivOneByte : 8 bit division                                  */
3998 /*-----------------------------------------------------------------*/
3999 static void genDivOneByte (operand *left,
4000                            operand *right,
4001                            operand *result)
4002 {
4003     sym_link *opetype = operandType(result);
4004     char *l ;
4005     symbol *lbl ;
4006     int size,offset;
4007
4008         /* result = divident / divisor
4009          * - divident may be a register or a literal,
4010          * - divisor may be a register or a literal,
4011          * so there are 3 cases (literal / literal is optimized
4012          * by the front-end) to handle.
4013          * In addition we must handle signed and unsigned, which
4014          * result in 6 final different cases -- VR */
4015
4016     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4017     size = AOP_SIZE(result) - 1;
4018     offset = 1;
4019     /* signed or unsigned */
4020     if (SPEC_USIGN(opetype)) {
4021       pCodeOp *pct1,    /* count */
4022                 *pct2,  /* reste */
4023                 *pct3;  /* temp */
4024       symbol *label1, *label2, *label3;;
4025
4026
4027         /* unsigned is easy */
4028
4029         pct1 = pic16_popGetTempReg();
4030         pct2 = pic16_popGetTempReg();
4031         pct3 = pic16_popGetTempReg();
4032         
4033         label1 = newiTempLabel(NULL);
4034         label2 = newiTempLabel(NULL);
4035         label3 = newiTempLabel(NULL);
4036
4037         /* the following algorithm is extracted from divuint.c */
4038
4039         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4040         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4041         
4042         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4043
4044         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4045         
4046         pic16_emitpLabel(label1->key);
4047         
4048         emitCLRC;
4049         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4050
4051
4052         emitCLRC;
4053         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4054         
4055
4056         emitSKPNC;
4057         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4058         
4059         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4060         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4061         
4062         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4063         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4064         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4065         
4066         pic16_emitpLabel( label3->key );
4067         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4068         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4069         
4070         
4071
4072         pic16_emitpLabel(label2->key);
4073         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4074         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4075         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4076         
4077         /* result is in wreg */
4078         if(AOP_TYPE(result) != AOP_ACC)
4079                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4080
4081         pic16_popReleaseTempReg( pct3 );
4082         pic16_popReleaseTempReg( pct2 );
4083         pic16_popReleaseTempReg( pct1 );
4084
4085         return ;
4086     }
4087
4088     /* signed is a little bit more difficult */
4089
4090     /* save the signs of the operands */
4091     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4092     MOVA(l);    
4093     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4094     pic16_emitcode("push","acc"); /* save it on the stack */
4095
4096     /* now sign adjust for both left & right */
4097     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4098     MOVA(l);       
4099     lbl = newiTempLabel(NULL);
4100     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4101     pic16_emitcode("cpl","a");   
4102     pic16_emitcode("inc","a");
4103     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4104     pic16_emitcode("mov","b,a");
4105
4106     /* sign adjust left side */
4107     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4108     MOVA(l);
4109
4110     lbl = newiTempLabel(NULL);
4111     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4112     pic16_emitcode("cpl","a");
4113     pic16_emitcode("inc","a");
4114     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4115
4116     /* now the division */
4117     pic16_emitcode("div","ab");
4118     /* we are interested in the lower order
4119     only */
4120     pic16_emitcode("mov","b,a");
4121     lbl = newiTempLabel(NULL);
4122     pic16_emitcode("pop","acc");   
4123     /* if there was an over flow we don't 
4124     adjust the sign of the result */
4125     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4126     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4127     CLRC;
4128     pic16_emitcode("clr","a");
4129     pic16_emitcode("subb","a,b");
4130     pic16_emitcode("mov","b,a");
4131     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4132
4133     /* now we are done */
4134     pic16_aopPut(AOP(result),"b",0);
4135     if(size > 0){
4136         pic16_emitcode("mov","c,b.7");
4137         pic16_emitcode("subb","a,acc");   
4138     }
4139     while (size--)
4140         pic16_aopPut(AOP(result),"a",offset++);
4141
4142 }
4143
4144 /*-----------------------------------------------------------------*/
4145 /* genDiv - generates code for division                            */
4146 /*-----------------------------------------------------------------*/
4147 static void genDiv (iCode *ic)
4148 {
4149     operand *left = IC_LEFT(ic);
4150     operand *right = IC_RIGHT(ic);
4151     operand *result= IC_RESULT(ic);   
4152
4153
4154         /* Division is a very lengthy algorithm, so it is better
4155          * to call support routines than inlining algorithm.
4156          * Division functions written here just in case someone
4157          * wants to inline and not use the support libraries -- VR */
4158
4159     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4160     /* assign the amsops */
4161     pic16_aopOp (left,ic,FALSE);
4162     pic16_aopOp (right,ic,FALSE);
4163     pic16_aopOp (result,ic,TRUE);
4164
4165     /* special cases first */
4166     /* both are bits */
4167     if (AOP_TYPE(left) == AOP_CRY &&
4168         AOP_TYPE(right)== AOP_CRY) {
4169         genDivbits(left,right,result);
4170         goto release ;
4171     }
4172
4173     /* if both are of size == 1 */
4174     if (AOP_SIZE(left) == 1 &&
4175         AOP_SIZE(right) == 1 ) {
4176         genDivOneByte(left,right,result);
4177         goto release ;
4178     }
4179
4180     /* should have been converted to function call */
4181     assert(0);
4182 release :
4183     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4184     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4185     pic16_freeAsmop(result,NULL,ic,TRUE); 
4186 }
4187
4188 /*-----------------------------------------------------------------*/
4189 /* genModbits :- modulus of bits                                   */
4190 /*-----------------------------------------------------------------*/
4191 static void genModbits (operand *left, 
4192                         operand *right, 
4193                         operand *result)
4194 {
4195
4196     char *l;
4197
4198     /* the result must be bit */    
4199     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4200     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4201
4202     MOVA(l);       
4203
4204     pic16_emitcode("div","ab");
4205     pic16_emitcode("mov","a,b");
4206     pic16_emitcode("rrc","a");
4207     pic16_aopPut(AOP(result),"c",0);
4208 }
4209
4210 /*-----------------------------------------------------------------*/
4211 /* genModOneByte : 8 bit modulus                                   */
4212 /*-----------------------------------------------------------------*/
4213 static void genModOneByte (operand *left,
4214                            operand *right,
4215                            operand *result)
4216 {
4217     sym_link *opetype = operandType(result);
4218     char *l ;
4219     symbol *lbl ;
4220
4221     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4222     /* signed or unsigned */
4223     if (SPEC_USIGN(opetype)) {
4224         /* unsigned is easy */
4225         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4226         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4227         MOVA(l);    
4228         pic16_emitcode("div","ab");
4229         pic16_aopPut(AOP(result),"b",0);
4230         return ;
4231     }
4232
4233     /* signed is a little bit more difficult */
4234
4235     /* save the signs of the operands */
4236     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4237     MOVA(l);
4238
4239     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4240     pic16_emitcode("push","acc"); /* save it on the stack */
4241
4242     /* now sign adjust for both left & right */
4243     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4244     MOVA(l);
4245
4246     lbl = newiTempLabel(NULL);
4247     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4248     pic16_emitcode("cpl","a");   
4249     pic16_emitcode("inc","a");
4250     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4251     pic16_emitcode("mov","b,a"); 
4252
4253     /* sign adjust left side */
4254     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4255     MOVA(l);
4256
4257     lbl = newiTempLabel(NULL);
4258     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4259     pic16_emitcode("cpl","a");   
4260     pic16_emitcode("inc","a");
4261     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4262
4263     /* now the multiplication */
4264     pic16_emitcode("div","ab");
4265     /* we are interested in the lower order
4266     only */
4267     lbl = newiTempLabel(NULL);
4268     pic16_emitcode("pop","acc");   
4269     /* if there was an over flow we don't 
4270     adjust the sign of the result */
4271     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4272     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4273     CLRC ;
4274     pic16_emitcode("clr","a");
4275     pic16_emitcode("subb","a,b");
4276     pic16_emitcode("mov","b,a");
4277     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4278
4279     /* now we are done */
4280     pic16_aopPut(AOP(result),"b",0);
4281
4282 }
4283
4284 /*-----------------------------------------------------------------*/
4285 /* genMod - generates code for division                            */
4286 /*-----------------------------------------------------------------*/
4287 static void genMod (iCode *ic)
4288 {
4289     operand *left = IC_LEFT(ic);
4290     operand *right = IC_RIGHT(ic);
4291     operand *result= IC_RESULT(ic);  
4292
4293     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4294     /* assign the amsops */
4295     pic16_aopOp (left,ic,FALSE);
4296     pic16_aopOp (right,ic,FALSE);
4297     pic16_aopOp (result,ic,TRUE);
4298
4299     /* special cases first */
4300     /* both are bits */
4301     if (AOP_TYPE(left) == AOP_CRY &&
4302         AOP_TYPE(right)== AOP_CRY) {
4303         genModbits(left,right,result);
4304         goto release ;
4305     }
4306
4307     /* if both are of size == 1 */
4308     if (AOP_SIZE(left) == 1 &&
4309         AOP_SIZE(right) == 1 ) {
4310         genModOneByte(left,right,result);
4311         goto release ;
4312     }
4313
4314     /* should have been converted to function call */
4315     assert(0);
4316
4317 release :
4318     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4319     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4320     pic16_freeAsmop(result,NULL,ic,TRUE); 
4321 }
4322
4323 /*-----------------------------------------------------------------*/
4324 /* genIfxJump :- will create a jump depending on the ifx           */
4325 /*-----------------------------------------------------------------*/
4326 /*
4327   note: May need to add parameter to indicate when a variable is in bit space.
4328 */
4329 static void genIfxJump (iCode *ic, char *jval)
4330 {
4331
4332     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4333     /* if true label then we jump if condition
4334     supplied is true */
4335     if ( IC_TRUE(ic) ) {
4336
4337         if(strcmp(jval,"a") == 0)
4338           emitSKPZ;
4339         else if (strcmp(jval,"c") == 0)
4340           emitSKPC;
4341         else {
4342           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4343           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4344         }
4345
4346         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4347         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4348
4349     }
4350     else {
4351         /* false label is present */
4352         if(strcmp(jval,"a") == 0)
4353           emitSKPNZ;
4354         else if (strcmp(jval,"c") == 0)
4355           emitSKPNC;
4356         else {
4357           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4358           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4359         }
4360
4361         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4362         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4363
4364     }
4365
4366
4367     /* mark the icode as generated */
4368     ic->generated = 1;
4369 }
4370
4371 #if 0
4372 // not needed ATM
4373
4374 /*-----------------------------------------------------------------*/
4375 /* genSkip                                                         */
4376 /*-----------------------------------------------------------------*/
4377 static void genSkip(iCode *ifx,int status_bit)
4378 {
4379   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4380   if(!ifx)
4381     return;
4382
4383   if ( IC_TRUE(ifx) ) {
4384     switch(status_bit) {
4385     case 'z':
4386       emitSKPNZ;
4387       break;
4388
4389     case 'c':
4390       emitSKPNC;
4391       break;
4392
4393     case 'd':
4394       emitSKPDC;
4395       break;
4396
4397     }
4398
4399     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4400     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4401
4402   } else {
4403
4404     switch(status_bit) {
4405
4406     case 'z':
4407       emitSKPZ;
4408       break;
4409
4410     case 'c':
4411       emitSKPC;
4412       break;
4413
4414     case 'd':
4415       emitSKPDC;
4416       break;
4417     }
4418     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4419     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4420
4421   }
4422
4423 }
4424 #endif
4425
4426 /*-----------------------------------------------------------------*/
4427 /* genSkipc                                                        */
4428 /*-----------------------------------------------------------------*/
4429 static void genSkipc(resolvedIfx *rifx)
4430 {
4431   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4432   
4433   if(!rifx)
4434     return;
4435
4436   if(rifx->condition)
4437     emitSKPC;
4438   else
4439     emitSKPNC;
4440
4441   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4442   rifx->generated = 1;
4443 }
4444
4445 /*-----------------------------------------------------------------*/
4446 /* genSkipz2                                                       */
4447 /*-----------------------------------------------------------------*/
4448 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4449 {
4450   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4451   
4452   if(!rifx)
4453     return;
4454
4455   if( (rifx->condition ^ invert_condition) & 1)
4456     emitSKPZ;
4457   else
4458     emitSKPNZ;
4459
4460   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4461   rifx->generated = 1;
4462 }
4463
4464 #if 0
4465 /*-----------------------------------------------------------------*/
4466 /* genSkipz                                                        */
4467 /*-----------------------------------------------------------------*/
4468 static void genSkipz(iCode *ifx, int condition)
4469 {
4470   if(!ifx)
4471     return;
4472
4473   if(condition)
4474     emitSKPNZ;
4475   else
4476     emitSKPZ;
4477
4478   if ( IC_TRUE(ifx) )
4479     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4480   else
4481     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4482
4483   if ( IC_TRUE(ifx) )
4484     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4485   else
4486     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4487
4488 }
4489 #endif
4490
4491 /*-----------------------------------------------------------------*/
4492 /* genSkipCond                                                     */
4493 /*-----------------------------------------------------------------*/
4494 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4495 {
4496   if(!rifx)
4497     return;
4498
4499   if(rifx->condition)
4500     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4501   else
4502     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4503
4504
4505   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4506   rifx->generated = 1;
4507 }
4508
4509 #if 0
4510 /*-----------------------------------------------------------------*/
4511 /* genChkZeroes :- greater or less than comparison                 */
4512 /*     For each byte in a literal that is zero, inclusive or the   */
4513 /*     the corresponding byte in the operand with W                */
4514 /*     returns true if any of the bytes are zero                   */
4515 /*-----------------------------------------------------------------*/
4516 static int genChkZeroes(operand *op, int lit,  int size)
4517 {
4518
4519   int i;
4520   int flag =1;
4521
4522   while(size--) {
4523     i = (lit >> (size*8)) & 0xff;
4524
4525     if(i==0) {
4526       if(flag) 
4527         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4528       else
4529         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4530       flag = 0;
4531     }
4532   }
4533
4534   return (flag==0);
4535 }
4536 #endif
4537
4538 /*-----------------------------------------------------------------*/
4539 /* genCmp :- greater or less than comparison                       */
4540 /*-----------------------------------------------------------------*/
4541 static void genCmp (operand *left,operand *right,
4542                     operand *result, iCode *ifx, int sign)
4543 {
4544   int size; //, offset = 0 ;
4545   unsigned long lit = 0L,i = 0;
4546   resolvedIfx rFalseIfx;
4547   //  resolvedIfx rTrueIfx;
4548   symbol *truelbl;
4549   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4550 /*
4551   if(ifx) {
4552     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4553     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4554   }
4555 */
4556
4557   resolveIfx(&rFalseIfx,ifx);
4558   truelbl  = newiTempLabel(NULL);
4559   size = max(AOP_SIZE(left),AOP_SIZE(right));
4560
4561   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4562
4563 #define _swapp
4564
4565   /* if literal is on the right then swap with left */
4566   if ((AOP_TYPE(right) == AOP_LIT)) {
4567     operand *tmp = right ;
4568     unsigned long mask = (0x100 << (8*(size-1))) - 1;
4569     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4570 #ifdef _swapp
4571
4572     lit = (lit - 1) & mask;
4573     right = left;
4574     left = tmp;
4575     rFalseIfx.condition ^= 1;
4576 #endif
4577
4578   } else if ((AOP_TYPE(left) == AOP_LIT)) {
4579     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4580   }
4581
4582
4583   //if(IC_TRUE(ifx) == NULL)
4584   /* if left & right are bit variables */
4585   if (AOP_TYPE(left) == AOP_CRY &&
4586       AOP_TYPE(right) == AOP_CRY ) {
4587     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4588     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4589   } else {
4590     /* subtract right from left if at the
4591        end the carry flag is set then we know that
4592        left is greater than right */
4593
4594     symbol *lbl  = newiTempLabel(NULL);
4595
4596 #if 0
4597         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4598                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
4599 #endif
4600
4601 #ifndef _swapp
4602     if(AOP_TYPE(right) == AOP_LIT) {
4603
4604       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4605
4606       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4607
4608       /* special cases */
4609
4610       if(lit == 0) {
4611
4612         if(sign != 0) 
4613           genSkipCond(&rFalseIfx,left,size-1,7);
4614         else 
4615           /* no need to compare to 0...*/
4616           /* NOTE: this is a de-generate compare that most certainly 
4617            *       creates some dead code. */
4618           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4619
4620         if(ifx) ifx->generated = 1;
4621         return;
4622
4623       }
4624       size--;
4625
4626       if(size == 0) {
4627         //i = (lit >> (size*8)) & 0xff;
4628         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4629         
4630         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4631
4632         i = ((0-lit) & 0xff);
4633         if(sign) {
4634           if( i == 0x81) { 
4635             /* lit is 0x7f, all signed chars are less than
4636              * this except for 0x7f itself */
4637             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4638             genSkipz2(&rFalseIfx,0);
4639           } else {
4640             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4641             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4642             genSkipc(&rFalseIfx);
4643           }
4644
4645         } else {
4646           if(lit == 1) {
4647             genSkipz2(&rFalseIfx,1);
4648           } else {
4649             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4650             genSkipc(&rFalseIfx);
4651           }
4652         }
4653
4654         if(ifx) ifx->generated = 1;
4655         return;
4656       }
4657
4658       /* chars are out of the way. now do ints and longs */
4659
4660
4661       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4662         
4663       /* special cases */
4664
4665       if(sign) {
4666
4667         if(lit == 0) {
4668           genSkipCond(&rFalseIfx,left,size,7);
4669           if(ifx) ifx->generated = 1;
4670           return;
4671         }
4672
4673         if(lit <0x100) {
4674           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4675
4676           //rFalseIfx.condition ^= 1;
4677           //genSkipCond(&rFalseIfx,left,size,7);
4678           //rFalseIfx.condition ^= 1;
4679
4680           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4681           if(rFalseIfx.condition)
4682             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4683           else
4684             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4685
4686           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4687           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4688           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4689
4690           while(size > 1)
4691             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4692
4693           if(rFalseIfx.condition) {
4694             emitSKPZ;
4695             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4696
4697           } else {
4698             emitSKPNZ;
4699           }
4700
4701           genSkipc(&rFalseIfx);
4702           pic16_emitpLabel(truelbl->key);
4703           if(ifx) ifx->generated = 1;
4704           return;
4705
4706         }
4707
4708         if(size == 1) {
4709
4710           if( (lit & 0xff) == 0) {
4711             /* lower byte is zero */
4712             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4713             i = ((lit >> 8) & 0xff) ^0x80;
4714             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4715             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4716             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4717             genSkipc(&rFalseIfx);
4718
4719
4720             if(ifx) ifx->generated = 1;
4721             return;
4722
4723           }
4724         } else {
4725           /* Special cases for signed longs */
4726           if( (lit & 0xffffff) == 0) {
4727             /* lower byte is zero */
4728             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4729             i = ((lit >> 8*3) & 0xff) ^0x80;
4730             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4731             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4732             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4733             genSkipc(&rFalseIfx);
4734
4735
4736             if(ifx) ifx->generated = 1;
4737             return;
4738
4739           }
4740
4741         }
4742
4743
4744         if(lit & (0x80 << (size*8))) {
4745           /* lit is negative */
4746           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4747
4748           //genSkipCond(&rFalseIfx,left,size,7);
4749
4750           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4751
4752           if(rFalseIfx.condition)
4753             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4754           else
4755             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4756
4757
4758         } else {
4759           /* lit is positive */
4760           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4761           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4762           if(rFalseIfx.condition)
4763             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4764           else
4765             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4766
4767         }
4768
4769         /*
4770           This works, but is only good for ints.
4771           It also requires a "known zero" register.
4772           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4773           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4774           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4775           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4776           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4777           genSkipc(&rFalseIfx);
4778
4779           pic16_emitpLabel(truelbl->key);
4780           if(ifx) ifx->generated = 1;
4781           return;
4782         **/
4783           
4784         /* There are no more special cases, so perform a general compare */
4785   
4786         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4787         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4788
4789         while(size--) {
4790
4791           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4792           emitSKPNZ;
4793           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4794         }
4795         //rFalseIfx.condition ^= 1;
4796         genSkipc(&rFalseIfx);
4797
4798         pic16_emitpLabel(truelbl->key);
4799
4800         if(ifx) ifx->generated = 1;
4801         return;
4802
4803
4804       }
4805
4806
4807       /* sign is out of the way. So now do an unsigned compare */
4808       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4809
4810
4811       /* General case - compare to an unsigned literal on the right.*/
4812
4813       i = (lit >> (size*8)) & 0xff;
4814       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4815       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4816       while(size--) {
4817         i = (lit >> (size*8)) & 0xff;
4818
4819         if(i) {
4820           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4821           emitSKPNZ;
4822           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4823         } else {
4824           /* this byte of the lit is zero, 
4825            *if it's not the last then OR in the variable */
4826           if(size)
4827             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4828         }
4829       }
4830
4831
4832       pic16_emitpLabel(lbl->key);
4833 //      pic16_emitpLabel(truelbl->key);
4834       //if(emitFinalCheck)
4835       genSkipc(&rFalseIfx);
4836       if(sign)
4837         pic16_emitpLabel(truelbl->key);
4838
4839       if(ifx) ifx->generated = 1;
4840       return;
4841
4842
4843     }
4844 #endif  // _swapp
4845
4846     if(AOP_TYPE(left) == AOP_LIT) {
4847       //symbol *lbl = newiTempLabel(NULL);
4848
4849       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4850
4851
4852       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4853
4854       /* Special cases */
4855       if((lit == 0) && (sign == 0)){
4856
4857         size--;
4858         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4859         while(size) 
4860           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4861
4862         genSkipz2(&rFalseIfx,0);
4863         if(ifx) ifx->generated = 1;
4864         return;
4865       }
4866
4867       if(size==1) {
4868         /* Special cases */
4869         lit &= 0xff;
4870         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4871           /* degenerate compare can never be true */
4872           if(rFalseIfx.condition == 0)
4873             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4874
4875           if(ifx) ifx->generated = 1;
4876           return;
4877         }
4878
4879         if(sign) {
4880           /* signed comparisons to a literal byte */
4881
4882           int lp1 = (lit+1) & 0xff;
4883
4884           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4885           switch (lp1) {
4886           case 0:
4887             rFalseIfx.condition ^= 1;
4888             genSkipCond(&rFalseIfx,right,0,7);
4889             break;
4890           case 0x7f:
4891             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4892             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4893             genSkipz2(&rFalseIfx,1);
4894             break;
4895           default:
4896             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4897             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4898             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4899             rFalseIfx.condition ^= 1;
4900             genSkipc(&rFalseIfx);
4901             break;
4902           }
4903         } else {
4904           /* unsigned comparisons to a literal byte */
4905
4906           switch(lit & 0xff ) {
4907           case 0:
4908             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4909             genSkipz2(&rFalseIfx,0);
4910             break;
4911           case 0x7f:
4912             rFalseIfx.condition ^= 1;
4913             genSkipCond(&rFalseIfx,right,0,7);
4914             break;
4915
4916           default:
4917             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4918             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4919             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4920             rFalseIfx.condition ^= 1;
4921             if (AOP_TYPE(result) == AOP_CRY)
4922               genSkipc(&rFalseIfx);
4923             else {
4924               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4925               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4926             }         
4927             break;
4928           }
4929         }
4930
4931         if(ifx) ifx->generated = 1;
4932         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
4933                 goto check_carry;
4934         return;
4935
4936       } else {
4937
4938         /* Size is greater than 1 */
4939
4940         if(sign) {
4941           int lp1 = lit+1;
4942
4943           size--;
4944
4945           if(lp1 == 0) {
4946             /* this means lit = 0xffffffff, or -1 */
4947
4948
4949             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4950             rFalseIfx.condition ^= 1;
4951             genSkipCond(&rFalseIfx,right,size,7);
4952             if(ifx) ifx->generated = 1;
4953             return;
4954           }
4955
4956           if(lit == 0) {
4957             int s = size;
4958
4959             if(rFalseIfx.condition) {
4960               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4961               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4962             }
4963
4964             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4965             while(size--)
4966               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4967
4968
4969             emitSKPZ;
4970             if(rFalseIfx.condition) {
4971               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4972               pic16_emitpLabel(truelbl->key);
4973             }else {
4974               rFalseIfx.condition ^= 1;
4975               genSkipCond(&rFalseIfx,right,s,7);
4976             }
4977
4978             if(ifx) ifx->generated = 1;
4979             return;
4980           }
4981
4982           if((size == 1) &&  (0 == (lp1&0xff))) {
4983             /* lower byte of signed word is zero */
4984             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4985             i = ((lp1 >> 8) & 0xff) ^0x80;
4986             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4987             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4988             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4989             rFalseIfx.condition ^= 1;
4990             genSkipc(&rFalseIfx);
4991
4992
4993             if(ifx) ifx->generated = 1;
4994             return;
4995           }
4996
4997           if(lit & (0x80 << (size*8))) {
4998             /* Lit is less than zero */
4999             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5000             //rFalseIfx.condition ^= 1;
5001             //genSkipCond(&rFalseIfx,left,size,7);
5002             //rFalseIfx.condition ^= 1;
5003             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5004             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5005
5006             if(rFalseIfx.condition)
5007               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5008             else
5009               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5010
5011
5012           } else {
5013             /* Lit is greater than or equal to zero */
5014             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5015             //rFalseIfx.condition ^= 1;
5016             //genSkipCond(&rFalseIfx,right,size,7);
5017             //rFalseIfx.condition ^= 1;
5018
5019             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5020             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5021
5022             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5023             if(rFalseIfx.condition)
5024               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5025             else
5026               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5027
5028           }
5029
5030
5031           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5032           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5033
5034           while(size--) {
5035
5036             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5037             emitSKPNZ;
5038             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5039           }
5040           rFalseIfx.condition ^= 1;
5041           //rFalseIfx.condition = 1;
5042           genSkipc(&rFalseIfx);
5043
5044           pic16_emitpLabel(truelbl->key);
5045
5046           if(ifx) ifx->generated = 1;
5047           return;
5048           // end of if (sign)
5049         } else {
5050
5051           /* compare word or long to an unsigned literal on the right.*/
5052
5053
5054           size--;
5055           if(lit < 0xff) {
5056             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5057             switch (lit) {
5058             case 0:
5059               break; /* handled above */
5060 /*
5061             case 0xff:
5062               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5063               while(size--)
5064                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5065               genSkipz2(&rFalseIfx,0);
5066               break;
5067 */
5068             default:
5069               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5070               while(--size)
5071                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5072
5073               emitSKPZ;
5074               if(rFalseIfx.condition)
5075                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5076               else
5077                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5078
5079
5080               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5081               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5082
5083               rFalseIfx.condition ^= 1;
5084               genSkipc(&rFalseIfx);
5085             }
5086
5087             pic16_emitpLabel(truelbl->key);
5088
5089             if(ifx) ifx->generated = 1;
5090             return;
5091           }
5092
5093
5094           lit++;
5095           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5096           i = (lit >> (size*8)) & 0xff;
5097
5098           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5099           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5100
5101           while(size--) {
5102             i = (lit >> (size*8)) & 0xff;
5103
5104             if(i) {
5105               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5106               emitSKPNZ;
5107               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5108             } else {
5109               /* this byte of the lit is zero, 
5110                * if it's not the last then OR in the variable */
5111               if(size)
5112                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5113             }
5114           }
5115
5116
5117           pic16_emitpLabel(lbl->key);
5118
5119           rFalseIfx.condition ^= 1;
5120
5121           genSkipc(&rFalseIfx);
5122         }
5123
5124         if(sign)
5125           pic16_emitpLabel(truelbl->key);
5126         if(ifx) ifx->generated = 1;
5127         return;
5128       }
5129     }
5130     /* Compare two variables */
5131
5132     DEBUGpic16_emitcode(";sign","%d",sign);
5133
5134     size--;
5135     if(sign) {
5136       /* Sigh. thus sucks... */
5137       if(size) {
5138         pCodeOp *pctemp;
5139         
5140         pctemp = pic16_popGetTempReg();
5141         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5142         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5143         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5144         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5145         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5146         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5147         pic16_popReleaseTempReg(pctemp);
5148       } else {
5149         /* Signed char comparison */
5150         /* Special thanks to Nikolai Golovchenko for this snippet */
5151         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5152         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5153         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5154         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5155         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5156         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5157
5158         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5159         genSkipc(&rFalseIfx);
5160           
5161         if(ifx) ifx->generated = 1;
5162         return;
5163       }
5164
5165     } else {
5166
5167       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5168       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5169     }
5170
5171
5172     /* The rest of the bytes of a multi-byte compare */
5173     while (size) {
5174
5175       emitSKPZ;
5176       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5177       size--;
5178
5179       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5180       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5181
5182
5183     }
5184
5185     pic16_emitpLabel(lbl->key);
5186
5187     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5188     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5189         (AOP_TYPE(result) == AOP_REG)) {
5190       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5191       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5192     } else {
5193       genSkipc(&rFalseIfx);
5194     }         
5195     //genSkipc(&rFalseIfx);
5196     if(ifx) ifx->generated = 1;
5197
5198     return;
5199
5200   }
5201
5202 check_carry:
5203   if ((AOP_TYPE(result) != AOP_CRY) 
5204         && AOP_SIZE(result)) {
5205     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5206
5207     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5208
5209     pic16_outBitC(result);
5210   } else {
5211     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5212     /* if the result is used in the next
5213        ifx conditional branch then generate
5214        code a little differently */
5215     if (ifx )
5216       genIfxJump (ifx,"c");
5217     else
5218       pic16_outBitC(result);
5219     /* leave the result in acc */
5220   }
5221
5222 }
5223
5224 /*-----------------------------------------------------------------*/
5225 /* genCmpGt :- greater than comparison                             */
5226 /*-----------------------------------------------------------------*/
5227 static void genCmpGt (iCode *ic, iCode *ifx)
5228 {
5229     operand *left, *right, *result;
5230     sym_link *letype , *retype;
5231     int sign ;
5232
5233     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5234     left = IC_LEFT(ic);
5235     right= IC_RIGHT(ic);
5236     result = IC_RESULT(ic);
5237
5238     letype = getSpec(operandType(left));
5239     retype =getSpec(operandType(right));
5240     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5241     /* assign the amsops */
5242     pic16_aopOp (left,ic,FALSE);
5243     pic16_aopOp (right,ic,FALSE);
5244     pic16_aopOp (result,ic,TRUE);
5245
5246     genCmp(right, left, result, ifx, sign);
5247
5248     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5249     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5250     pic16_freeAsmop(result,NULL,ic,TRUE); 
5251 }
5252
5253 /*-----------------------------------------------------------------*/
5254 /* genCmpLt - less than comparisons                                */
5255 /*-----------------------------------------------------------------*/
5256 static void genCmpLt (iCode *ic, iCode *ifx)
5257 {
5258     operand *left, *right, *result;
5259     sym_link *letype , *retype;
5260     int sign ;
5261
5262     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5263     left = IC_LEFT(ic);
5264     right= IC_RIGHT(ic);
5265     result = IC_RESULT(ic);
5266
5267     letype = getSpec(operandType(left));
5268     retype =getSpec(operandType(right));
5269     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5270
5271     /* assign the amsops */
5272     pic16_aopOp (left,ic,FALSE);
5273     pic16_aopOp (right,ic,FALSE);
5274     pic16_aopOp (result,ic,TRUE);
5275
5276     genCmp(left, right, result, ifx, sign);
5277
5278     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5279     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5280     pic16_freeAsmop(result,NULL,ic,TRUE); 
5281 }
5282
5283 #if 0
5284 // not needed ATM
5285 // FIXME reenable literal optimisation when the pic16 port is stable
5286
5287 /*-----------------------------------------------------------------*/
5288 /* genc16bit2lit - compare a 16 bit value to a literal             */
5289 /*-----------------------------------------------------------------*/
5290 static void genc16bit2lit(operand *op, int lit, int offset)
5291 {
5292   int i;
5293
5294   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
5295   if( (lit&0xff) == 0) 
5296     i=1;
5297   else
5298     i=0;
5299
5300   switch( BYTEofLONG(lit,i)) { 
5301   case 0:
5302     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5303     break;
5304   case 1:
5305     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5306     break;
5307   case 0xff:
5308     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5309     break;
5310   default:
5311     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5312     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5313   }
5314
5315   i ^= 1;
5316
5317   switch( BYTEofLONG(lit,i)) { 
5318   case 0:
5319     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5320     break;
5321   case 1:
5322     emitSKPNZ;
5323     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5324     break;
5325   case 0xff:
5326     emitSKPNZ;
5327     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5328     break;
5329   default:
5330     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5331     emitSKPNZ;
5332     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5333
5334   }
5335
5336 }
5337 #endif
5338
5339 #if 0
5340 // not needed ATM
5341 /*-----------------------------------------------------------------*/
5342 /* gencjneshort - compare and jump if not equal                    */
5343 /*-----------------------------------------------------------------*/
5344 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5345 {
5346   int size = max(AOP_SIZE(left),AOP_SIZE(right));
5347   int offset = 0;
5348   int res_offset = 0;  /* the result may be a different size then left or right */
5349   int res_size = AOP_SIZE(result);
5350   resolvedIfx rIfx;
5351   symbol *lbl, *lbl_done;
5352
5353   unsigned long lit = 0L;
5354   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5355
5356   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5357   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5358   if(result)
5359     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
5360   resolveIfx(&rIfx,ifx);
5361   lbl =  newiTempLabel(NULL);
5362   lbl_done =  newiTempLabel(NULL);
5363
5364
5365   /* if the left side is a literal or 
5366      if the right is in a pointer register and left 
5367      is not */
5368   if ((AOP_TYPE(left) == AOP_LIT) || 
5369       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5370     operand *t = right;
5371     right = left;
5372     left = t;
5373   }
5374   if(AOP_TYPE(right) == AOP_LIT)
5375     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5376
5377   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5378     preserve_result = 1;
5379
5380   if(result && !preserve_result)
5381     {
5382       int i;
5383       for(i = 0; i < AOP_SIZE(result); i++)
5384         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5385     }
5386
5387
5388   /* if the right side is a literal then anything goes */
5389   if (AOP_TYPE(right) == AOP_LIT &&
5390       AOP_TYPE(left) != AOP_DIR ) {
5391     switch(size) {
5392     case 2:
5393       genc16bit2lit(left, lit, 0);
5394       emitSKPZ;
5395       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5396       break;
5397     default:
5398       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5399       while (size--) {
5400         if(lit & 0xff) {
5401           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5402           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5403         } else {
5404           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5405         }
5406
5407         emitSKPZ;
5408         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5409         offset++;
5410         if(res_offset < res_size-1)
5411           res_offset++;
5412         lit >>= 8;
5413       }
5414       break;
5415     }
5416   }
5417
5418   /* if the right side is in a register or in direct space or
5419      if the left is a pointer register & right is not */    
5420   else if (AOP_TYPE(right) == AOP_REG ||
5421            AOP_TYPE(right) == AOP_DIR || 
5422            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5423            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5424     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5425     int lbl_key = lbl->key;
5426
5427     if(result) {
5428       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5429       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5430     }else {
5431       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5432       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5433               __FUNCTION__,__LINE__);
5434       return;
5435     }
5436    
5437 /*     switch(size) { */
5438 /*     case 2: */
5439 /*       genc16bit2lit(left, lit, 0); */
5440 /*       emitSKPNZ; */
5441 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5442 /*       break; */
5443 /*     default: */
5444     while (size--) {
5445       int emit_skip=1;
5446       if((AOP_TYPE(left) == AOP_DIR) && 
5447          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5448
5449         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5450         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5451
5452       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5453             
5454         switch (lit & 0xff) {
5455         case 0:
5456           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5457           break;
5458         case 1:
5459           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5460           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5461           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5462           emit_skip=0;
5463           break;
5464         case 0xff:
5465           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5466           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5467           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5468           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5469           emit_skip=0;
5470           break;
5471         default:
5472           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5473           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5474         }
5475         lit >>= 8;
5476
5477       } else {
5478         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5479       }
5480       if(emit_skip) {
5481         if(AOP_TYPE(result) == AOP_CRY) {
5482           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5483           if(rIfx.condition)
5484             emitSKPNZ;
5485           else
5486             emitSKPZ;
5487           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5488         } else {
5489           /* fix me. probably need to check result size too */
5490           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5491           if(rIfx.condition)
5492             emitSKPZ;
5493           else
5494             emitSKPNZ;
5495           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5496           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5497         }
5498         if(ifx)
5499           ifx->generated=1;
5500       }
5501       emit_skip++;
5502       offset++;
5503       if(res_offset < res_size-1)
5504         res_offset++;
5505     }
5506 /*       break; */
5507 /*     } */
5508   } else if(AOP_TYPE(right) == AOP_REG &&
5509             AOP_TYPE(left) != AOP_DIR){
5510
5511     while(size--) {
5512       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5513       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5514       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5515       if(rIfx.condition)
5516         emitSKPNZ;
5517       else
5518         emitSKPZ;
5519       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5520       offset++;
5521       if(res_offset < res_size-1)
5522         res_offset++;
5523     }
5524       
5525   }else{
5526     /* right is a pointer reg need both a & b */
5527     while(size--) {
5528       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5529       if(strcmp(l,"b"))
5530         pic16_emitcode("mov","b,%s",l);
5531       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5532       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5533       offset++;
5534     }
5535   }
5536
5537   if(result && preserve_result)
5538     {
5539       int i;
5540       for(i = 0; i < AOP_SIZE(result); i++)
5541         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5542     }
5543
5544   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
5545
5546   if(result && preserve_result)
5547     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
5548
5549   if(!rIfx.condition)
5550     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5551
5552   pic16_emitpLabel(lbl->key);
5553
5554   if(result && preserve_result)
5555     {
5556       int i;
5557       for(i = 0; i < AOP_SIZE(result); i++)
5558         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5559
5560       pic16_emitpLabel(lbl_done->key);
5561    }
5562
5563   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5564
5565   if(ifx)
5566     ifx->generated = 1;
5567 }
5568 #endif
5569
5570 #if 0
5571 /*-----------------------------------------------------------------*/
5572 /* gencjne - compare and jump if not equal                         */
5573 /*-----------------------------------------------------------------*/
5574 static void gencjne(operand *left, operand *right, iCode *ifx)
5575 {
5576     symbol *tlbl  = newiTempLabel(NULL);
5577
5578     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5579     gencjneshort(left, right, lbl);
5580
5581     pic16_emitcode("mov","a,%s",one);
5582     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5583     pic16_emitcode("","%05d_DS_:",lbl->key+100);
5584     pic16_emitcode("clr","a");
5585     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5586
5587     pic16_emitpLabel(lbl->key);
5588     pic16_emitpLabel(tlbl->key);
5589
5590 }
5591 #endif
5592
5593
5594 /*-----------------------------------------------------------------*/
5595 /* is_LitOp - check if operand has to be treated as literal        */
5596 /*-----------------------------------------------------------------*/
5597 static bool is_LitOp(operand *op)
5598 {
5599   return (AOP_TYPE(op) == AOP_LIT)
5600       || ( (AOP_TYPE(op) == AOP_PCODE)
5601           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
5602               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ));  
5603 }
5604
5605 /*-----------------------------------------------------------------*/
5606 /* is_LitAOp - check if operand has to be treated as literal        */
5607 /*-----------------------------------------------------------------*/
5608 static bool is_LitAOp(asmop *aop)
5609 {
5610   return (aop->type == AOP_LIT)
5611       || ( (aop->type == AOP_PCODE)
5612           && ( (aop->aopu.pcop->type == PO_LITERAL)
5613               || (aop->aopu.pcop->type == PO_IMMEDIATE) ));  
5614 }
5615
5616
5617
5618 /*-----------------------------------------------------------------*/
5619 /* genCmpEq - generates code for equal to                          */
5620 /*-----------------------------------------------------------------*/
5621 static void genCmpEq (iCode *ic, iCode *ifx)
5622 {
5623   operand *left, *right, *result;
5624   symbol *falselbl = newiTempLabel(NULL);
5625   symbol *donelbl = newiTempLabel(NULL);
5626
5627   int preserve_result = 0;
5628   int generate_result = 0;
5629   int i=0;
5630
5631   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5632   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5633   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5634  
5635   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5636   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5637
5638   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
5639     {
5640       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5641       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
5642       goto release;
5643     }
5644
5645   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
5646     {
5647       operand *tmp = right ;
5648       right = left;
5649       left = tmp;
5650     }
5651
5652   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5653     preserve_result = 1;
5654
5655   if(result && AOP_SIZE(result))
5656     generate_result = 1;
5657
5658   if(generate_result && !preserve_result)
5659     {
5660       for(i = 0; i < AOP_SIZE(result); i++)
5661         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5662     }
5663
5664   for(i=0; i < AOP_SIZE(left); i++)
5665     {
5666       if(AOP_TYPE(left) != AOP_ACC)
5667         {
5668           if(is_LitOp(left))
5669             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
5670           else
5671             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
5672         }
5673       if(is_LitOp(right))
5674         pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
5675       else
5676         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
5677
5678       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
5679     }
5680
5681   // result == true
5682
5683   if(generate_result && preserve_result)
5684     {
5685       for(i = 0; i < AOP_SIZE(result); i++)
5686         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5687     }
5688
5689   if(generate_result)
5690     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
5691
5692   if(generate_result && preserve_result)
5693     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5694
5695   if(ifx && IC_TRUE(ifx))
5696     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5697
5698   if(ifx && IC_FALSE(ifx))
5699     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5700
5701   pic16_emitpLabel(falselbl->key);
5702
5703   // result == false
5704
5705   if(ifx && IC_FALSE(ifx))
5706     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5707
5708   if(generate_result && preserve_result)
5709     {
5710       for(i = 0; i < AOP_SIZE(result); i++)
5711         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5712     }
5713
5714   pic16_emitpLabel(donelbl->key);
5715
5716   if(ifx)
5717     ifx->generated = 1;
5718
5719 release:
5720   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5721   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5722   pic16_freeAsmop(result,NULL,ic,TRUE);
5723
5724 }
5725
5726
5727 #if 0
5728 // old version kept for reference
5729
5730 /*-----------------------------------------------------------------*/
5731 /* genCmpEq - generates code for equal to                          */
5732 /*-----------------------------------------------------------------*/
5733 static void genCmpEq (iCode *ic, iCode *ifx)
5734 {
5735     operand *left, *right, *result;
5736     unsigned long lit = 0L;
5737     int size,offset=0;
5738     symbol *falselbl  = newiTempLabel(NULL);
5739
5740
5741     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5742
5743     if(ifx)
5744       DEBUGpic16_emitcode ("; ifx is non-null","");
5745     else
5746       DEBUGpic16_emitcode ("; ifx is null","");
5747
5748     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5749     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5750     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5751
5752     size = max(AOP_SIZE(left),AOP_SIZE(right));
5753
5754     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5755
5756     /* if literal, literal on the right or 
5757     if the right is in a pointer register and left 
5758     is not */
5759     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
5760         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5761       operand *tmp = right ;
5762       right = left;
5763       left = tmp;
5764     }
5765
5766
5767     if(ifx && !AOP_SIZE(result)){
5768         symbol *tlbl;
5769         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
5770         /* if they are both bit variables */
5771         if (AOP_TYPE(left) == AOP_CRY &&
5772             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5773                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
5774             if(AOP_TYPE(right) == AOP_LIT){
5775                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5776                 if(lit == 0L){
5777                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5778                     pic16_emitcode("cpl","c");
5779                 } else if(lit == 1L) {
5780                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5781                 } else {
5782                     pic16_emitcode("clr","c");
5783                 }
5784                 /* AOP_TYPE(right) == AOP_CRY */
5785             } else {
5786                 symbol *lbl = newiTempLabel(NULL);
5787                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5788                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5789                 pic16_emitcode("cpl","c");
5790                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5791             }
5792             /* if true label then we jump if condition
5793             supplied is true */
5794             tlbl = newiTempLabel(NULL);
5795             if ( IC_TRUE(ifx) ) {
5796                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5797                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5798             } else {
5799                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5800                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5801             }
5802             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5803
5804                 {
5805                 /* left and right are both bit variables, result is carry */
5806                         resolvedIfx rIfx;
5807               
5808                         resolveIfx(&rIfx,ifx);
5809
5810                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5811                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5812                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5813                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5814                         genSkipz2(&rIfx,0);
5815                 }
5816         } else {
5817
5818                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
5819
5820                         /* They're not both bit variables. Is the right a literal? */
5821                         if(AOP_TYPE(right) == AOP_LIT) {
5822                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5823             
5824                         switch(size) {
5825
5826                                 case 1:
5827                                         switch(lit & 0xff) {
5828                                                 case 1:
5829                                                                 if ( IC_TRUE(ifx) ) {
5830                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
5831                                                                         emitSKPNZ;
5832                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5833                                                                 } else {
5834                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5835                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5836                                                                 }
5837                                                                 break;
5838                                                 case 0xff:
5839                                                                 if ( IC_TRUE(ifx) ) {
5840                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
5841                                                                         emitSKPNZ;
5842                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5843                                                                 } else {
5844                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5845                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5846                                                                 }
5847                                                                 break;
5848                                                 default:
5849                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5850                                                                 if(lit)
5851                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5852                                                                 genSkip(ifx,'z');
5853                                         } // switch lit
5854
5855
5856                                         /* end of size == 1 */
5857                                         break;
5858               
5859                                 case 2:
5860                                         genc16bit2lit(left,lit,offset);
5861                                         genSkip(ifx,'z');
5862                                         break;
5863                                         /* end of size == 2 */
5864
5865                                 default:
5866                                         /* size is 4 */
5867                                         if(lit==0) {
5868                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5869                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
5870                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5871                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5872                                                 genSkip(ifx,'z');
5873                                         } else {
5874                                                 /* search for patterns that can be optimized */
5875
5876                                                 genc16bit2lit(left,lit,0);
5877                                                 lit >>= 16;
5878                                                 if(lit) {
5879                                                                 if(IC_TRUE(ifx))
5880                                                                 emitSKPZ; // if hi word unequal
5881                                                                 else
5882                                                                 emitSKPNZ; // if hi word equal
5883                                                                 // fail early
5884                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
5885                                                         genc16bit2lit(left,lit,2);
5886                                                         genSkip(ifx,'z');
5887                                                 } else {
5888                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5889                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5890                                                         genSkip(ifx,'z');
5891                                                 }
5892                                         }
5893                                                 pic16_emitpLabel(falselbl->key);
5894                                                 break;
5895
5896                         } // switch size
5897           
5898                         ifx->generated = 1;
5899                         goto release ;
5900             
5901
5902           } else if(AOP_TYPE(right) == AOP_CRY ) {
5903             /* we know the left is not a bit, but that the right is */
5904             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5905             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5906                       pic16_popGet(AOP(right),offset));
5907             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
5908
5909             /* if the two are equal, then W will be 0 and the Z bit is set
5910              * we could test Z now, or go ahead and check the high order bytes if
5911              * the variable we're comparing is larger than a byte. */
5912
5913             while(--size)
5914               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
5915
5916             if ( IC_TRUE(ifx) ) {
5917               emitSKPNZ;
5918               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5919               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5920             } else {
5921               emitSKPZ;
5922               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5923               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5924             }
5925
5926           } else {
5927             /* They're both variables that are larger than bits */
5928             int s = size;
5929
5930             tlbl = newiTempLabel(NULL);
5931
5932             while(size--) {
5933               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5934               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5935
5936               if ( IC_TRUE(ifx) ) {
5937                 if(size) {
5938                   emitSKPZ;
5939                 
5940                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5941
5942                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5943                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
5944                 } else {
5945                   emitSKPNZ;
5946
5947                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5948
5949
5950                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5951                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5952                 }
5953               } else {
5954                 emitSKPZ;
5955
5956                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5957
5958                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5959                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5960               }
5961               offset++;
5962             }
5963             if(s>1 && IC_TRUE(ifx)) {
5964               pic16_emitpLabel(tlbl->key);
5965               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
5966             }
5967           }
5968         }
5969         /* mark the icode as generated */
5970         ifx->generated = 1;
5971         goto release ;
5972     }
5973
5974     /* if they are both bit variables */
5975     if (AOP_TYPE(left) == AOP_CRY &&
5976         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5977         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
5978         if(AOP_TYPE(right) == AOP_LIT){
5979             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5980             if(lit == 0L){
5981                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5982                 pic16_emitcode("cpl","c");
5983             } else if(lit == 1L) {
5984                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5985             } else {
5986                 pic16_emitcode("clr","c");
5987             }
5988             /* AOP_TYPE(right) == AOP_CRY */
5989         } else {
5990             symbol *lbl = newiTempLabel(NULL);
5991             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5992             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5993             pic16_emitcode("cpl","c");
5994             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5995         }
5996         /* c = 1 if egal */
5997         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5998             pic16_outBitC(result);
5999             goto release ;
6000         }
6001         if (ifx) {
6002             genIfxJump (ifx,"c");
6003             goto release ;
6004         }
6005         /* if the result is used in an arithmetic operation
6006         then put the result in place */
6007         pic16_outBitC(result);
6008     } else {
6009       
6010       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
6011       gencjne(left,right,result,ifx);
6012 /*
6013       if(ifx) 
6014         gencjne(left,right,newiTempLabel(NULL));
6015       else {
6016         if(IC_TRUE(ifx)->key)
6017           gencjne(left,right,IC_TRUE(ifx)->key);
6018         else
6019           gencjne(left,right,IC_FALSE(ifx)->key);
6020         ifx->generated = 1;
6021         goto release ;
6022       }
6023       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
6024         pic16_aopPut(AOP(result),"a",0);
6025         goto release ;
6026       }
6027
6028       if (ifx) {
6029         genIfxJump (ifx,"a");
6030         goto release ;
6031       }
6032 */
6033       /* if the result is used in an arithmetic operation
6034          then put the result in place */
6035 /*
6036       if (AOP_TYPE(result) != AOP_CRY) 
6037         pic16_outAcc(result);
6038 */
6039       /* leave the result in acc */
6040     }
6041
6042 release:
6043     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6044     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6045     pic16_freeAsmop(result,NULL,ic,TRUE);
6046 }
6047 #endif
6048
6049 /*-----------------------------------------------------------------*/
6050 /* ifxForOp - returns the icode containing the ifx for operand     */
6051 /*-----------------------------------------------------------------*/
6052 static iCode *ifxForOp ( operand *op, iCode *ic )
6053 {
6054     /* if true symbol then needs to be assigned */
6055     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6056     if (IS_TRUE_SYMOP(op))
6057         return NULL ;
6058
6059     /* if this has register type condition and
6060     the next instruction is ifx with the same operand
6061     and live to of the operand is upto the ifx only then */
6062     if (ic->next
6063         && ic->next->op == IFX
6064         && IC_COND(ic->next)->key == op->key
6065         && OP_SYMBOL(op)->liveTo <= ic->next->seq
6066         ) {
6067                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
6068           return ic->next;
6069     }
6070
6071     if (ic->next &&
6072         ic->next->op == IFX &&
6073         IC_COND(ic->next)->key == op->key) {
6074       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6075       return ic->next;
6076     }
6077
6078     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
6079     if (ic->next &&
6080         ic->next->op == IFX)
6081       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
6082
6083     if (ic->next &&
6084         ic->next->op == IFX &&
6085         IC_COND(ic->next)->key == op->key) {
6086       DEBUGpic16_emitcode ("; "," key is okay");
6087       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
6088                            OP_SYMBOL(op)->liveTo,
6089                            ic->next->seq);
6090     }
6091
6092 #if 0
6093     /* the code below is completely untested
6094      * it just allows ulong2fs.c compile -- VR */
6095          
6096     ic = ic->next;
6097     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
6098                                         __FILE__, __FUNCTION__, __LINE__);
6099         
6100     /* if this has register type condition and
6101     the next instruction is ifx with the same operand
6102     and live to of the operand is upto the ifx only then */
6103     if (ic->next &&
6104         ic->next->op == IFX &&
6105         IC_COND(ic->next)->key == op->key &&
6106         OP_SYMBOL(op)->liveTo <= ic->next->seq )
6107         return ic->next;
6108
6109     if (ic->next &&
6110         ic->next->op == IFX &&
6111         IC_COND(ic->next)->key == op->key) {
6112       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6113       return ic->next;
6114     }
6115
6116     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
6117                                         __FILE__, __FUNCTION__, __LINE__);
6118
6119 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
6120 #endif
6121
6122     return NULL;
6123 }
6124 /*-----------------------------------------------------------------*/
6125 /* genAndOp - for && operation                                     */
6126 /*-----------------------------------------------------------------*/
6127 static void genAndOp (iCode *ic)
6128 {
6129     operand *left,*right, *result;
6130 /*     symbol *tlbl; */
6131
6132     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6133     /* note here that && operations that are in an
6134     if statement are taken away by backPatchLabels
6135     only those used in arthmetic operations remain */
6136     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6137     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6138     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6139
6140     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6141
6142     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6143     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
6144     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
6145
6146     /* if both are bit variables */
6147 /*     if (AOP_TYPE(left) == AOP_CRY && */
6148 /*         AOP_TYPE(right) == AOP_CRY ) { */
6149 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
6150 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
6151 /*         pic16_outBitC(result); */
6152 /*     } else { */
6153 /*         tlbl = newiTempLabel(NULL); */
6154 /*         pic16_toBoolean(left);     */
6155 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
6156 /*         pic16_toBoolean(right); */
6157 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
6158 /*         pic16_outBitAcc(result); */
6159 /*     } */
6160
6161     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6162     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6163     pic16_freeAsmop(result,NULL,ic,TRUE);
6164 }
6165
6166
6167 /*-----------------------------------------------------------------*/
6168 /* genOrOp - for || operation                                      */
6169 /*-----------------------------------------------------------------*/
6170 /*
6171   tsd pic port -
6172   modified this code, but it doesn't appear to ever get called
6173 */
6174
6175 static void genOrOp (iCode *ic)
6176 {
6177     operand *left,*right, *result;
6178     symbol *tlbl;
6179
6180     /* note here that || operations that are in an
6181     if statement are taken away by backPatchLabels
6182     only those used in arthmetic operations remain */
6183     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6184     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6185     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6186     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6187
6188     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6189
6190     /* if both are bit variables */
6191     if (AOP_TYPE(left) == AOP_CRY &&
6192         AOP_TYPE(right) == AOP_CRY ) {
6193       pic16_emitcode("clrc","");
6194       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6195                AOP(left)->aopu.aop_dir,
6196                AOP(left)->aopu.aop_dir);
6197       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6198                AOP(right)->aopu.aop_dir,
6199                AOP(right)->aopu.aop_dir);
6200       pic16_emitcode("setc","");
6201
6202     } else {
6203         tlbl = newiTempLabel(NULL);
6204         pic16_toBoolean(left);
6205         emitSKPZ;
6206         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
6207         pic16_toBoolean(right);
6208         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6209
6210         pic16_outBitAcc(result);
6211     }
6212
6213     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6214     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6215     pic16_freeAsmop(result,NULL,ic,TRUE);            
6216 }
6217
6218 /*-----------------------------------------------------------------*/
6219 /* isLiteralBit - test if lit == 2^n                               */
6220 /*-----------------------------------------------------------------*/
6221 static int isLiteralBit(unsigned long lit)
6222 {
6223     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
6224     0x100L,0x200L,0x400L,0x800L,
6225     0x1000L,0x2000L,0x4000L,0x8000L,
6226     0x10000L,0x20000L,0x40000L,0x80000L,
6227     0x100000L,0x200000L,0x400000L,0x800000L,
6228     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
6229     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
6230     int idx;
6231     
6232     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6233     for(idx = 0; idx < 32; idx++)
6234         if(lit == pw[idx])
6235             return idx+1;
6236     return 0;
6237 }
6238
6239 /*-----------------------------------------------------------------*/
6240 /* continueIfTrue -                                                */
6241 /*-----------------------------------------------------------------*/
6242 static void continueIfTrue (iCode *ic)
6243 {
6244     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6245     if(IC_TRUE(ic))
6246         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6247     ic->generated = 1;
6248 }
6249
6250 /*-----------------------------------------------------------------*/
6251 /* jmpIfTrue -                                                     */
6252 /*-----------------------------------------------------------------*/
6253 static void jumpIfTrue (iCode *ic)
6254 {
6255     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6256     if(!IC_TRUE(ic))
6257         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6258     ic->generated = 1;
6259 }
6260
6261 /*-----------------------------------------------------------------*/
6262 /* jmpTrueOrFalse -                                                */
6263 /*-----------------------------------------------------------------*/
6264 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
6265 {
6266     // ugly but optimized by peephole
6267     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6268     if(IC_TRUE(ic)){
6269         symbol *nlbl = newiTempLabel(NULL);
6270         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
6271         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6272         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6273         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
6274     }
6275     else{
6276         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6277         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6278     }
6279     ic->generated = 1;
6280 }
6281
6282 /*-----------------------------------------------------------------*/
6283 /* genAnd  - code for and                                          */
6284 /*-----------------------------------------------------------------*/
6285 static void genAnd (iCode *ic, iCode *ifx)
6286 {
6287   operand *left, *right, *result;
6288   int size, offset=0;  
6289   unsigned long lit = 0L;
6290   int bytelit = 0;
6291   resolvedIfx rIfx;
6292
6293
6294   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6295   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6296   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6297   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6298
6299   resolveIfx(&rIfx,ifx);
6300
6301   /* if left is a literal & right is not then exchange them */
6302   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6303       AOP_NEEDSACC(left)) {
6304     operand *tmp = right ;
6305     right = left;
6306     left = tmp;
6307   }
6308
6309   /* if result = right then exchange them */
6310   if(pic16_sameRegs(AOP(result),AOP(right))){
6311     operand *tmp = right ;
6312     right = left;
6313     left = tmp;
6314   }
6315
6316   /* if right is bit then exchange them */
6317   if (AOP_TYPE(right) == AOP_CRY &&
6318       AOP_TYPE(left) != AOP_CRY){
6319     operand *tmp = right ;
6320     right = left;
6321     left = tmp;
6322   }
6323   if(AOP_TYPE(right) == AOP_LIT)
6324     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6325
6326   size = AOP_SIZE(result);
6327
6328   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6329
6330   // if(bit & yy)
6331   // result = bit & yy;
6332   if (AOP_TYPE(left) == AOP_CRY){
6333     // c = bit & literal;
6334     if(AOP_TYPE(right) == AOP_LIT){
6335       if(lit & 1) {
6336         if(size && pic16_sameRegs(AOP(result),AOP(left)))
6337           // no change
6338           goto release;
6339         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6340       } else {
6341         // bit(result) = 0;
6342         if(size && (AOP_TYPE(result) == AOP_CRY)){
6343           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
6344           goto release;
6345         }
6346         if((AOP_TYPE(result) == AOP_CRY) && ifx){
6347           jumpIfTrue(ifx);
6348           goto release;
6349         }
6350         pic16_emitcode("clr","c");
6351       }
6352     } else {
6353       if (AOP_TYPE(right) == AOP_CRY){
6354         // c = bit & bit;
6355         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6356         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6357       } else {
6358         // c = bit & val;
6359         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
6360         // c = lsb
6361         pic16_emitcode("rrc","a");
6362         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6363       }
6364     }
6365     // bit = c
6366     // val = c
6367     if(size)
6368       pic16_outBitC(result);
6369     // if(bit & ...)
6370     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6371       genIfxJump(ifx, "c");           
6372     goto release ;
6373   }
6374
6375   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6376   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6377   if((AOP_TYPE(right) == AOP_LIT) &&
6378      (AOP_TYPE(result) == AOP_CRY) &&
6379      (AOP_TYPE(left) != AOP_CRY)){
6380     int posbit = isLiteralBit(lit);
6381     /* left &  2^n */
6382     if(posbit){
6383       posbit--;
6384       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6385       // bit = left & 2^n
6386       if(size)
6387         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6388       // if(left &  2^n)
6389       else{
6390         if(ifx){
6391 /*
6392           if(IC_TRUE(ifx)) {
6393             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6394             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
6395           } else {
6396             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6397             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
6398           }
6399 */
6400         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
6401         size = AOP_SIZE(left);
6402
6403         {
6404           int bp = posbit, ofs=0;
6405           
6406             while(bp > 7) {
6407               bp -= 8;
6408               ofs++;
6409             }
6410         
6411           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6412                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
6413
6414         }
6415 /*
6416           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6417                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6418 */
6419           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6420           
6421           ifx->generated = 1;
6422         }
6423         goto release;
6424       }
6425     } else {
6426       symbol *tlbl = newiTempLabel(NULL);
6427       int sizel = AOP_SIZE(left);
6428       if(size)
6429         pic16_emitcode("setb","c");
6430       while(sizel--){
6431         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
6432           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6433           // byte ==  2^n ?
6434           if((posbit = isLiteralBit(bytelit)) != 0)
6435             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6436           else{
6437             if(bytelit != 0x0FFL)
6438               pic16_emitcode("anl","a,%s",
6439                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6440             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6441           }
6442         }
6443         offset++;
6444       }
6445       // bit = left & literal
6446       if(size){
6447         pic16_emitcode("clr","c");
6448         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6449       }
6450       // if(left & literal)
6451       else{
6452         if(ifx)
6453           jmpTrueOrFalse(ifx, tlbl);
6454         goto release ;
6455       }
6456     }
6457     pic16_outBitC(result);
6458     goto release ;
6459   }
6460
6461   /* if left is same as result */
6462   if(pic16_sameRegs(AOP(result),AOP(left))){
6463     int know_W = -1;
6464     for(;size--; offset++,lit>>=8) {
6465       if(AOP_TYPE(right) == AOP_LIT){
6466         switch(lit & 0xff) {
6467         case 0x00:
6468           /*  and'ing with 0 has clears the result */
6469 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6470           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6471           break;
6472         case 0xff:
6473           /* and'ing with 0xff is a nop when the result and left are the same */
6474           break;
6475
6476         default:
6477           {
6478             int p = my_powof2( (~lit) & 0xff );
6479             if(p>=0) {
6480               /* only one bit is set in the literal, so use a bcf instruction */
6481 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6482               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
6483
6484             } else {
6485               pic16_emitcode("movlw","0x%x", (lit & 0xff));
6486               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6487               if(know_W != (lit&0xff))
6488                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6489               know_W = lit &0xff;
6490               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6491             }
6492           }    
6493         }
6494       } else {
6495         if (AOP_TYPE(left) == AOP_ACC) {
6496           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6497         } else {                    
6498           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6499           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6500
6501         }
6502       }
6503     }
6504
6505   } else {
6506     // left & result in different registers
6507     if(AOP_TYPE(result) == AOP_CRY){
6508       // result = bit
6509       // if(size), result in bit
6510       // if(!size && ifx), conditional oper: if(left & right)
6511       symbol *tlbl = newiTempLabel(NULL);
6512       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6513       if(size)
6514         pic16_emitcode("setb","c");
6515       while(sizer--){
6516         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6517         pic16_emitcode("anl","a,%s",
6518                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6519         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6520         offset++;
6521       }
6522       if(size){
6523         CLRC;
6524         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6525         pic16_outBitC(result);
6526       } else if(ifx)
6527         jmpTrueOrFalse(ifx, tlbl);
6528     } else {
6529       for(;(size--);offset++) {
6530         // normal case
6531         // result = left & right
6532         if(AOP_TYPE(right) == AOP_LIT){
6533           int t = (lit >> (offset*8)) & 0x0FFL;
6534           switch(t) { 
6535           case 0x00:
6536             pic16_emitcode("clrf","%s",
6537                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6538             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6539             break;
6540           case 0xff:
6541             pic16_emitcode("movf","%s,w",
6542                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6543             pic16_emitcode("movwf","%s",
6544                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6545             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6546             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6547             break;
6548           default:
6549             pic16_emitcode("movlw","0x%x",t);
6550             pic16_emitcode("andwf","%s,w",
6551                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6552             pic16_emitcode("movwf","%s",
6553                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6554               
6555             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6556             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6557             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6558           }
6559           continue;
6560         }
6561
6562         if (AOP_TYPE(left) == AOP_ACC) {
6563           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6564           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6565         } else {
6566           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6567           pic16_emitcode("andwf","%s,w",
6568                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6569           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6570           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6571         }
6572         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6573         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6574       }
6575     }
6576   }
6577
6578   release :
6579     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6580   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6581   pic16_freeAsmop(result,NULL,ic,TRUE);     
6582 }
6583
6584 /*-----------------------------------------------------------------*/
6585 /* genOr  - code for or                                            */
6586 /*-----------------------------------------------------------------*/
6587 static void genOr (iCode *ic, iCode *ifx)
6588 {
6589     operand *left, *right, *result;
6590     int size, offset=0;
6591     unsigned long lit = 0L;
6592
6593     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6594
6595     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6596     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6597     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6598
6599     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6600
6601     /* if left is a literal & right is not then exchange them */
6602     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6603         AOP_NEEDSACC(left)) {
6604         operand *tmp = right ;
6605         right = left;
6606         left = tmp;
6607     }
6608
6609     /* if result = right then exchange them */
6610     if(pic16_sameRegs(AOP(result),AOP(right))){
6611         operand *tmp = right ;
6612         right = left;
6613         left = tmp;
6614     }
6615
6616     /* if right is bit then exchange them */
6617     if (AOP_TYPE(right) == AOP_CRY &&
6618         AOP_TYPE(left) != AOP_CRY){
6619         operand *tmp = right ;
6620         right = left;
6621         left = tmp;
6622     }
6623
6624     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6625
6626     if(AOP_TYPE(right) == AOP_LIT)
6627         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6628
6629     size = AOP_SIZE(result);
6630
6631     // if(bit | yy)
6632     // xx = bit | yy;
6633     if (AOP_TYPE(left) == AOP_CRY){
6634         if(AOP_TYPE(right) == AOP_LIT){
6635             // c = bit & literal;
6636             if(lit){
6637                 // lit != 0 => result = 1
6638                 if(AOP_TYPE(result) == AOP_CRY){
6639                   if(size)
6640                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6641                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6642                   //     AOP(result)->aopu.aop_dir,
6643                   //     AOP(result)->aopu.aop_dir);
6644                     else if(ifx)
6645                         continueIfTrue(ifx);
6646                     goto release;
6647                 }
6648             } else {
6649                 // lit == 0 => result = left
6650                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6651                     goto release;
6652                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6653             }
6654         } else {
6655             if (AOP_TYPE(right) == AOP_CRY){
6656               if(pic16_sameRegs(AOP(result),AOP(left))){
6657                 // c = bit | bit;
6658                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6659                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6660                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6661
6662                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6663                          AOP(result)->aopu.aop_dir,
6664                          AOP(result)->aopu.aop_dir);
6665                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6666                          AOP(right)->aopu.aop_dir,
6667                          AOP(right)->aopu.aop_dir);
6668                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6669                          AOP(result)->aopu.aop_dir,
6670                          AOP(result)->aopu.aop_dir);
6671               } else {
6672                 if( AOP_TYPE(result) == AOP_ACC) {
6673                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6674                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6675                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6676                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6677
6678                 } else {
6679
6680                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6681                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6682                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6683                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6684
6685                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6686                                  AOP(result)->aopu.aop_dir,
6687                                  AOP(result)->aopu.aop_dir);
6688                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6689                                  AOP(right)->aopu.aop_dir,
6690                                  AOP(right)->aopu.aop_dir);
6691                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6692                                  AOP(left)->aopu.aop_dir,
6693                                  AOP(left)->aopu.aop_dir);
6694                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6695                                  AOP(result)->aopu.aop_dir,
6696                                  AOP(result)->aopu.aop_dir);
6697                 }
6698               }
6699             } else {
6700                 // c = bit | val;
6701                 symbol *tlbl = newiTempLabel(NULL);
6702                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6703
6704
6705                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6706                 if( AOP_TYPE(right) == AOP_ACC) {
6707                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6708                   emitSKPNZ;
6709                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6710                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6711                 }
6712
6713
6714
6715                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6716                     pic16_emitcode(";XXX setb","c");
6717                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6718                          AOP(left)->aopu.aop_dir,tlbl->key+100);
6719                 pic16_toBoolean(right);
6720                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6721                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6722                     jmpTrueOrFalse(ifx, tlbl);
6723                     goto release;
6724                 } else {
6725                     CLRC;
6726                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6727                 }
6728             }
6729         }
6730         // bit = c
6731         // val = c
6732         if(size)
6733             pic16_outBitC(result);
6734         // if(bit | ...)
6735         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6736             genIfxJump(ifx, "c");           
6737         goto release ;
6738     }
6739
6740     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6741     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6742     if((AOP_TYPE(right) == AOP_LIT) &&
6743        (AOP_TYPE(result) == AOP_CRY) &&
6744        (AOP_TYPE(left) != AOP_CRY)){
6745         if(lit){
6746           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6747             // result = 1
6748             if(size)
6749                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6750             else 
6751                 continueIfTrue(ifx);
6752             goto release;
6753         } else {
6754           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6755             // lit = 0, result = boolean(left)
6756             if(size)
6757                 pic16_emitcode(";XXX setb","c");
6758             pic16_toBoolean(right);
6759             if(size){
6760                 symbol *tlbl = newiTempLabel(NULL);
6761                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6762                 CLRC;
6763                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6764             } else {
6765                 genIfxJump (ifx,"a");
6766                 goto release;
6767             }
6768         }
6769         pic16_outBitC(result);
6770         goto release ;
6771     }
6772
6773     /* if left is same as result */
6774     if(pic16_sameRegs(AOP(result),AOP(left))){
6775       int know_W = -1;
6776       for(;size--; offset++,lit>>=8) {
6777         if(AOP_TYPE(right) == AOP_LIT){
6778           if((lit & 0xff) == 0)
6779             /*  or'ing with 0 has no effect */
6780             continue;
6781           else {
6782             int p = my_powof2(lit & 0xff);
6783             if(p>=0) {
6784               /* only one bit is set in the literal, so use a bsf instruction */
6785               pic16_emitpcode(POC_BSF,
6786                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
6787             } else {
6788               if(know_W != (lit & 0xff))
6789                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6790               know_W = lit & 0xff;
6791               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6792             }
6793                     
6794           }
6795         } else {
6796           if (AOP_TYPE(left) == AOP_ACC) {
6797             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
6798             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6799           } else {                  
6800             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6801             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
6802
6803             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6804             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6805
6806           }
6807         }
6808       }
6809     } else {
6810         // left & result in different registers
6811         if(AOP_TYPE(result) == AOP_CRY){
6812             // result = bit
6813             // if(size), result in bit
6814             // if(!size && ifx), conditional oper: if(left | right)
6815             symbol *tlbl = newiTempLabel(NULL);
6816             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6817             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6818
6819
6820             if(size)
6821                 pic16_emitcode(";XXX setb","c");
6822             while(sizer--){
6823                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6824                 pic16_emitcode(";XXX orl","a,%s",
6825                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6826                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6827                 offset++;
6828             }
6829             if(size){
6830                 CLRC;
6831                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6832                 pic16_outBitC(result);
6833             } else if(ifx)
6834                 jmpTrueOrFalse(ifx, tlbl);
6835         } else for(;(size--);offset++){
6836           // normal case
6837           // result = left & right
6838           if(AOP_TYPE(right) == AOP_LIT){
6839             int t = (lit >> (offset*8)) & 0x0FFL;
6840             switch(t) { 
6841             case 0x00:
6842               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
6843               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6844
6845               pic16_emitcode("movf","%s,w",
6846                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6847               pic16_emitcode("movwf","%s",
6848                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6849               break;
6850             default:
6851               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
6852               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6853               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6854
6855               pic16_emitcode("movlw","0x%x",t);
6856               pic16_emitcode("iorwf","%s,w",
6857                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6858               pic16_emitcode("movwf","%s",
6859                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6860               
6861             }
6862             continue;
6863           }
6864
6865           // faster than result <- left, anl result,right
6866           // and better if result is SFR
6867           if (AOP_TYPE(left) == AOP_ACC) {
6868             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
6869             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6870           } else {
6871             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6872             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6873
6874             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6875             pic16_emitcode("iorwf","%s,w",
6876                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6877           }
6878           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6879           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6880         }
6881     }
6882
6883 release :
6884     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6885     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6886     pic16_freeAsmop(result,NULL,ic,TRUE);     
6887 }
6888
6889 /*-----------------------------------------------------------------*/
6890 /* genXor - code for xclusive or                                   */
6891 /*-----------------------------------------------------------------*/
6892 static void genXor (iCode *ic, iCode *ifx)
6893 {
6894   operand *left, *right, *result;
6895   int size, offset=0;
6896   unsigned long lit = 0L;
6897
6898   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6899
6900   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6901   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6902   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6903
6904   /* if left is a literal & right is not ||
6905      if left needs acc & right does not */
6906   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6907       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6908     operand *tmp = right ;
6909     right = left;
6910     left = tmp;
6911   }
6912
6913   /* if result = right then exchange them */
6914   if(pic16_sameRegs(AOP(result),AOP(right))){
6915     operand *tmp = right ;
6916     right = left;
6917     left = tmp;
6918   }
6919
6920   /* if right is bit then exchange them */
6921   if (AOP_TYPE(right) == AOP_CRY &&
6922       AOP_TYPE(left) != AOP_CRY){
6923     operand *tmp = right ;
6924     right = left;
6925     left = tmp;
6926   }
6927   if(AOP_TYPE(right) == AOP_LIT)
6928     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6929
6930   size = AOP_SIZE(result);
6931
6932   // if(bit ^ yy)
6933   // xx = bit ^ yy;
6934   if (AOP_TYPE(left) == AOP_CRY){
6935     if(AOP_TYPE(right) == AOP_LIT){
6936       // c = bit & literal;
6937       if(lit>>1){
6938         // lit>>1  != 0 => result = 1
6939         if(AOP_TYPE(result) == AOP_CRY){
6940           if(size)
6941             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
6942             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6943           else if(ifx)
6944             continueIfTrue(ifx);
6945           goto release;
6946         }
6947         pic16_emitcode("setb","c");
6948       } else{
6949         // lit == (0 or 1)
6950         if(lit == 0){
6951           // lit == 0, result = left
6952           if(size && pic16_sameRegs(AOP(result),AOP(left)))
6953             goto release;
6954           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6955         } else{
6956           // lit == 1, result = not(left)
6957           if(size && pic16_sameRegs(AOP(result),AOP(left))){
6958             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
6959             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
6960             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6961             goto release;
6962           } else {
6963             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6964             pic16_emitcode("cpl","c");
6965           }
6966         }
6967       }
6968
6969     } else {
6970       // right != literal
6971       symbol *tlbl = newiTempLabel(NULL);
6972       if (AOP_TYPE(right) == AOP_CRY){
6973         // c = bit ^ bit;
6974         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6975       }
6976       else{
6977         int sizer = AOP_SIZE(right);
6978         // c = bit ^ val
6979         // if val>>1 != 0, result = 1
6980         pic16_emitcode("setb","c");
6981         while(sizer){
6982           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
6983           if(sizer == 1)
6984             // test the msb of the lsb
6985             pic16_emitcode("anl","a,#0xfe");
6986           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6987           sizer--;
6988         }
6989         // val = (0,1)
6990         pic16_emitcode("rrc","a");
6991       }
6992       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6993       pic16_emitcode("cpl","c");
6994       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
6995     }
6996     // bit = c
6997     // val = c
6998     if(size)
6999       pic16_outBitC(result);
7000     // if(bit | ...)
7001     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7002       genIfxJump(ifx, "c");           
7003     goto release ;
7004   }
7005
7006   if(pic16_sameRegs(AOP(result),AOP(left))){
7007     /* if left is same as result */
7008     for(;size--; offset++) {
7009       if(AOP_TYPE(right) == AOP_LIT){
7010         int t  = (lit >> (offset*8)) & 0x0FFL;
7011         if(t == 0x00L)
7012           continue;
7013         else
7014           if (IS_AOP_PREG(left)) {
7015             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7016             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7017             pic16_aopPut(AOP(result),"a",offset);
7018           } else {
7019             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7020             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7021             pic16_emitcode("xrl","%s,%s",
7022                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
7023                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7024           }
7025       } else {
7026         if (AOP_TYPE(left) == AOP_ACC)
7027           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7028         else {
7029           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7030           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7031 /*
7032           if (IS_AOP_PREG(left)) {
7033             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7034             pic16_aopPut(AOP(result),"a",offset);
7035           } else
7036             pic16_emitcode("xrl","%s,a",
7037                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7038 */
7039         }
7040       }
7041     }
7042   } else {
7043     // left & result in different registers
7044     if(AOP_TYPE(result) == AOP_CRY){
7045       // result = bit
7046       // if(size), result in bit
7047       // if(!size && ifx), conditional oper: if(left ^ right)
7048       symbol *tlbl = newiTempLabel(NULL);
7049       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7050       if(size)
7051         pic16_emitcode("setb","c");
7052       while(sizer--){
7053         if((AOP_TYPE(right) == AOP_LIT) &&
7054            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
7055           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7056         } else {
7057           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7058           pic16_emitcode("xrl","a,%s",
7059                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7060         }
7061         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7062         offset++;
7063       }
7064       if(size){
7065         CLRC;
7066         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7067         pic16_outBitC(result);
7068       } else if(ifx)
7069         jmpTrueOrFalse(ifx, tlbl);
7070     } else for(;(size--);offset++){
7071       // normal case
7072       // result = left & right
7073       if(AOP_TYPE(right) == AOP_LIT){
7074         int t = (lit >> (offset*8)) & 0x0FFL;
7075         switch(t) { 
7076         case 0x00:
7077           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7078           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7079           pic16_emitcode("movf","%s,w",
7080                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7081           pic16_emitcode("movwf","%s",
7082                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7083           break;
7084         case 0xff:
7085           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
7086           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7087           pic16_emitcode("comf","%s,w",
7088                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7089           pic16_emitcode("movwf","%s",
7090                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7091           break;
7092         default:
7093           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7094           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7095           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7096           pic16_emitcode("movlw","0x%x",t);
7097           pic16_emitcode("xorwf","%s,w",
7098                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7099           pic16_emitcode("movwf","%s",
7100                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7101
7102         }
7103         continue;
7104       }
7105
7106       // faster than result <- left, anl result,right
7107       // and better if result is SFR
7108       if (AOP_TYPE(left) == AOP_ACC) {
7109         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7110         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7111       } else {
7112         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7113         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7114         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7115         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7116       }
7117       if ( AOP_TYPE(result) != AOP_ACC){
7118         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7119         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7120       }
7121     }
7122   }
7123
7124   release :
7125     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7126   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7127   pic16_freeAsmop(result,NULL,ic,TRUE);     
7128 }
7129
7130 /*-----------------------------------------------------------------*/
7131 /* genInline - write the inline code out                           */
7132 /*-----------------------------------------------------------------*/
7133 static void genInline (iCode *ic)
7134 {
7135   char *buffer, *bp, *bp1;
7136     
7137         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7138
7139         _G.inLine += (!options.asmpeep);
7140
7141         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7142         strcpy(buffer,IC_INLINE(ic));
7143
7144 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
7145
7146         /* emit each line as a code */
7147         while (*bp) {
7148                 if (*bp == '\n') {
7149                         *bp++ = '\0';
7150
7151                         if(*bp1)
7152                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7153                         bp1 = bp;
7154                 } else {
7155                         if (*bp == ':') {
7156                                 bp++;
7157                                 *bp = '\0';
7158                                 bp++;
7159
7160                                 /* print label, use this special format with NULL directive
7161                                  * to denote that the argument should not be indented with tab */
7162                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
7163                                 bp1 = bp;
7164                         } else
7165                                 bp++;
7166                 }
7167         }
7168
7169         if ((bp1 != bp) && *bp1)
7170                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7171
7172
7173     Safe_free(buffer);
7174
7175     _G.inLine -= (!options.asmpeep);
7176 }
7177
7178 /*-----------------------------------------------------------------*/
7179 /* genRRC - rotate right with carry                                */
7180 /*-----------------------------------------------------------------*/
7181 static void genRRC (iCode *ic)
7182 {
7183   operand *left , *result ;
7184   int size, offset = 0, same;
7185
7186   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7187
7188   /* rotate right with carry */
7189   left = IC_LEFT(ic);
7190   result=IC_RESULT(ic);
7191   pic16_aopOp (left,ic,FALSE);
7192   pic16_aopOp (result,ic,FALSE);
7193
7194   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7195
7196   same = pic16_sameRegs(AOP(result),AOP(left));
7197
7198   size = AOP_SIZE(result);    
7199
7200   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
7201
7202   /* get the lsb and put it into the carry */
7203   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
7204
7205   offset = 0 ;
7206
7207   while(size--) {
7208
7209     if(same) {
7210       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
7211     } else {
7212       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
7213       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7214     }
7215
7216     offset++;
7217   }
7218
7219   pic16_freeAsmop(left,NULL,ic,TRUE);
7220   pic16_freeAsmop(result,NULL,ic,TRUE);
7221 }
7222
7223 /*-----------------------------------------------------------------*/
7224 /* genRLC - generate code for rotate left with carry               */
7225 /*-----------------------------------------------------------------*/
7226 static void genRLC (iCode *ic)
7227 {    
7228   operand *left , *result ;
7229   int size, offset = 0;
7230   int same;
7231
7232   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7233   /* rotate right with carry */
7234   left = IC_LEFT(ic);
7235   result=IC_RESULT(ic);
7236   pic16_aopOp (left,ic,FALSE);
7237   pic16_aopOp (result,ic,FALSE);
7238
7239   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7240
7241   same = pic16_sameRegs(AOP(result),AOP(left));
7242
7243   /* move it to the result */
7244   size = AOP_SIZE(result);    
7245
7246   /* get the msb and put it into the carry */
7247   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7248
7249   offset = 0 ;
7250
7251   while(size--) {
7252
7253     if(same) {
7254       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7255     } else {
7256       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7257       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7258     }
7259
7260     offset++;
7261   }
7262
7263
7264   pic16_freeAsmop(left,NULL,ic,TRUE);
7265   pic16_freeAsmop(result,NULL,ic,TRUE);
7266 }
7267
7268
7269 /* gpasm can get the highest order bit with HIGH/UPPER
7270  * so the following probably is not needed -- VR */
7271  
7272 /*-----------------------------------------------------------------*/
7273 /* genGetHbit - generates code get highest order bit               */
7274 /*-----------------------------------------------------------------*/
7275 static void genGetHbit (iCode *ic)
7276 {
7277     operand *left, *result;
7278     left = IC_LEFT(ic);
7279     result=IC_RESULT(ic);
7280     pic16_aopOp (left,ic,FALSE);
7281     pic16_aopOp (result,ic,FALSE);
7282
7283     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7284     /* get the highest order byte into a */
7285     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7286     if(AOP_TYPE(result) == AOP_CRY){
7287         pic16_emitcode("rlc","a");
7288         pic16_outBitC(result);
7289     }
7290     else{
7291         pic16_emitcode("rl","a");
7292         pic16_emitcode("anl","a,#0x01");
7293         pic16_outAcc(result);
7294     }
7295
7296
7297     pic16_freeAsmop(left,NULL,ic,TRUE);
7298     pic16_freeAsmop(result,NULL,ic,TRUE);
7299 }
7300
7301 #if 0
7302 /*-----------------------------------------------------------------*/
7303 /* AccRol - rotate left accumulator by known count                 */
7304 /*-----------------------------------------------------------------*/
7305 static void AccRol (int shCount)
7306 {
7307     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7308     shCount &= 0x0007;              // shCount : 0..7
7309     switch(shCount){
7310         case 0 :
7311             break;
7312         case 1 :
7313             pic16_emitcode("rl","a");
7314             break;
7315         case 2 :
7316             pic16_emitcode("rl","a");
7317             pic16_emitcode("rl","a");
7318             break;
7319         case 3 :
7320             pic16_emitcode("swap","a");
7321             pic16_emitcode("rr","a");
7322             break;
7323         case 4 :
7324             pic16_emitcode("swap","a");
7325             break;
7326         case 5 :
7327             pic16_emitcode("swap","a");
7328             pic16_emitcode("rl","a");
7329             break;
7330         case 6 :
7331             pic16_emitcode("rr","a");
7332             pic16_emitcode("rr","a");
7333             break;
7334         case 7 :
7335             pic16_emitcode("rr","a");
7336             break;
7337     }
7338 }
7339 #endif
7340
7341 /*-----------------------------------------------------------------*/
7342 /* AccLsh - left shift accumulator by known count                  */
7343 /*-----------------------------------------------------------------*/
7344 static void AccLsh (int shCount)
7345 {
7346         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7347         switch(shCount){
7348                 case 0 :
7349                         return;
7350                         break;
7351                 case 1 :
7352                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7353                         break;
7354                 case 2 :
7355                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7356                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7357                         break;
7358                 case 3 :
7359                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7360                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7361                         break;
7362                 case 4 :
7363                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7364                         break;
7365                 case 5 :
7366                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7367                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7368                         break;
7369                 case 6 :
7370                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7371                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7372                         break;
7373                 case 7 :
7374                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7375                         break;
7376         }
7377
7378         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
7379 }
7380
7381 /*-----------------------------------------------------------------*/
7382 /* AccRsh - right shift accumulator by known count                 */
7383 /*-----------------------------------------------------------------*/
7384 static void AccRsh (int shCount, int andmask)
7385 {
7386         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7387         switch(shCount){
7388                 case 0 :
7389                         return; break;
7390                 case 1 :
7391                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7392 //                      andmask = 0;    /* no need */
7393                         break;
7394                 case 2 :
7395                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7396                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7397 //                      andmask = 0;    /* no need */
7398                         break;
7399                 case 3 :
7400                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7401                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7402                         break;
7403                 case 4 :
7404                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7405                         break;
7406                 case 5 :
7407                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7408                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7409                         break;
7410                 case 6 :
7411                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7412                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7413                         break;
7414                 case 7 :
7415                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7416                         break;
7417         }
7418         
7419         if(andmask)
7420                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7421         else
7422                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7423 }
7424
7425 #if 0
7426 /*-----------------------------------------------------------------*/
7427 /* AccSRsh - signed right shift accumulator by known count                 */
7428 /*-----------------------------------------------------------------*/
7429 static void AccSRsh (int shCount)
7430 {
7431     symbol *tlbl ;
7432     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7433     if(shCount != 0){
7434         if(shCount == 1){
7435             pic16_emitcode("mov","c,acc.7");
7436             pic16_emitcode("rrc","a");
7437         } else if(shCount == 2){
7438             pic16_emitcode("mov","c,acc.7");
7439             pic16_emitcode("rrc","a");
7440             pic16_emitcode("mov","c,acc.7");
7441             pic16_emitcode("rrc","a");
7442         } else {
7443             tlbl = newiTempLabel(NULL);
7444             /* rotate right accumulator */
7445             AccRol(8 - shCount);
7446             /* and kill the higher order bits */
7447             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7448             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7449             pic16_emitcode("orl","a,#0x%02x",
7450                      (unsigned char)~SRMask[shCount]);
7451             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7452         }
7453     }
7454 }
7455 #endif
7456 /*-----------------------------------------------------------------*/
7457 /* shiftR1Left2Result - shift right one byte from left to result   */
7458 /*-----------------------------------------------------------------*/
7459 static void shiftR1Left2ResultSigned (operand *left, int offl,
7460                                 operand *result, int offr,
7461                                 int shCount)
7462 {
7463   int same;
7464
7465   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7466
7467   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7468
7469   switch(shCount) {
7470   case 1:
7471     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7472     if(same) 
7473       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7474     else {
7475       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7476       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7477     }
7478
7479     break;
7480   case 2:
7481
7482     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7483     if(same) 
7484       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7485     else {
7486       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7487       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7488     }
7489     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7490     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7491
7492     break;
7493
7494   case 3:
7495     if(same)
7496       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7497     else {
7498       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7499       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7500     }
7501
7502     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7503     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7504     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7505
7506     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7507     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7508
7509     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7510     break;
7511
7512   case 4:
7513     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7514     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
7515     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7516     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
7517     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7518     break;
7519   case 5:
7520     if(same) {
7521       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
7522     } else {
7523       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
7524       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7525     }
7526     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
7527     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
7528     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7529     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
7530     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7531     break;
7532
7533   case 6:
7534     if(same) {
7535       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7536       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7537       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7538       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7539       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7540       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7541     } else {
7542       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7543       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7544       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7545       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7546       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7547     }
7548     break;
7549
7550   case 7:
7551     if(same) {
7552       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7553       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7554       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7555       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7556     } else {
7557       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7558       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7559       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7560     }
7561
7562   default:
7563     break;
7564   }
7565 }
7566
7567 /*-----------------------------------------------------------------*/
7568 /* shiftR1Left2Result - shift right one byte from left to result   */
7569 /*-----------------------------------------------------------------*/
7570 static void shiftR1Left2Result (operand *left, int offl,
7571                                 operand *result, int offr,
7572                                 int shCount, int sign)
7573 {
7574   int same;
7575
7576   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7577
7578   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7579
7580   /* Copy the msb into the carry if signed. */
7581   if(sign) {
7582     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7583     return;
7584   }
7585
7586
7587
7588   switch(shCount) {
7589   case 1:
7590     emitCLRC;
7591     if(same) 
7592       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7593     else {
7594       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7595       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7596     }
7597     break;
7598   case 2:
7599     emitCLRC;
7600     if(same) {
7601       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7602     } else {
7603       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7604       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7605     }
7606     emitCLRC;
7607     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7608
7609     break;
7610   case 3:
7611     if(same)
7612       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7613     else {
7614       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7615       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7616     }
7617
7618     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7619     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7620     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7621     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7622     break;
7623       
7624   case 4:
7625     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7626     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7627     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7628     break;
7629
7630   case 5:
7631     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7632     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7633     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7634     emitCLRC;
7635     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7636
7637     break;
7638   case 6:
7639
7640     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
7641     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7642     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7643     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7644     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7645     break;
7646
7647   case 7:
7648
7649     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7650     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7651     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7652
7653     break;
7654
7655   default:
7656     break;
7657   }
7658 }
7659
7660 /*-----------------------------------------------------------------*/
7661 /* shiftL1Left2Result - shift left one byte from left to result    */
7662 /*-----------------------------------------------------------------*/
7663 static void shiftL1Left2Result (operand *left, int offl,
7664                                 operand *result, int offr, int shCount)
7665 {
7666   int same;
7667
7668   //    char *l;
7669   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7670
7671   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7672   DEBUGpic16_emitcode ("; ***","same =  %d",same);
7673     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7674     //    MOVA(l);
7675     /* shift left accumulator */
7676     //AccLsh(shCount); // don't comment out just yet...
7677   //    pic16_aopPut(AOP(result),"a",offr);
7678
7679   switch(shCount) {
7680   case 1:
7681     /* Shift left 1 bit position */
7682     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7683     if(same) {
7684       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7685     } else {
7686       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7687       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7688     }
7689     break;
7690   case 2:
7691     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7692     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7693     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7694     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7695     break;
7696   case 3:
7697     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7698     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7699     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7700     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7701     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7702     break;
7703   case 4:
7704     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7705     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7706     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7707     break;
7708   case 5:
7709     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7710     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7711     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7712     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7713     break;
7714   case 6:
7715     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7716     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7717     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7718     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7719     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7720     break;
7721   case 7:
7722     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7723     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7724     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7725     break;
7726
7727   default:
7728     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7729   }
7730
7731 }
7732
7733 /*-----------------------------------------------------------------*/
7734 /* movLeft2Result - move byte from left to result                  */
7735 /*-----------------------------------------------------------------*/
7736 static void movLeft2Result (operand *left, int offl,
7737                             operand *result, int offr)
7738 {
7739   char *l;
7740   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7741   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7742     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7743
7744     if (*l == '@' && (IS_AOP_PREG(result))) {
7745       pic16_emitcode("mov","a,%s",l);
7746       pic16_aopPut(AOP(result),"a",offr);
7747     } else {
7748       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7749       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7750     }
7751   }
7752 }
7753
7754 /*-----------------------------------------------------------------*/
7755 /* shiftL2Left2Result - shift left two bytes from left to result   */
7756 /*-----------------------------------------------------------------*/
7757 static void shiftL2Left2Result (operand *left, int offl,
7758                                 operand *result, int offr, int shCount)
7759 {
7760   int same = pic16_sameRegs(AOP(result), AOP(left));
7761   int i;
7762
7763   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7764
7765   if (same && (offl != offr)) { // shift bytes
7766     if (offr > offl) {
7767        for(i=1;i>-1;i--) {
7768          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7769          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7770        }
7771     } else { // just treat as different later on
7772                 same = 0;
7773     }
7774   }
7775
7776   if(same) {
7777     switch(shCount) {
7778     case 0:
7779       break;
7780     case 1:
7781     case 2:
7782     case 3:
7783
7784       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7785       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7786       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7787
7788       while(--shCount) {
7789                 emitCLRC;
7790                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7791                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7792       }
7793
7794       break;
7795     case 4:
7796     case 5:
7797       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
7798       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
7799       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7800       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7801       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
7802       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7803       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7804       if(shCount >=5) {
7805                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7806                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7807       }
7808       break;
7809     case 6:
7810       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7811       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7812       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7813       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7814       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7815       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7816       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7817       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7818       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7819       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7820       break;
7821     case 7:
7822       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7823       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7824       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7825       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7826       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7827     }
7828
7829   } else {
7830     switch(shCount) {
7831     case 0:
7832       break;
7833     case 1:
7834     case 2:
7835     case 3:
7836       /* note, use a mov/add for the shift since the mov has a
7837          chance of getting optimized out */
7838       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7839       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7840       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7841       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
7842       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7843
7844       while(--shCount) {
7845                 emitCLRC;
7846                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7847                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7848       }
7849       break;
7850
7851     case 4:
7852     case 5:
7853       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7854       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7855       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7856       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7857       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7858       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7859       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7860       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7861
7862
7863       if(shCount == 5) {
7864                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7865                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7866       }
7867       break;
7868     case 6:
7869       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7870       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7871       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7872       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7873
7874       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7875       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7876       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7877       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7878       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7879       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7880       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7881       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7882       break;
7883     case 7:
7884       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7885       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7886       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7887       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7888       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7889     }
7890   }
7891
7892 }
7893 /*-----------------------------------------------------------------*/
7894 /* shiftR2Left2Result - shift right two bytes from left to result  */
7895 /*-----------------------------------------------------------------*/
7896 static void shiftR2Left2Result (operand *left, int offl,
7897                                 operand *result, int offr,
7898                                 int shCount, int sign)
7899 {
7900   int same = pic16_sameRegs(AOP(result), AOP(left));
7901   int i;
7902   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7903
7904   if (same && (offl != offr)) { // shift right bytes
7905     if (offr < offl) {
7906        for(i=0;i<2;i++) {
7907          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7908          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7909        }
7910     } else { // just treat as different later on
7911                 same = 0;
7912     }
7913   }
7914
7915   switch(shCount) {
7916   case 0:
7917     break;
7918   case 1:
7919   case 2:
7920   case 3:
7921     if(sign)
7922       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7923     else
7924       emitCLRC;
7925
7926     if(same) {
7927       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7928       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7929     } else {
7930       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7931       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7932       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7933       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7934     }
7935
7936     while(--shCount) {
7937       if(sign)
7938                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7939       else
7940                 emitCLRC;
7941       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7942       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7943     }
7944     break;
7945   case 4:
7946   case 5:
7947     if(same) {
7948
7949       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7950       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7951       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7952
7953       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7954       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7955       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7956       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7957     } else {
7958       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7959       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7960       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7961
7962       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7963       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7964       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7965       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7966       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7967     }
7968
7969     if(shCount >=5) {
7970       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7971       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7972     }
7973
7974     if(sign) {
7975       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7976       pic16_emitpcode(POC_BTFSC, 
7977                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
7978       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7979     }
7980
7981     break;
7982
7983   case 6:
7984     if(same) {
7985
7986       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7987       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7988
7989       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7990       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7991       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7992       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7993       if(sign) {
7994         pic16_emitpcode(POC_BTFSC, 
7995                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0, PO_GPR_REGISTER));
7996         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7997       }
7998       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7999       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
8000       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8001       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8002     } else {
8003       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8004       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8005       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8006       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8007       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8008       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8009       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
8010       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8011       if(sign) {
8012         pic16_emitpcode(POC_BTFSC, 
8013                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8014         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8015       }
8016       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8017       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8018
8019         
8020     }
8021
8022     break;
8023   case 7:
8024     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8025     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8026     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8027     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
8028     if(sign) {
8029       emitSKPNC;
8030       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
8031     } else 
8032       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8033   }
8034 }
8035
8036
8037 /*-----------------------------------------------------------------*/
8038 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
8039 /*-----------------------------------------------------------------*/
8040 static void shiftLLeftOrResult (operand *left, int offl,
8041                                 operand *result, int offr, int shCount)
8042 {
8043     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8044
8045     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8046     /* shift left accumulator */
8047     AccLsh(shCount);
8048     /* or with result */
8049     /* back to result */
8050     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8051 }
8052
8053 /*-----------------------------------------------------------------*/
8054 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
8055 /*-----------------------------------------------------------------*/
8056 static void shiftRLeftOrResult (operand *left, int offl,
8057                                 operand *result, int offr, int shCount)
8058 {
8059     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8060     
8061     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8062     /* shift right accumulator */
8063     AccRsh(shCount, 1);
8064     /* or with result */
8065     /* back to result */
8066     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8067 }
8068
8069 /*-----------------------------------------------------------------*/
8070 /* genlshOne - left shift a one byte quantity by known count       */
8071 /*-----------------------------------------------------------------*/
8072 static void genlshOne (operand *result, operand *left, int shCount)
8073 {       
8074     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8075     shiftL1Left2Result(left, LSB, result, LSB, shCount);
8076 }
8077
8078 /*-----------------------------------------------------------------*/
8079 /* genlshTwo - left shift two bytes by known amount != 0           */
8080 /*-----------------------------------------------------------------*/
8081 static void genlshTwo (operand *result,operand *left, int shCount)
8082 {
8083     int size;
8084     
8085     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8086     size = pic16_getDataSize(result);
8087
8088     /* if shCount >= 8 */
8089     if (shCount >= 8) {
8090         shCount -= 8 ;
8091
8092         if (size > 1){
8093             if (shCount)
8094                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8095             else 
8096                 movLeft2Result(left, LSB, result, MSB16);
8097         }
8098         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8099     }
8100
8101     /*  1 <= shCount <= 7 */
8102     else {  
8103         if(size == 1)
8104             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
8105         else 
8106             shiftL2Left2Result(left, LSB, result, LSB, shCount);
8107     }
8108 }
8109
8110 /*-----------------------------------------------------------------*/
8111 /* shiftLLong - shift left one long from left to result            */
8112 /* offr = LSB or MSB16                                             */
8113 /*-----------------------------------------------------------------*/
8114 static void shiftLLong (operand *left, operand *result, int offr )
8115 {
8116     int size = AOP_SIZE(result);
8117     int same = pic16_sameRegs(AOP(left),AOP(result));
8118         int i;
8119
8120     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
8121
8122         if (same && (offr == MSB16)) { //shift one byte
8123                 for(i=size-1;i>=MSB16;i--) {
8124                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
8125                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
8126                 }
8127         } else {
8128                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
8129         }
8130         
8131     if (size >= LSB+offr ){
8132                 if (same) {
8133                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
8134                 } else {
8135                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
8136                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
8137                 }
8138          }
8139
8140     if(size >= MSB16+offr){
8141                 if (same) {
8142                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
8143                 } else {
8144                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
8145                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
8146                 }
8147     }
8148
8149     if(size >= MSB24+offr){
8150                 if (same) {
8151                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
8152                 } else {
8153                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
8154                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
8155                 }
8156     }
8157
8158     if(size > MSB32+offr){
8159                 if (same) {
8160                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
8161                 } else {
8162                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
8163                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
8164                 }
8165     }
8166     if(offr != LSB)
8167                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8168
8169 }
8170
8171 /*-----------------------------------------------------------------*/
8172 /* genlshFour - shift four byte by a known amount != 0             */
8173 /*-----------------------------------------------------------------*/
8174 static void genlshFour (operand *result, operand *left, int shCount)
8175 {
8176     int size;
8177
8178     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8179     size = AOP_SIZE(result);
8180
8181     /* if shifting more that 3 bytes */
8182     if (shCount >= 24 ) {
8183         shCount -= 24;
8184         if (shCount)
8185             /* lowest order of left goes to the highest
8186             order of the destination */
8187             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
8188         else
8189             movLeft2Result(left, LSB, result, MSB32);
8190
8191                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8192                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8193                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
8194
8195         return;
8196     }
8197
8198     /* more than two bytes */
8199     else if ( shCount >= 16 ) {
8200         /* lower order two bytes goes to higher order two bytes */
8201         shCount -= 16;
8202         /* if some more remaining */
8203         if (shCount)
8204             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
8205         else {
8206             movLeft2Result(left, MSB16, result, MSB32);
8207             movLeft2Result(left, LSB, result, MSB24);
8208         }
8209                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8210                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8211         return;
8212     }    
8213
8214     /* if more than 1 byte */
8215     else if ( shCount >= 8 ) {
8216         /* lower order three bytes goes to higher order  three bytes */
8217         shCount -= 8;
8218         if(size == 2){
8219             if(shCount)
8220                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8221             else
8222                 movLeft2Result(left, LSB, result, MSB16);
8223         }
8224         else{   /* size = 4 */
8225             if(shCount == 0){
8226                 movLeft2Result(left, MSB24, result, MSB32);
8227                 movLeft2Result(left, MSB16, result, MSB24);
8228                 movLeft2Result(left, LSB, result, MSB16);
8229                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8230             }
8231             else if(shCount == 1)
8232                 shiftLLong(left, result, MSB16);
8233             else{
8234                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8235                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8236                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8237                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8238             }
8239         }
8240     }
8241
8242     /* 1 <= shCount <= 7 */
8243     else if(shCount <= 3)
8244     { 
8245         shiftLLong(left, result, LSB);
8246         while(--shCount >= 1)
8247             shiftLLong(result, result, LSB);
8248     }
8249     /* 3 <= shCount <= 7, optimize */
8250     else{
8251         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8252         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8253         shiftL2Left2Result(left, LSB, result, LSB, shCount);
8254     }
8255 }
8256
8257 /*-----------------------------------------------------------------*/
8258 /* genLeftShiftLiteral - left shifting by known count              */
8259 /*-----------------------------------------------------------------*/
8260 static void genLeftShiftLiteral (operand *left,
8261                                  operand *right,
8262                                  operand *result,
8263                                  iCode *ic)
8264 {    
8265     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8266     int size;
8267
8268     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8269     pic16_freeAsmop(right,NULL,ic,TRUE);
8270
8271     pic16_aopOp(left,ic,FALSE);
8272     pic16_aopOp(result,ic,FALSE);
8273
8274     size = getSize(operandType(result));
8275
8276 #if VIEW_SIZE
8277     pic16_emitcode("; shift left ","result %d, left %d",size,
8278              AOP_SIZE(left));
8279 #endif
8280
8281     /* I suppose that the left size >= result size */
8282     if(shCount == 0){
8283         while(size--){
8284             movLeft2Result(left, size, result, size);
8285         }
8286     }
8287
8288     else if(shCount >= (size * 8))
8289         while(size--)
8290             pic16_aopPut(AOP(result),zero,size);
8291     else{
8292         switch (size) {
8293             case 1:
8294                 genlshOne (result,left,shCount);
8295                 break;
8296
8297             case 2:
8298             case 3:
8299                 genlshTwo (result,left,shCount);
8300                 break;
8301
8302             case 4:
8303                 genlshFour (result,left,shCount);
8304                 break;
8305         }
8306     }
8307     pic16_freeAsmop(left,NULL,ic,TRUE);
8308     pic16_freeAsmop(result,NULL,ic,TRUE);
8309 }
8310
8311 /*-----------------------------------------------------------------*
8312  * genMultiAsm - repeat assembly instruction for size of register.
8313  * if endian == 1, then the high byte (i.e base address + size of 
8314  * register) is used first else the low byte is used first;
8315  *-----------------------------------------------------------------*/
8316 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8317 {
8318
8319   int offset = 0;
8320
8321   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8322
8323   if(!reg)
8324     return;
8325
8326   if(!endian) {
8327     endian = 1;
8328   } else {
8329     endian = -1;
8330     offset = size-1;
8331   }
8332
8333   while(size--) {
8334     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
8335     offset += endian;
8336   }
8337
8338 }
8339 /*-----------------------------------------------------------------*/
8340 /* genLeftShift - generates code for left shifting                 */
8341 /*-----------------------------------------------------------------*/
8342 static void genLeftShift (iCode *ic)
8343 {
8344   operand *left,*right, *result;
8345   int size, offset;
8346   char *l;
8347   symbol *tlbl , *tlbl1;
8348   pCodeOp *pctemp;
8349
8350   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8351
8352   right = IC_RIGHT(ic);
8353   left  = IC_LEFT(ic);
8354   result = IC_RESULT(ic);
8355
8356   pic16_aopOp(right,ic,FALSE);
8357
8358   /* if the shift count is known then do it 
8359      as efficiently as possible */
8360   if (AOP_TYPE(right) == AOP_LIT) {
8361     genLeftShiftLiteral (left,right,result,ic);
8362     return ;
8363   }
8364
8365   /* shift count is unknown then we have to form 
8366      a loop get the loop count in B : Note: we take
8367      only the lower order byte since shifting
8368      more that 32 bits make no sense anyway, ( the
8369      largest size of an object can be only 32 bits ) */  
8370
8371     
8372   pic16_aopOp(left,ic,FALSE);
8373   pic16_aopOp(result,ic,FALSE);
8374
8375   /* now move the left to the result if they are not the
8376      same */
8377   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8378       AOP_SIZE(result) > 1) {
8379
8380     size = AOP_SIZE(result);
8381     offset=0;
8382     while (size--) {
8383       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8384       if (*l == '@' && (IS_AOP_PREG(result))) {
8385
8386         pic16_emitcode("mov","a,%s",l);
8387         pic16_aopPut(AOP(result),"a",offset);
8388       } else {
8389         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8390         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8391         //pic16_aopPut(AOP(result),l,offset);
8392       }
8393       offset++;
8394     }
8395   }
8396
8397   size = AOP_SIZE(result);
8398
8399   /* if it is only one byte then */
8400   if (size == 1) {
8401     if(optimized_for_speed) {
8402       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8403       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
8404       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
8405       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8406       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8407       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8408       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8409       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
8410       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
8411       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
8412       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
8413       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8414     } else {
8415
8416       tlbl = newiTempLabel(NULL);
8417       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8418                 pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8419                 pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8420       }
8421
8422       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8423       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8424       pic16_emitpLabel(tlbl->key);
8425       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8426       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8427       emitSKPC;
8428       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8429     }
8430     goto release ;
8431   }
8432     
8433   if (pic16_sameRegs(AOP(left),AOP(result))) {
8434
8435     tlbl = newiTempLabel(NULL);
8436     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8437     genMultiAsm(POC_RRCF, result, size,1);
8438     pic16_emitpLabel(tlbl->key);
8439     genMultiAsm(POC_RLCF, result, size,0);
8440     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8441     emitSKPC;
8442     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8443     goto release;
8444   }
8445
8446   //tlbl = newiTempLabel(NULL);
8447   //offset = 0 ;   
8448   //tlbl1 = newiTempLabel(NULL);
8449
8450   //reAdjustPreg(AOP(result));    
8451     
8452   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
8453   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8454   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8455   //MOVA(l);
8456   //pic16_emitcode("add","a,acc");         
8457   //pic16_aopPut(AOP(result),"a",offset++);
8458   //while (--size) {
8459   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8460   //  MOVA(l);
8461   //  pic16_emitcode("rlc","a");         
8462   //  pic16_aopPut(AOP(result),"a",offset++);
8463   //}
8464   //reAdjustPreg(AOP(result));
8465
8466   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8467   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8468
8469
8470   tlbl = newiTempLabel(NULL);
8471   tlbl1= newiTempLabel(NULL);
8472
8473   size = AOP_SIZE(result);
8474   offset = 1;
8475
8476   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8477
8478   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8479
8480   /* offset should be 0, 1 or 3 */
8481   
8482   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8483   emitSKPNZ;
8484   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8485
8486   pic16_emitpcode(POC_MOVWF, pctemp);
8487
8488
8489   pic16_emitpLabel(tlbl->key);
8490
8491   emitCLRC;
8492   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
8493   while(--size)
8494     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
8495
8496   pic16_emitpcode(POC_DECFSZ,  pctemp);
8497   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8498   pic16_emitpLabel(tlbl1->key);
8499
8500   pic16_popReleaseTempReg(pctemp);
8501
8502
8503  release:
8504   pic16_freeAsmop (right,NULL,ic,TRUE);
8505   pic16_freeAsmop(left,NULL,ic,TRUE);
8506   pic16_freeAsmop(result,NULL,ic,TRUE);
8507 }
8508
8509 /*-----------------------------------------------------------------*/
8510 /* genrshOne - right shift a one byte quantity by known count      */
8511 /*-----------------------------------------------------------------*/
8512 static void genrshOne (operand *result, operand *left,
8513                        int shCount, int sign)
8514 {
8515     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8516     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8517 }
8518
8519 /*-----------------------------------------------------------------*/
8520 /* genrshTwo - right shift two bytes by known amount != 0          */
8521 /*-----------------------------------------------------------------*/
8522 static void genrshTwo (operand *result,operand *left,
8523                        int shCount, int sign)
8524 {
8525   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8526   /* if shCount >= 8 */
8527   if (shCount >= 8) {
8528     shCount -= 8 ;
8529     if (shCount)
8530       shiftR1Left2Result(left, MSB16, result, LSB,
8531                          shCount, sign);
8532     else
8533       movLeft2Result(left, MSB16, result, LSB);
8534
8535     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8536
8537     if(sign) {
8538       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8539       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8540     }
8541   }
8542
8543   /*  1 <= shCount <= 7 */
8544   else
8545     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
8546 }
8547
8548 /*-----------------------------------------------------------------*/
8549 /* shiftRLong - shift right one long from left to result           */
8550 /* offl = LSB or MSB16                                             */
8551 /*-----------------------------------------------------------------*/
8552 static void shiftRLong (operand *left, int offl,
8553                         operand *result, int sign)
8554 {
8555     int size = AOP_SIZE(result);
8556     int same = pic16_sameRegs(AOP(left),AOP(result));
8557     int i;
8558     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8559
8560         if (same && (offl == MSB16)) { //shift one byte right
8561                 for(i=MSB16;i<size;i++) {
8562                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8563                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8564                 }
8565         }
8566
8567     if(sign)
8568                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8569         else
8570                 emitCLRC;
8571
8572         if (same) {
8573                 if (offl == LSB)
8574                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8575         } else {
8576         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8577         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8578         }
8579
8580     if(offl == MSB16) {
8581         /* add sign of "a" */
8582         pic16_addSign(result, MSB32, sign);
8583         }
8584
8585         if (same) {
8586         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8587         } else {
8588         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8589         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8590         }
8591         
8592         if (same) {
8593         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8594         } else {
8595         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8596         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8597         }
8598
8599         if (same) {
8600         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8601         } else {
8602         if(offl == LSB){
8603                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8604                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8605         }
8606         }
8607 }
8608
8609 /*-----------------------------------------------------------------*/
8610 /* genrshFour - shift four byte by a known amount != 0             */
8611 /*-----------------------------------------------------------------*/
8612 static void genrshFour (operand *result, operand *left,
8613                         int shCount, int sign)
8614 {
8615   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8616   /* if shifting more that 3 bytes */
8617   if(shCount >= 24 ) {
8618     shCount -= 24;
8619     if(shCount)
8620       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8621     else
8622       movLeft2Result(left, MSB32, result, LSB);
8623
8624     pic16_addSign(result, MSB16, sign);
8625   }
8626   else if(shCount >= 16){
8627     shCount -= 16;
8628     if(shCount)
8629       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8630     else{
8631       movLeft2Result(left, MSB24, result, LSB);
8632       movLeft2Result(left, MSB32, result, MSB16);
8633     }
8634     pic16_addSign(result, MSB24, sign);
8635   }
8636   else if(shCount >= 8){
8637     shCount -= 8;
8638     if(shCount == 1)
8639       shiftRLong(left, MSB16, result, sign);
8640     else if(shCount == 0){
8641       movLeft2Result(left, MSB16, result, LSB);
8642       movLeft2Result(left, MSB24, result, MSB16);
8643       movLeft2Result(left, MSB32, result, MSB24);
8644       pic16_addSign(result, MSB32, sign);
8645     }
8646     else{ //shcount >= 2
8647       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8648       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8649       /* the last shift is signed */
8650       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8651       pic16_addSign(result, MSB32, sign);
8652     }
8653   }
8654   else{   /* 1 <= shCount <= 7 */
8655     if(shCount <= 2){
8656       shiftRLong(left, LSB, result, sign);
8657       if(shCount == 2)
8658         shiftRLong(result, LSB, result, sign);
8659     }
8660     else{
8661       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8662       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8663       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8664     }
8665   }
8666 }
8667
8668 /*-----------------------------------------------------------------*/
8669 /* genRightShiftLiteral - right shifting by known count            */
8670 /*-----------------------------------------------------------------*/
8671 static void genRightShiftLiteral (operand *left,
8672                                   operand *right,
8673                                   operand *result,
8674                                   iCode *ic,
8675                                   int sign)
8676 {    
8677   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8678   int lsize,res_size;
8679
8680   pic16_freeAsmop(right,NULL,ic,TRUE);
8681
8682   pic16_aopOp(left,ic,FALSE);
8683   pic16_aopOp(result,ic,FALSE);
8684
8685   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8686
8687 #if VIEW_SIZE
8688   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8689                  AOP_SIZE(left));
8690 #endif
8691
8692   lsize = pic16_getDataSize(left);
8693   res_size = pic16_getDataSize(result);
8694   /* test the LEFT size !!! */
8695
8696   /* I suppose that the left size >= result size */
8697   if(shCount == 0){
8698     while(res_size--)
8699       movLeft2Result(left, lsize, result, res_size);
8700   }
8701
8702   else if(shCount >= (lsize * 8)){
8703
8704     if(res_size == 1) {
8705       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8706       if(sign) {
8707         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8708         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8709       }
8710     } else {
8711
8712       if(sign) {
8713         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8714         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8715         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8716         while(res_size--)
8717           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8718
8719       } else {
8720
8721         while(res_size--)
8722           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8723       }
8724     }
8725   } else {
8726
8727     switch (res_size) {
8728     case 1:
8729       genrshOne (result,left,shCount,sign);
8730       break;
8731
8732     case 2:
8733       genrshTwo (result,left,shCount,sign);
8734       break;
8735
8736     case 4:
8737       genrshFour (result,left,shCount,sign);
8738       break;
8739     default :
8740       break;
8741     }
8742
8743   }
8744
8745   pic16_freeAsmop(left,NULL,ic,TRUE);
8746   pic16_freeAsmop(result,NULL,ic,TRUE);
8747 }
8748
8749 /*-----------------------------------------------------------------*/
8750 /* genSignedRightShift - right shift of signed number              */
8751 /*-----------------------------------------------------------------*/
8752 static void genSignedRightShift (iCode *ic)
8753 {
8754   operand *right, *left, *result;
8755   int size, offset;
8756   //  char *l;
8757   symbol *tlbl, *tlbl1 ;
8758   pCodeOp *pctemp;
8759
8760   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8761
8762   /* we do it the hard way put the shift count in b
8763      and loop thru preserving the sign */
8764   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8765
8766   right = IC_RIGHT(ic);
8767   left  = IC_LEFT(ic);
8768   result = IC_RESULT(ic);
8769
8770   pic16_aopOp(right,ic,FALSE);  
8771   pic16_aopOp(left,ic,FALSE);
8772   pic16_aopOp(result,ic,FALSE);
8773
8774
8775   if ( AOP_TYPE(right) == AOP_LIT) {
8776     genRightShiftLiteral (left,right,result,ic,1);
8777     return ;
8778   }
8779   /* shift count is unknown then we have to form 
8780      a loop get the loop count in B : Note: we take
8781      only the lower order byte since shifting
8782      more that 32 bits make no sense anyway, ( the
8783      largest size of an object can be only 32 bits ) */  
8784
8785   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8786   //pic16_emitcode("inc","b");
8787   //pic16_freeAsmop (right,NULL,ic,TRUE);
8788   //pic16_aopOp(left,ic,FALSE);
8789   //pic16_aopOp(result,ic,FALSE);
8790
8791   /* now move the left to the result if they are not the
8792      same */
8793   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8794       AOP_SIZE(result) > 1) {
8795
8796     size = AOP_SIZE(result);
8797     offset=0;
8798     while (size--) { 
8799       /*
8800         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8801         if (*l == '@' && IS_AOP_PREG(result)) {
8802
8803         pic16_emitcode("mov","a,%s",l);
8804         pic16_aopPut(AOP(result),"a",offset);
8805         } else
8806         pic16_aopPut(AOP(result),l,offset);
8807       */
8808       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8809       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8810
8811       offset++;
8812     }
8813   }
8814
8815   /* mov the highest order bit to OVR */    
8816   tlbl = newiTempLabel(NULL);
8817   tlbl1= newiTempLabel(NULL);
8818
8819   size = AOP_SIZE(result);
8820   offset = size - 1;
8821
8822   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8823
8824   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8825
8826   /* offset should be 0, 1 or 3 */
8827   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
8828   emitSKPNZ;
8829   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8830
8831   pic16_emitpcode(POC_MOVWF, pctemp);
8832
8833
8834   pic16_emitpLabel(tlbl->key);
8835
8836   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
8837   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
8838
8839   while(--size) {
8840     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
8841   }
8842
8843   pic16_emitpcode(POC_DECFSZ,  pctemp);
8844   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8845   pic16_emitpLabel(tlbl1->key);
8846
8847   pic16_popReleaseTempReg(pctemp);
8848 #if 0
8849   size = AOP_SIZE(result);
8850   offset = size - 1;
8851   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8852   pic16_emitcode("rlc","a");
8853   pic16_emitcode("mov","ov,c");
8854   /* if it is only one byte then */
8855   if (size == 1) {
8856     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8857     MOVA(l);
8858     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8859     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8860     pic16_emitcode("mov","c,ov");
8861     pic16_emitcode("rrc","a");
8862     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8863     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8864     pic16_aopPut(AOP(result),"a",0);
8865     goto release ;
8866   }
8867
8868   reAdjustPreg(AOP(result));
8869   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8870   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8871   pic16_emitcode("mov","c,ov");
8872   while (size--) {
8873     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8874     MOVA(l);
8875     pic16_emitcode("rrc","a");         
8876     pic16_aopPut(AOP(result),"a",offset--);
8877   }
8878   reAdjustPreg(AOP(result));
8879   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8880   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8881
8882  release:
8883 #endif
8884
8885   pic16_freeAsmop(left,NULL,ic,TRUE);
8886   pic16_freeAsmop(result,NULL,ic,TRUE);
8887   pic16_freeAsmop(right,NULL,ic,TRUE);
8888 }
8889
8890 /*-----------------------------------------------------------------*/
8891 /* genRightShift - generate code for right shifting                */
8892 /*-----------------------------------------------------------------*/
8893 static void genRightShift (iCode *ic)
8894 {
8895     operand *right, *left, *result;
8896     sym_link *letype ;
8897     int size, offset;
8898     char *l;
8899     symbol *tlbl, *tlbl1 ;
8900
8901     /* if signed then we do it the hard way preserve the
8902     sign bit moving it inwards */
8903     letype = getSpec(operandType(IC_LEFT(ic)));
8904     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8905
8906     if (!SPEC_USIGN(letype)) {
8907         genSignedRightShift (ic);
8908         return ;
8909     }
8910
8911     /* signed & unsigned types are treated the same : i.e. the
8912     signed is NOT propagated inwards : quoting from the
8913     ANSI - standard : "for E1 >> E2, is equivalent to division
8914     by 2**E2 if unsigned or if it has a non-negative value,
8915     otherwise the result is implementation defined ", MY definition
8916     is that the sign does not get propagated */
8917
8918     right = IC_RIGHT(ic);
8919     left  = IC_LEFT(ic);
8920     result = IC_RESULT(ic);
8921
8922     pic16_aopOp(right,ic,FALSE);
8923
8924     /* if the shift count is known then do it 
8925     as efficiently as possible */
8926     if (AOP_TYPE(right) == AOP_LIT) {
8927         genRightShiftLiteral (left,right,result,ic, 0);
8928         return ;
8929     }
8930
8931     /* shift count is unknown then we have to form 
8932     a loop get the loop count in B : Note: we take
8933     only the lower order byte since shifting
8934     more that 32 bits make no sense anyway, ( the
8935     largest size of an object can be only 32 bits ) */  
8936
8937     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8938     pic16_emitcode("inc","b");
8939     pic16_aopOp(left,ic,FALSE);
8940     pic16_aopOp(result,ic,FALSE);
8941
8942     /* now move the left to the result if they are not the
8943     same */
8944     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8945         AOP_SIZE(result) > 1) {
8946
8947         size = AOP_SIZE(result);
8948         offset=0;
8949         while (size--) {
8950             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8951             if (*l == '@' && IS_AOP_PREG(result)) {
8952
8953                 pic16_emitcode("mov","a,%s",l);
8954                 pic16_aopPut(AOP(result),"a",offset);
8955             } else
8956                 pic16_aopPut(AOP(result),l,offset);
8957             offset++;
8958         }
8959     }
8960
8961     tlbl = newiTempLabel(NULL);
8962     tlbl1= newiTempLabel(NULL);
8963     size = AOP_SIZE(result);
8964     offset = size - 1;
8965
8966     /* if it is only one byte then */
8967     if (size == 1) {
8968
8969       tlbl = newiTempLabel(NULL);
8970       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8971         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8972         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8973       }
8974
8975       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8976       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8977       pic16_emitpLabel(tlbl->key);
8978       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8979       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8980       emitSKPC;
8981       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8982
8983       goto release ;
8984     }
8985
8986     reAdjustPreg(AOP(result));
8987     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8988     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8989     CLRC;
8990     while (size--) {
8991         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8992         MOVA(l);
8993         pic16_emitcode("rrc","a");         
8994         pic16_aopPut(AOP(result),"a",offset--);
8995     }
8996     reAdjustPreg(AOP(result));
8997
8998     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8999     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9000
9001 release:
9002     pic16_freeAsmop(left,NULL,ic,TRUE);
9003     pic16_freeAsmop (right,NULL,ic,TRUE);
9004     pic16_freeAsmop(result,NULL,ic,TRUE);
9005 }
9006
9007 /*-----------------------------------------------------------------*/
9008 /* genUnpackBits - generates code for unpacking bits               */
9009 /*-----------------------------------------------------------------*/
9010 static void genUnpackBits (operand *result, char *rname, int ptype)
9011 {    
9012     int shCnt ;
9013     int rlen = 0 ;
9014     sym_link *etype;
9015     int offset = 0 ;
9016
9017         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9018         etype = getSpec(operandType(result));
9019
9020         /* read the first byte  */
9021         switch (ptype) {
9022                 case POINTER:
9023                 case IPOINTER:
9024                 case PPOINTER:
9025                 case FPOINTER:
9026                 case GPOINTER:
9027                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9028                         break;
9029                 case CPOINTER:
9030                         pic16_emitcode("clr","a");
9031                         pic16_emitcode("movc","a","@a+dptr");
9032                         break;
9033         }
9034         
9035
9036         /* if we have bitdisplacement then it fits   */
9037         /* into this byte completely or if length is */
9038         /* less than a byte                          */
9039         if ((shCnt = SPEC_BSTR(etype)) || 
9040                 (SPEC_BLEN(etype) <= 8))  {
9041
9042                 /* shift right acc */
9043                 AccRsh(shCnt, 0);
9044
9045                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9046                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
9047
9048 /* VR -- normally I would use the following, but since we use the hack,
9049  * to avoid the masking from AccRsh, why not mask it right now? */
9050
9051 /*
9052                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
9053 */
9054
9055                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9056           return ;
9057         }
9058
9059
9060
9061         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9062         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9063         exit(-1);
9064
9065     /* bit field did not fit in a byte  */
9066     rlen = SPEC_BLEN(etype) - 8;
9067     pic16_aopPut(AOP(result),"a",offset++);
9068
9069     while (1)  {
9070
9071         switch (ptype) {
9072         case POINTER:
9073         case IPOINTER:
9074             pic16_emitcode("inc","%s",rname);
9075             pic16_emitcode("mov","a,@%s",rname);
9076             break;
9077             
9078         case PPOINTER:
9079             pic16_emitcode("inc","%s",rname);
9080             pic16_emitcode("movx","a,@%s",rname);
9081             break;
9082
9083         case FPOINTER:
9084             pic16_emitcode("inc","dptr");
9085             pic16_emitcode("movx","a,@dptr");
9086             break;
9087             
9088         case CPOINTER:
9089             pic16_emitcode("clr","a");
9090             pic16_emitcode("inc","dptr");
9091             pic16_emitcode("movc","a","@a+dptr");
9092             break;
9093             
9094         case GPOINTER:
9095             pic16_emitcode("inc","dptr");
9096             pic16_emitcode("lcall","__gptrget");
9097             break;
9098         }
9099
9100         rlen -= 8;            
9101         /* if we are done */
9102         if ( rlen <= 0 )
9103             break ;
9104         
9105         pic16_aopPut(AOP(result),"a",offset++);
9106                               
9107     }
9108     
9109     if (rlen) {
9110         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
9111         pic16_aopPut(AOP(result),"a",offset);          
9112     }
9113     
9114     return ;
9115 }
9116
9117
9118 static void genDataPointerGet(operand *left,
9119                               operand *result,
9120                               iCode *ic)
9121 {
9122   int size, offset = 0, leoffset=0 ;
9123
9124         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9125         pic16_aopOp(result, ic, FALSE);
9126
9127         size = AOP_SIZE(result);
9128 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9129
9130
9131 #if 0
9132         /* The following tests may save a redudant movff instruction when
9133          * accessing unions */
9134          
9135         /* if they are the same */
9136         if (operandsEqu (left, result)) {
9137                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
9138                 goto release;
9139         }
9140 #endif
9141
9142 #if 0
9143         /* if they are the same registers */
9144         if (pic16_sameRegs(AOP(left),AOP(result))) {
9145                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
9146                 goto release;
9147         }
9148 #endif
9149
9150 #if 1
9151         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
9152                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
9153                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
9154                 goto release;
9155         }
9156 #endif
9157
9158
9159 #if 0
9160         if ( AOP_TYPE(left) == AOP_PCODE) {
9161                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
9162                                 AOP(left)->aopu.pcop->name,
9163                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
9164                                 PCOR(AOP(left)->aopu.pcop)->instance:
9165                                 PCOI(AOP(left)->aopu.pcop)->offset);
9166         }
9167 #endif
9168
9169         if(AOP(left)->aopu.pcop->type == PO_DIR)
9170                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
9171
9172         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9173
9174         while (size--) {
9175                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
9176                 
9177                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
9178                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
9179                         mov2w(AOP(left), offset); // patch 8
9180                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9181                 } else {
9182                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
9183                                 pic16_popGet(AOP(left), offset), //patch 8
9184                                 pic16_popGet(AOP(result), offset)));
9185                 }
9186
9187                 offset++;
9188                 leoffset++;
9189         }
9190
9191 release:
9192     pic16_freeAsmop(result,NULL,ic,TRUE);
9193 }
9194
9195 void pic16_loadFSR0(operand *op)
9196 {
9197         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
9198 }
9199
9200
9201 /*-----------------------------------------------------------------*/
9202 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
9203 /*-----------------------------------------------------------------*/
9204 static void genNearPointerGet (operand *left, 
9205                                operand *result, 
9206                                iCode *ic)
9207 {
9208     asmop *aop = NULL;
9209     //regs *preg = NULL ;
9210     sym_link *rtype, *retype;
9211     sym_link *ltype = operandType(left);    
9212
9213         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9214         rtype = operandType(result);
9215         retype= getSpec(rtype);
9216     
9217         pic16_aopOp(left,ic,FALSE);
9218
9219 //      pic16_DumpOp("(left)",left);
9220 //      pic16_DumpOp("(result)",result);
9221
9222         /* if left is rematerialisable and
9223          * result is not bit variable type and
9224          * the left is pointer to data space i.e
9225          * lower 128 bytes of space */
9226         if (AOP_TYPE(left) == AOP_PCODE
9227                 && !IS_BITFIELD(retype)
9228                 && DCL_TYPE(ltype) == POINTER) {
9229
9230                 genDataPointerGet (left,result,ic);
9231                 pic16_freeAsmop(left, NULL, ic, TRUE);
9232           return ;
9233         }
9234     
9235         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9236
9237         /* if the value is already in a pointer register
9238          * then don't need anything more */
9239         if (!AOP_INPREG(AOP(left))) {
9240                 /* otherwise get a free pointer register */
9241                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9242                 
9243                 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
9244                 if( (AOP_TYPE(left) == AOP_PCODE) 
9245                         && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9246                                 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
9247                 {
9248                         pic16_loadFSR0( left );  // patch 10
9249                 } else {
9250                         // set up FSR0 with address from left
9251                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9252                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9253                 }
9254         }
9255 //       else
9256 //      rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9257     
9258         pic16_aopOp (result,ic,FALSE);
9259     
9260       /* if bitfield then unpack the bits */
9261     if (IS_BITFIELD(retype)) 
9262         genUnpackBits (result, NULL, POINTER);
9263     else {
9264         /* we have can just get the values */
9265       int size = AOP_SIZE(result);
9266       int offset = 0;   
9267         
9268       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9269
9270
9271         /* fsr0 is loaded already -- VR */
9272 //      pic16_loadFSR0( left );
9273
9274 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
9275 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9276       while(size--) {
9277
9278         if(size) {
9279                 pic16_emitpcode(POC_MOVFF,
9280                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
9281                                 pic16_popGet(AOP(result), offset++)));
9282         } else {
9283                 pic16_emitpcode(POC_MOVFF,
9284                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
9285                                 pic16_popGet(AOP(result), offset++)));
9286         }
9287       }
9288 #if 0
9289 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
9290 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
9291         if(size)
9292           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9293 #endif
9294 /*
9295         while (size--) {
9296             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
9297
9298                 pic16_emitcode("mov","a,@%s",rname);
9299                 pic16_aopPut(AOP(result),"a",offset);
9300             } else {
9301                 sprintf(buffer,"@%s",rname);
9302                 pic16_aopPut(AOP(result),buffer,offset);
9303             }
9304             offset++ ;
9305             if (size)
9306                 pic16_emitcode("inc","%s",rname);
9307         }
9308 */
9309     }
9310
9311     /* now some housekeeping stuff */
9312     if (aop) {
9313         /* we had to allocate for this iCode */
9314     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9315         pic16_freeAsmop(NULL,aop,ic,TRUE);
9316     } else { 
9317         /* we did not allocate which means left
9318            already in a pointer register, then
9319            if size > 0 && this could be used again
9320            we have to point it back to where it 
9321            belongs */
9322     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9323         if (AOP_SIZE(result) > 1 &&
9324             !OP_SYMBOL(left)->remat &&
9325             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9326               ic->depth )) {
9327 //          int size = AOP_SIZE(result) - 1;
9328 //          while (size--)
9329 //              pic16_emitcode("dec","%s",rname);
9330         }
9331     }
9332
9333     /* done */
9334     pic16_freeAsmop(left,NULL,ic,TRUE);
9335     pic16_freeAsmop(result,NULL,ic,TRUE);
9336      
9337 }
9338
9339 /*-----------------------------------------------------------------*/
9340 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
9341 /*-----------------------------------------------------------------*/
9342 static void genPagedPointerGet (operand *left, 
9343                                operand *result, 
9344                                iCode *ic)
9345 {
9346     asmop *aop = NULL;
9347     regs *preg = NULL ;
9348     char *rname ;
9349     sym_link *rtype, *retype;    
9350
9351     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9352
9353     rtype = operandType(result);
9354     retype= getSpec(rtype);
9355     
9356     pic16_aopOp(left,ic,FALSE);
9357
9358   /* if the value is already in a pointer register
9359        then don't need anything more */
9360     if (!AOP_INPREG(AOP(left))) {
9361         /* otherwise get a free pointer register */
9362         aop = newAsmop(0);
9363         preg = getFreePtr(ic,&aop,FALSE);
9364         pic16_emitcode("mov","%s,%s",
9365                 preg->name,
9366                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
9367         rname = preg->name ;
9368     } else
9369         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9370     
9371     pic16_freeAsmop(left,NULL,ic,TRUE);
9372     pic16_aopOp (result,ic,FALSE);
9373
9374     /* if bitfield then unpack the bits */
9375     if (IS_BITFIELD(retype)) 
9376         genUnpackBits (result,rname,PPOINTER);
9377     else {
9378         /* we have can just get the values */
9379         int size = AOP_SIZE(result);
9380         int offset = 0 ;        
9381         
9382         while (size--) {
9383             
9384             pic16_emitcode("movx","a,@%s",rname);
9385             pic16_aopPut(AOP(result),"a",offset);
9386             
9387             offset++ ;
9388             
9389             if (size)
9390                 pic16_emitcode("inc","%s",rname);
9391         }
9392     }
9393
9394     /* now some housekeeping stuff */
9395     if (aop) {
9396         /* we had to allocate for this iCode */
9397         pic16_freeAsmop(NULL,aop,ic,TRUE);
9398     } else { 
9399         /* we did not allocate which means left
9400            already in a pointer register, then
9401            if size > 0 && this could be used again
9402            we have to point it back to where it 
9403            belongs */
9404         if (AOP_SIZE(result) > 1 &&
9405             !OP_SYMBOL(left)->remat &&
9406             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9407               ic->depth )) {
9408             int size = AOP_SIZE(result) - 1;
9409             while (size--)
9410                 pic16_emitcode("dec","%s",rname);
9411         }
9412     }
9413
9414     /* done */
9415     pic16_freeAsmop(result,NULL,ic,TRUE);
9416     
9417         
9418 }
9419
9420 /*-----------------------------------------------------------------*/
9421 /* genFarPointerGet - gget value from far space                    */
9422 /*-----------------------------------------------------------------*/
9423 static void genFarPointerGet (operand *left,
9424                               operand *result, iCode *ic)
9425 {
9426     int size, offset ;
9427     sym_link *retype = getSpec(operandType(result));
9428
9429     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9430
9431     pic16_aopOp(left,ic,FALSE);
9432
9433     /* if the operand is already in dptr 
9434     then we do nothing else we move the value to dptr */
9435     if (AOP_TYPE(left) != AOP_STR) {
9436         /* if this is remateriazable */
9437         if (AOP_TYPE(left) == AOP_IMMD)
9438             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9439         else { /* we need to get it byte by byte */
9440             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9441             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9442             if (options.model == MODEL_FLAT24)
9443             {
9444                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9445             }
9446         }
9447     }
9448     /* so dptr know contains the address */
9449     pic16_freeAsmop(left,NULL,ic,TRUE);
9450     pic16_aopOp(result,ic,FALSE);
9451
9452     /* if bit then unpack */
9453     if (IS_BITFIELD(retype)) 
9454         genUnpackBits(result,"dptr",FPOINTER);
9455     else {
9456         size = AOP_SIZE(result);
9457         offset = 0 ;
9458
9459         while (size--) {
9460             pic16_emitcode("movx","a,@dptr");
9461             pic16_aopPut(AOP(result),"a",offset++);
9462             if (size)
9463                 pic16_emitcode("inc","dptr");
9464         }
9465     }
9466
9467     pic16_freeAsmop(result,NULL,ic,TRUE);
9468 }
9469 #if 0
9470 /*-----------------------------------------------------------------*/
9471 /* genCodePointerGet - get value from code space                  */
9472 /*-----------------------------------------------------------------*/
9473 static void genCodePointerGet (operand *left,
9474                                 operand *result, iCode *ic)
9475 {
9476     int size, offset ;
9477     sym_link *retype = getSpec(operandType(result));
9478
9479     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9480
9481     pic16_aopOp(left,ic,FALSE);
9482
9483     /* if the operand is already in dptr 
9484     then we do nothing else we move the value to dptr */
9485     if (AOP_TYPE(left) != AOP_STR) {
9486         /* if this is remateriazable */
9487         if (AOP_TYPE(left) == AOP_IMMD)
9488             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9489         else { /* we need to get it byte by byte */
9490             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9491             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9492             if (options.model == MODEL_FLAT24)
9493             {
9494                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9495             }
9496         }
9497     }
9498     /* so dptr know contains the address */
9499     pic16_freeAsmop(left,NULL,ic,TRUE);
9500     pic16_aopOp(result,ic,FALSE);
9501
9502     /* if bit then unpack */
9503     if (IS_BITFIELD(retype)) 
9504         genUnpackBits(result,"dptr",CPOINTER);
9505     else {
9506         size = AOP_SIZE(result);
9507         offset = 0 ;
9508
9509         while (size--) {
9510             pic16_emitcode("clr","a");
9511             pic16_emitcode("movc","a,@a+dptr");
9512             pic16_aopPut(AOP(result),"a",offset++);
9513             if (size)
9514                 pic16_emitcode("inc","dptr");
9515         }
9516     }
9517
9518     pic16_freeAsmop(result,NULL,ic,TRUE);
9519 }
9520 #endif
9521 /*-----------------------------------------------------------------*/
9522 /* genGenPointerGet - gget value from generic pointer space        */
9523 /*-----------------------------------------------------------------*/
9524 static void genGenPointerGet (operand *left,
9525                               operand *result, iCode *ic)
9526 {
9527   int size, offset, lit;
9528   sym_link *retype = getSpec(operandType(result));
9529
9530         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9531         pic16_aopOp(left,ic,FALSE);
9532         pic16_aopOp(result,ic,FALSE);
9533         size = AOP_SIZE(result);
9534
9535         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9536
9537         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9538
9539                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9540                 // load FSR0 from immediate
9541                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9542
9543 //              pic16_loadFSR0( left );
9544
9545                 offset = 0;
9546                 while(size--) {
9547                         if(size) {
9548                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9549                         } else {
9550                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9551                         }
9552                         offset++;
9553                 }
9554                 goto release;
9555
9556         }
9557         else { /* we need to get it byte by byte */
9558                 // set up FSR0 with address from left
9559                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9560                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9561
9562                 offset = 0 ;
9563
9564                 while(size--) {
9565                         if(size) {
9566                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9567                         } else {
9568                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9569                         }
9570                         offset++;
9571                 }
9572                 goto release;
9573         }
9574
9575   /* if bit then unpack */
9576         if (IS_BITFIELD(retype)) 
9577                 genUnpackBits(result,"BAD",GPOINTER);
9578
9579         release:
9580         pic16_freeAsmop(left,NULL,ic,TRUE);
9581         pic16_freeAsmop(result,NULL,ic,TRUE);
9582
9583 }
9584
9585 /*-----------------------------------------------------------------*/
9586 /* genConstPointerGet - get value from const generic pointer space */
9587 /*-----------------------------------------------------------------*/
9588 static void genConstPointerGet (operand *left,
9589                                 operand *result, iCode *ic)
9590 {
9591   //sym_link *retype = getSpec(operandType(result));
9592   // symbol *albl = newiTempLabel(NULL);        // patch 15
9593   // symbol *blbl = newiTempLabel(NULL);        //
9594   // PIC_OPCODE poc;                            // patch 15
9595   int size;
9596   int offset = 0;
9597
9598   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9599   pic16_aopOp(left,ic,FALSE);
9600   pic16_aopOp(result,ic,TRUE);
9601   size = AOP_SIZE(result);
9602
9603   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9604
9605   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9606 #if 0                                                                   // patch 15
9607   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9608   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9609   pic16_emitpLabel(albl->key);
9610
9611   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9612     
9613   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9614   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9615   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9616   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9617   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9618
9619   pic16_emitpLabel(blbl->key);
9620
9621   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9622 #endif                                                                  // patch 15
9623
9624
9625   // set up table pointer
9626   if( (AOP_TYPE(left) == AOP_PCODE) 
9627       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9628           || (AOP(left)->aopu.pcop->type == PO_DIR)))                   // patch 15 ......
9629     {
9630       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9631       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9632       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9633       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9634       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9635       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9636     }
9637   else
9638     {
9639       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9640       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9641       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9642     }
9643
9644
9645   while(size--)
9646     {
9647       pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9648       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9649       offset++;
9650     }
9651     
9652   pic16_freeAsmop(left,NULL,ic,TRUE);
9653   pic16_freeAsmop(result,NULL,ic,TRUE);
9654
9655 }
9656
9657
9658 /*-----------------------------------------------------------------*/
9659 /* genPointerGet - generate code for pointer get                   */
9660 /*-----------------------------------------------------------------*/
9661 static void genPointerGet (iCode *ic)
9662 {
9663     operand *left, *result ;
9664     sym_link *type, *etype;
9665     int p_type;
9666
9667     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9668
9669     left = IC_LEFT(ic);
9670     result = IC_RESULT(ic) ;
9671
9672     /* depending on the type of pointer we need to
9673     move it to the correct pointer register */
9674     type = operandType(left);
9675     etype = getSpec(type);
9676
9677 #if 0
9678     if (IS_PTR_CONST(type))
9679 #else
9680     if (IS_CODEPTR(type))
9681 #endif
9682       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9683
9684     /* if left is of type of pointer then it is simple */
9685     if (IS_PTR(type) && !IS_FUNC(type->next)) 
9686         p_type = DCL_TYPE(type);
9687     else {
9688         /* we have to go by the storage class */
9689         p_type = PTR_TYPE(SPEC_OCLS(etype));
9690
9691         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9692
9693         if (SPEC_OCLS(etype)->codesp ) {
9694           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9695           //p_type = CPOINTER ; 
9696         }
9697         else
9698             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9699               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9700                /*p_type = FPOINTER ;*/ 
9701             else
9702                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9703                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9704 /*                  p_type = PPOINTER; */
9705                 else
9706                     if (SPEC_OCLS(etype) == idata )
9707                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9708 /*                      p_type = IPOINTER; */
9709                     else
9710                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9711 /*                      p_type = POINTER ; */
9712     }
9713
9714     /* now that we have the pointer type we assign
9715     the pointer values */
9716     switch (p_type) {
9717
9718     case POINTER:       
9719     case IPOINTER:
9720         genNearPointerGet (left,result,ic);
9721         break;
9722
9723     case PPOINTER:
9724         genPagedPointerGet(left,result,ic);
9725         break;
9726
9727     case FPOINTER:
9728         genFarPointerGet (left,result,ic);
9729         break;
9730
9731     case CPOINTER:
9732         genConstPointerGet (left,result,ic);
9733         //pic16_emitcodePointerGet (left,result,ic);
9734         break;
9735
9736     case GPOINTER:
9737 #if 0
9738       if (IS_PTR_CONST(type))
9739         genConstPointerGet (left,result,ic);
9740       else
9741 #endif
9742         genGenPointerGet (left,result,ic);
9743       break;
9744
9745     default:
9746       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9747               "genPointerGet: illegal pointer type");
9748     
9749     }
9750
9751 }
9752
9753 /*-----------------------------------------------------------------*/
9754 /* genPackBits - generates code for packed bit storage             */
9755 /*-----------------------------------------------------------------*/
9756 static void genPackBits (sym_link    *etype ,
9757                          operand *right ,
9758                          char *rname, int p_type)
9759 {
9760   int shCnt = 0 ;
9761   int offset = 0  ;
9762   int rLen = 0 ;
9763   int blen, bstr ;   
9764   char *l ;
9765
9766         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9767         blen = SPEC_BLEN(etype);
9768         bstr = SPEC_BSTR(etype);
9769
9770         if(AOP_TYPE(right) == AOP_LIT) {
9771                 if((blen == 1) && (bstr < 8)) {
9772                   unsigned long lit;
9773                         /* it is a single bit, so use the appropriate bit instructions */
9774
9775                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
9776
9777                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9778 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9779                         if(lit) {
9780                                 pic16_emitpcode(POC_BSF,
9781                                         pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9782                         } else {
9783                                 pic16_emitpcode(POC_BCF,
9784                                         pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9785                         }
9786         
9787                   return;
9788                 }
9789
9790                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
9791                 offset++;
9792         } else
9793                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
9794
9795         /* if the bit lenth is less than or    */
9796         /* it exactly fits a byte then         */
9797         if((shCnt=SPEC_BSTR(etype))
9798                 || SPEC_BLEN(etype) <= 8 )  {
9799
9800                 /* shift left acc */
9801                 AccLsh(shCnt);
9802
9803                 /* using PRODL as a temporary register here */
9804                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
9805
9806                 switch (p_type) {
9807                         case FPOINTER:
9808                         case POINTER:
9809                         case GPOINTER:
9810                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9811 //                              pic16_emitcode ("mov","b,a");
9812 //                              pic16_emitcode("mov","a,@%s",rname);
9813                                 break;
9814                 }
9815 #if 1
9816                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9817                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
9818                                         (unsigned char)(0xff >> (8-bstr))) ));
9819                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
9820                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9821 #endif
9822
9823           return;
9824         }
9825
9826
9827         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9828         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9829         exit(-1);
9830
9831
9832     /* if we r done */
9833     if ( SPEC_BLEN(etype) <= 8 )
9834         return ;
9835
9836     pic16_emitcode("inc","%s",rname);
9837     rLen = SPEC_BLEN(etype) ;     
9838
9839
9840
9841     /* now generate for lengths greater than one byte */
9842     while (1) {
9843
9844         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
9845
9846         rLen -= 8 ;
9847         if (rLen <= 0 )
9848             break ;
9849
9850         switch (p_type) {
9851             case POINTER:
9852                 if (*l == '@') {
9853                     MOVA(l);
9854                     pic16_emitcode("mov","@%s,a",rname);
9855                 } else
9856                     pic16_emitcode("mov","@%s,%s",rname,l);
9857                 break;
9858
9859             case FPOINTER:
9860                 MOVA(l);
9861                 pic16_emitcode("movx","@dptr,a");
9862                 break;
9863
9864             case GPOINTER:
9865                 MOVA(l);
9866                 DEBUGpic16_emitcode(";lcall","__gptrput");
9867                 break;  
9868         }   
9869         pic16_emitcode ("inc","%s",rname);
9870     }
9871
9872     MOVA(l);
9873
9874     /* last last was not complete */
9875     if (rLen)   {
9876         /* save the byte & read byte */
9877         switch (p_type) {
9878             case POINTER:
9879                 pic16_emitcode ("mov","b,a");
9880                 pic16_emitcode("mov","a,@%s",rname);
9881                 break;
9882
9883             case FPOINTER:
9884                 pic16_emitcode ("mov","b,a");
9885                 pic16_emitcode("movx","a,@dptr");
9886                 break;
9887
9888             case GPOINTER:
9889                 pic16_emitcode ("push","b");
9890                 pic16_emitcode ("push","acc");
9891                 pic16_emitcode ("lcall","__gptrget");
9892                 pic16_emitcode ("pop","b");
9893                 break;
9894         }
9895
9896         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
9897         pic16_emitcode ("orl","a,b");
9898     }
9899
9900     if (p_type == GPOINTER)
9901         pic16_emitcode("pop","b");
9902
9903     switch (p_type) {
9904
9905     case POINTER:
9906         pic16_emitcode("mov","@%s,a",rname);
9907         break;
9908         
9909     case FPOINTER:
9910         pic16_emitcode("movx","@dptr,a");
9911         break;
9912         
9913     case GPOINTER:
9914         DEBUGpic16_emitcode(";lcall","__gptrput");
9915         break;                  
9916     }
9917 }
9918 /*-----------------------------------------------------------------*/
9919 /* genDataPointerSet - remat pointer to data space                 */
9920 /*-----------------------------------------------------------------*/
9921 static void genDataPointerSet(operand *right,
9922                               operand *result,
9923                               iCode *ic)
9924 {
9925     int size, offset = 0, resoffset=0 ;
9926
9927     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9928     pic16_aopOp(right,ic,FALSE);
9929
9930     size = AOP_SIZE(right);
9931
9932 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9933
9934 #if 0
9935     if ( AOP_TYPE(result) == AOP_PCODE) {
9936       fprintf(stderr,"genDataPointerSet   %s, %d\n",
9937               AOP(result)->aopu.pcop->name,
9938                 (AOP(result)->aopu.pcop->type == PO_DIR)?
9939               PCOR(AOP(result)->aopu.pcop)->instance:
9940               PCOI(AOP(result)->aopu.pcop)->offset);
9941     }
9942 #endif
9943
9944         if(AOP(result)->aopu.pcop->type == PO_DIR)
9945                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
9946
9947         while (size--) {
9948                 if (AOP_TYPE(right) == AOP_LIT) {
9949                   unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9950
9951                         lit = lit >> (8*offset);
9952                         if(lit&0xff) {
9953                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
9954                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
9955                         } else {
9956                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
9957                         }
9958                 } else {
9959                         mov2w(AOP(right), offset);
9960                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
9961                 }
9962                 offset++;
9963                 resoffset++;
9964         }
9965
9966     pic16_freeAsmop(right,NULL,ic,TRUE);
9967 }
9968
9969
9970
9971 /*-----------------------------------------------------------------*/
9972 /* genNearPointerSet - pic16_emitcode for near pointer put         */
9973 /*-----------------------------------------------------------------*/
9974 static void genNearPointerSet (operand *right,
9975                                operand *result, 
9976                                iCode *ic)
9977 {
9978   asmop *aop = NULL;
9979   char *l;
9980   sym_link *retype;
9981   sym_link *ptype = operandType(result);
9982   sym_link *resetype;
9983     
9984         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9985         retype= getSpec(operandType(right));
9986         resetype = getSpec(operandType(result));
9987   
9988         pic16_aopOp(result,ic,FALSE);
9989     
9990         /* if the result is rematerializable &
9991          * in data space & not a bit variable */
9992         
9993         /* and result is not a bit variable */
9994         if (AOP_TYPE(result) == AOP_PCODE
9995 //              && AOP_TYPE(result) == AOP_IMMD
9996                 && DCL_TYPE(ptype) == POINTER
9997                 && !IS_BITFIELD(retype)
9998                 && !IS_BITFIELD(resetype)) {
9999
10000                 genDataPointerSet (right,result,ic);
10001                 pic16_freeAsmop(result,NULL,ic,TRUE);
10002           return;
10003         }
10004
10005         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10006         pic16_aopOp(right,ic,FALSE);
10007         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10008
10009         /* if the value is already in a pointer register
10010          * then don't need anything more */
10011         if (!AOP_INPREG(AOP(result))) {
10012                 /* otherwise get a free pointer register */
10013                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10014
10015                 if( (AOP_TYPE(result) == AOP_PCODE) 
10016                         && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
10017                                 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
10018                 {
10019                         pic16_loadFSR0( result );  // patch 10
10020                 } else {
10021                         // set up FSR0 with address of result
10022                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10023                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10024                 }
10025
10026         }
10027 //      else
10028 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10029
10030         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10031
10032         /* if bitfield then unpack the bits */
10033         if (IS_BITFIELD(resetype)) {
10034                 genPackBits (resetype, right, NULL, POINTER);
10035         } else {
10036                 /* we have can just get the values */
10037           int size = AOP_SIZE(right);
10038           int offset = 0 ;    
10039
10040                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10041                 while (size--) {
10042                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10043                         if (*l == '@' ) {
10044                                 //MOVA(l);
10045                                 //pic16_emitcode("mov","@%s,a",rname);
10046                                 pic16_emitcode("movf","indf0,w ;1");
10047                         } else {
10048
10049                                 if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
10050                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
10051                                         if (size) {                                                                     // 
10052                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
10053                                         } else {                                                                        // 
10054                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
10055                                         }                                                                               // 
10056                                 } else { // no literal                                                                  // 
10057                                         if(size) {                                                                      // 
10058                                                 pic16_emitpcode(POC_MOVFF,                                              // 
10059                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
10060                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));         // 
10061                                         } else {                                                                        // 
10062                                                 pic16_emitpcode(POC_MOVFF,                                              // 
10063                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
10064                                                                         pic16_popCopyReg(&pic16_pc_indf0)));            //
10065                                         }                                                                               //
10066                                 }                                                                                       // patch 10
10067                         }
10068                         offset++;
10069                 }
10070         }
10071
10072         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10073         /* now some housekeeping stuff */
10074         if (aop) {
10075                 /* we had to allocate for this iCode */
10076                 pic16_freeAsmop(NULL,aop,ic,TRUE);
10077         } else { 
10078                 /* we did not allocate which means left
10079                  * already in a pointer register, then
10080                  * if size > 0 && this could be used again
10081                  * we have to point it back to where it 
10082                  * belongs */
10083                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10084                 if (AOP_SIZE(right) > 1
10085                         && !OP_SYMBOL(result)->remat
10086                         && ( OP_SYMBOL(result)->liveTo > ic->seq
10087                                 || ic->depth )) {
10088
10089                   int size = AOP_SIZE(right) - 1;
10090
10091                         while (size--)
10092                                 pic16_emitcode("decf","fsr0,f");
10093                         //pic16_emitcode("dec","%s",rname);
10094                 }
10095         }
10096
10097         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10098         /* done */
10099 //release:
10100         pic16_freeAsmop(right,NULL,ic,TRUE);
10101         pic16_freeAsmop(result,NULL,ic,TRUE);
10102 }
10103
10104 /*-----------------------------------------------------------------*/
10105 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
10106 /*-----------------------------------------------------------------*/
10107 static void genPagedPointerSet (operand *right,
10108                                operand *result, 
10109                                iCode *ic)
10110 {
10111     asmop *aop = NULL;
10112     regs *preg = NULL ;
10113     char *rname , *l;
10114     sym_link *retype;
10115        
10116     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10117
10118     retype= getSpec(operandType(right));
10119     
10120     pic16_aopOp(result,ic,FALSE);
10121     
10122     /* if the value is already in a pointer register
10123        then don't need anything more */
10124     if (!AOP_INPREG(AOP(result))) {
10125         /* otherwise get a free pointer register */
10126         aop = newAsmop(0);
10127         preg = getFreePtr(ic,&aop,FALSE);
10128         pic16_emitcode("mov","%s,%s",
10129                 preg->name,
10130                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
10131         rname = preg->name ;
10132     } else
10133         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10134     
10135     pic16_freeAsmop(result,NULL,ic,TRUE);
10136     pic16_aopOp (right,ic,FALSE);
10137
10138     /* if bitfield then unpack the bits */
10139     if (IS_BITFIELD(retype)) 
10140         genPackBits (retype,right,rname,PPOINTER);
10141     else {
10142         /* we have can just get the values */
10143         int size = AOP_SIZE(right);
10144         int offset = 0 ;        
10145         
10146         while (size--) {
10147             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10148             
10149             MOVA(l);
10150             pic16_emitcode("movx","@%s,a",rname);
10151
10152             if (size)
10153                 pic16_emitcode("inc","%s",rname);
10154
10155             offset++;
10156         }
10157     }
10158     
10159     /* now some housekeeping stuff */
10160     if (aop) {
10161         /* we had to allocate for this iCode */
10162         pic16_freeAsmop(NULL,aop,ic,TRUE);
10163     } else { 
10164         /* we did not allocate which means left
10165            already in a pointer register, then
10166            if size > 0 && this could be used again
10167            we have to point it back to where it 
10168            belongs */
10169         if (AOP_SIZE(right) > 1 &&
10170             !OP_SYMBOL(result)->remat &&
10171             ( OP_SYMBOL(result)->liveTo > ic->seq ||
10172               ic->depth )) {
10173             int size = AOP_SIZE(right) - 1;
10174             while (size--)
10175                 pic16_emitcode("dec","%s",rname);
10176         }
10177     }
10178
10179     /* done */
10180     pic16_freeAsmop(right,NULL,ic,TRUE);
10181     
10182         
10183 }
10184
10185 /*-----------------------------------------------------------------*/
10186 /* genFarPointerSet - set value from far space                     */
10187 /*-----------------------------------------------------------------*/
10188 static void genFarPointerSet (operand *right,
10189                               operand *result, iCode *ic)
10190 {
10191     int size, offset ;
10192     sym_link *retype = getSpec(operandType(right));
10193
10194     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10195     pic16_aopOp(result,ic,FALSE);
10196
10197     /* if the operand is already in dptr 
10198     then we do nothing else we move the value to dptr */
10199     if (AOP_TYPE(result) != AOP_STR) {
10200         /* if this is remateriazable */
10201         if (AOP_TYPE(result) == AOP_IMMD)
10202             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
10203         else { /* we need to get it byte by byte */
10204             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
10205             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
10206             if (options.model == MODEL_FLAT24)
10207             {
10208                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
10209             }
10210         }
10211     }
10212     /* so dptr know contains the address */
10213     pic16_freeAsmop(result,NULL,ic,TRUE);
10214     pic16_aopOp(right,ic,FALSE);
10215
10216     /* if bit then unpack */
10217     if (IS_BITFIELD(retype)) 
10218         genPackBits(retype,right,"dptr",FPOINTER);
10219     else {
10220         size = AOP_SIZE(right);
10221         offset = 0 ;
10222
10223         while (size--) {
10224             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10225             MOVA(l);
10226             pic16_emitcode("movx","@dptr,a");
10227             if (size)
10228                 pic16_emitcode("inc","dptr");
10229         }
10230     }
10231
10232     pic16_freeAsmop(right,NULL,ic,TRUE);
10233 }
10234
10235 /*-----------------------------------------------------------------*/
10236 /* genGenPointerSet - set value from generic pointer space         */
10237 /*-----------------------------------------------------------------*/
10238 static void genGenPointerSet (operand *right,
10239                               operand *result, iCode *ic)
10240 {
10241         int i, size, offset, lit;
10242         sym_link *retype = getSpec(operandType(right));
10243
10244         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10245
10246         pic16_aopOp(result,ic,FALSE);
10247         pic16_aopOp(right,ic,FALSE);
10248         size = AOP_SIZE(right);
10249         offset = 0;
10250
10251         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10252
10253         /* if the operand is already in dptr 
10254                 then we do nothing else we move the value to dptr */
10255         if (AOP_TYPE(result) != AOP_STR) {
10256                 /* if this is remateriazable */
10257                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10258                 // WARNING: anythig until "else" is untested!
10259                 if (AOP_TYPE(result) == AOP_IMMD) {
10260                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10261                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
10262                         // load FSR0 from immediate
10263                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10264                         offset = 0;
10265                         while(size--) {
10266                                 if(size) {
10267                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10268                                 } else {
10269                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10270                                 }
10271                                 offset++;
10272                         }
10273                         goto release;
10274                 }
10275                 else { /* we need to get it byte by byte */
10276                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10277                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10278
10279                         // set up FSR0 with address of result
10280                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10281                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10282
10283                         /* hack hack! see if this the FSR. If so don't load W */
10284                         if(AOP_TYPE(right) != AOP_ACC) {
10285
10286                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10287
10288                                 if(AOP_TYPE(right) == AOP_LIT)
10289                                 {
10290                                         // copy literal
10291                                         // note: pic16_popGet handles sign extension
10292                                         for(i=0;i<size;i++) {
10293                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
10294                                                 if(i < size-1)
10295                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
10296                                                 else
10297                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10298                                         }
10299                                 } else {
10300                                         // copy regs
10301
10302                                         for(i=0;i<size;i++) {
10303                                                 if(i < size-1)
10304                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10305                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
10306                                                 else
10307                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10308                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
10309                                         }
10310                                 }
10311                                 goto release;
10312                         } 
10313                         // right = ACC
10314                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10315                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10316                         goto release;
10317         } // if (AOP_TYPE(result) != AOP_IMMD)
10318
10319         } // if (AOP_TYPE(result) != AOP_STR)
10320         /* so dptr know contains the address */
10321
10322
10323         /* if bit then unpack */
10324         if (IS_BITFIELD(retype)) 
10325                 genPackBits(retype,right,"dptr",GPOINTER);
10326         else {
10327                 size = AOP_SIZE(right);
10328                 offset = 0 ;
10329
10330                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
10331
10332                 // set up FSR0 with address of result
10333                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10334                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10335         
10336                 while (size--) {
10337                         if (AOP_TYPE(right) == AOP_LIT) {
10338                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10339                                 if (size) {
10340                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
10341                                 } else {
10342                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10343                                 }
10344                         } else { // no literal
10345                                 if(size) {
10346                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10347                                 } else {
10348                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10349                                 }
10350                         }
10351                         offset++;
10352                 }
10353         }
10354
10355         release:
10356         pic16_freeAsmop(right,NULL,ic,TRUE);
10357         pic16_freeAsmop(result,NULL,ic,TRUE);
10358 }
10359
10360 /*-----------------------------------------------------------------*/
10361 /* genPointerSet - stores the value into a pointer location        */
10362 /*-----------------------------------------------------------------*/
10363 static void genPointerSet (iCode *ic)
10364 {    
10365     operand *right, *result ;
10366     sym_link *type, *etype;
10367     int p_type;
10368
10369     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10370
10371     right = IC_RIGHT(ic);
10372     result = IC_RESULT(ic) ;
10373
10374     /* depending on the type of pointer we need to
10375     move it to the correct pointer register */
10376     type = operandType(result);
10377     etype = getSpec(type);
10378     /* if left is of type of pointer then it is simple */
10379     if (IS_PTR(type) && !IS_FUNC(type->next)) {
10380         p_type = DCL_TYPE(type);
10381     }
10382     else {
10383         /* we have to go by the storage class */
10384         p_type = PTR_TYPE(SPEC_OCLS(etype));
10385
10386 /*      if (SPEC_OCLS(etype)->codesp ) { */
10387 /*          p_type = CPOINTER ;  */
10388 /*      } */
10389 /*      else */
10390 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10391 /*              p_type = FPOINTER ; */
10392 /*          else */
10393 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10394 /*                  p_type = PPOINTER ; */
10395 /*              else */
10396 /*                  if (SPEC_OCLS(etype) == idata ) */
10397 /*                      p_type = IPOINTER ; */
10398 /*                  else */
10399 /*                      p_type = POINTER ; */
10400     }
10401
10402     /* now that we have the pointer type we assign
10403     the pointer values */
10404     switch (p_type) {
10405
10406     case POINTER:
10407     case IPOINTER:
10408         genNearPointerSet (right,result,ic);
10409         break;
10410
10411     case PPOINTER:
10412         genPagedPointerSet (right,result,ic);
10413         break;
10414
10415     case FPOINTER:
10416         genFarPointerSet (right,result,ic);
10417         break;
10418
10419     case GPOINTER:
10420         genGenPointerSet (right,result,ic);
10421         break;
10422
10423     default:
10424       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10425               "genPointerSet: illegal pointer type");
10426     }
10427 }
10428
10429 /*-----------------------------------------------------------------*/
10430 /* genIfx - generate code for Ifx statement                        */
10431 /*-----------------------------------------------------------------*/
10432 static void genIfx (iCode *ic, iCode *popIc)
10433 {
10434   operand *cond = IC_COND(ic);
10435   int isbit =0;
10436
10437   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10438
10439   pic16_aopOp(cond,ic,FALSE);
10440
10441   /* get the value into acc */
10442   if (AOP_TYPE(cond) != AOP_CRY)
10443     pic16_toBoolean(cond);
10444   else
10445     isbit = 1;
10446   /* the result is now in the accumulator */
10447   pic16_freeAsmop(cond,NULL,ic,TRUE);
10448
10449   /* if there was something to be popped then do it */
10450   if (popIc)
10451     genIpop(popIc);
10452
10453   /* if the condition is  a bit variable */
10454   if (isbit && IS_ITEMP(cond) && 
10455       SPIL_LOC(cond)) {
10456     genIfxJump(ic,SPIL_LOC(cond)->rname);
10457     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10458   }
10459   else {
10460     if (isbit && !IS_ITEMP(cond))
10461       genIfxJump(ic,OP_SYMBOL(cond)->rname);
10462     else
10463       genIfxJump(ic,"a");
10464   }
10465   ic->generated = 1;
10466
10467 }
10468
10469 /*-----------------------------------------------------------------*/
10470 /* genAddrOf - generates code for address of                       */
10471 /*-----------------------------------------------------------------*/
10472 static void genAddrOf (iCode *ic)
10473 {
10474   operand *result, *left;
10475   int size;
10476   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
10477   pCodeOp *pcop0, *pcop1, *pcop2;
10478
10479         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10480
10481         pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10482         pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10483
10484         sym = OP_SYMBOL( left );
10485
10486         size = AOP_SIZE(IC_RESULT(ic));
10487
10488 //      if(pic16_debug_verbose) {
10489 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10490 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10491 //      }
10492         
10493         /* Assume that what we want the address of is in data space
10494          * since there is no stack on the PIC, yet! -- VR */
10495         /* low */
10496         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10497
10498         /* high */
10499         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10500         
10501         /* upper */
10502         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10503         
10504
10505         if (size == 3) {
10506                 pic16_emitpcode(POC_MOVLW, pcop0);
10507                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10508                 pic16_emitpcode(POC_MOVLW, pcop1);
10509                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10510                 pic16_emitpcode(POC_MOVLW, pcop2);
10511                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10512         } else
10513         if (size == 2) {
10514                 pic16_emitpcode(POC_MOVLW, pcop0);
10515                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10516                 pic16_emitpcode(POC_MOVLW, pcop1);
10517                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10518         } else {
10519                 pic16_emitpcode(POC_MOVLW, pcop0);
10520                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10521         }
10522
10523         pic16_freeAsmop(result,NULL,ic,TRUE);
10524         pic16_freeAsmop(left, NULL, ic, FALSE);
10525 }
10526
10527
10528 #if 0
10529 /*-----------------------------------------------------------------*/
10530 /* genFarFarAssign - assignment when both are in far space         */
10531 /*-----------------------------------------------------------------*/
10532 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10533 {
10534     int size = AOP_SIZE(right);
10535     int offset = 0;
10536     char *l ;
10537     /* first push the right side on to the stack */
10538     while (size--) {
10539         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10540         MOVA(l);
10541         pic16_emitcode ("push","acc");
10542     }
10543     
10544     pic16_freeAsmop(right,NULL,ic,FALSE);
10545     /* now assign DPTR to result */
10546     pic16_aopOp(result,ic,FALSE);
10547     size = AOP_SIZE(result);
10548     while (size--) {
10549         pic16_emitcode ("pop","acc");
10550         pic16_aopPut(AOP(result),"a",--offset);
10551     }
10552     pic16_freeAsmop(result,NULL,ic,FALSE);
10553         
10554 }
10555 #endif
10556
10557 /*-----------------------------------------------------------------*/
10558 /* genAssign - generate code for assignment                        */
10559 /*-----------------------------------------------------------------*/
10560 static void genAssign (iCode *ic)
10561 {
10562   operand *result, *right;
10563   int size, offset,know_W;
10564   unsigned long lit = 0L;
10565
10566   result = IC_RESULT(ic);
10567   right  = IC_RIGHT(ic) ;
10568
10569   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10570   
10571   /* if they are the same */
10572   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10573     return ;
10574
10575   pic16_aopOp(right,ic,FALSE);
10576   pic16_aopOp(result,ic,TRUE);
10577
10578   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10579
10580   /* if they are the same registers */
10581   if (pic16_sameRegs(AOP(right),AOP(result)))
10582     goto release;
10583
10584   /* if the result is a bit */
10585   if (AOP_TYPE(result) == AOP_CRY) {
10586     /* if the right size is a literal then
10587        we know what the value is */
10588     if (AOP_TYPE(right) == AOP_LIT) {
10589           
10590       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10591                   pic16_popGet(AOP(result),0));
10592
10593       if (((int) operandLitValue(right))) 
10594         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10595                        AOP(result)->aopu.aop_dir,
10596                        AOP(result)->aopu.aop_dir);
10597       else
10598         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10599                        AOP(result)->aopu.aop_dir,
10600                        AOP(result)->aopu.aop_dir);
10601       goto release;
10602     }
10603
10604     /* the right is also a bit variable */
10605     if (AOP_TYPE(right) == AOP_CRY) {
10606       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10607       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10608       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10609
10610       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10611                      AOP(result)->aopu.aop_dir,
10612                      AOP(result)->aopu.aop_dir);
10613       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10614                      AOP(right)->aopu.aop_dir,
10615                      AOP(right)->aopu.aop_dir);
10616       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10617                      AOP(result)->aopu.aop_dir,
10618                      AOP(result)->aopu.aop_dir);
10619       goto release ;
10620     }
10621
10622     /* we need to or */
10623     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10624     pic16_toBoolean(right);
10625     emitSKPZ;
10626     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10627     //pic16_aopPut(AOP(result),"a",0);
10628     goto release ;
10629   }
10630
10631   /* bit variables done */
10632   /* general case */
10633   size = AOP_SIZE(result);
10634   offset = 0 ;
10635
10636   if(AOP_TYPE(right) == AOP_LIT) {
10637         if(!IS_FLOAT(operandType( right )))
10638                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10639         else {
10640            union {
10641               unsigned long lit_int;
10642               float lit_float;
10643             } info;
10644         
10645                 /* take care if literal is a float */
10646                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
10647                 lit = info.lit_int;
10648         }
10649   }
10650
10651 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
10652 //                      sizeof(unsigned long int), sizeof(float));
10653
10654   if(AOP_TYPE(right) != AOP_LIT
10655         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))) {
10656         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
10657
10658         // set up table pointer
10659         if( (AOP_TYPE(right) == AOP_PCODE)
10660                 && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE)
10661                 || (AOP(right)->aopu.pcop->type == PO_DIR)))
10662         {
10663                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
10664                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
10665                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
10666                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
10667                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
10668                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
10669         } else {
10670                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
10671                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
10672                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
10673                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
10674                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
10675                                 pic16_popCopyReg(&pic16_pc_tblptru)));
10676         }
10677
10678         size = min(AOP_SIZE(right), AOP_SIZE(result));
10679         while(size--) {
10680                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
10681                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
10682                         pic16_popGet(AOP(result),offset)));
10683                 offset++;
10684         }
10685
10686         if(AOP_SIZE(result) > AOP_SIZE(right)) {
10687                 size = AOP_SIZE(result) - AOP_SIZE(right);
10688                 while(size--) {
10689                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
10690                         offset++;
10691                 }
10692         }
10693         goto release;
10694   }
10695
10696
10697
10698 /* VR - What is this?! */
10699   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10700   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10701     if(aopIdx(AOP(result),0) == 4) {
10702   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10703         assert(0);
10704       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10705       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10706       goto release;
10707     } else
10708 //      assert(0);
10709       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10710   }
10711
10712   know_W=-1;
10713   while (size--) {
10714   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10715     if(AOP_TYPE(right) == AOP_LIT) {
10716       if(lit&0xff) {
10717         if(know_W != (lit&0xff))
10718           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10719         know_W = lit&0xff;
10720         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10721       } else
10722         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10723
10724       lit >>= 8;
10725
10726     } else if (AOP_TYPE(right) == AOP_CRY) {
10727       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10728       if(offset == 0) {
10729         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10730         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10731       }
10732     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10733         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10734         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10735     } else {
10736   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10737
10738 #if 1
10739         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10740            normally should work, but mind that the W register live range
10741            is not checked, so if the code generator assumes that the W
10742            is already loaded after such a pair, wrong code will be generated.
10743            
10744            Checking the live range is the next step.
10745            This is experimental code yet and has not been fully tested yet.
10746            USE WITH CARE. Revert to old code by setting 0 to the condition above.
10747            Vangelis Rokas 030603 (vrokas@otenet.gr) */
10748            
10749         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10750 #else   
10751         /* This is the old code, which is assumed(?!) that works fine(!?) */
10752
10753         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10754         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10755 #endif
10756     }
10757             
10758     offset++;
10759   }
10760
10761     
10762  release:
10763   pic16_freeAsmop (right,NULL,ic,FALSE);
10764   pic16_freeAsmop (result,NULL,ic,TRUE);
10765 }   
10766
10767 /*-----------------------------------------------------------------*/
10768 /* genJumpTab - generates code for jump table                       */
10769 /*-----------------------------------------------------------------*/
10770 static void genJumpTab (iCode *ic)
10771 {
10772     symbol *jtab;
10773     char *l;
10774
10775     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10776
10777     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
10778     /* get the condition into accumulator */
10779     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10780     MOVA(l);
10781     /* multiply by three */
10782     pic16_emitcode("add","a,acc");
10783     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10784
10785     jtab = newiTempLabel(NULL);
10786     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10787     pic16_emitcode("jmp","@a+dptr");
10788     pic16_emitcode("","%05d_DS_:",jtab->key+100);
10789
10790     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
10791     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
10792     emitSKPNC;
10793     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
10794     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
10795     pic16_emitpLabel(jtab->key);
10796
10797     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10798
10799     /* now generate the jump labels */
10800     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10801          jtab = setNextItem(IC_JTLABELS(ic))) {
10802         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
10803         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
10804         
10805     }
10806
10807 }
10808
10809 /*-----------------------------------------------------------------*/
10810 /* genMixedOperation - gen code for operators between mixed types  */
10811 /*-----------------------------------------------------------------*/
10812 /*
10813   TSD - Written for the PIC port - but this unfortunately is buggy.
10814   This routine is good in that it is able to efficiently promote 
10815   types to different (larger) sizes. Unfortunately, the temporary
10816   variables that are optimized out by this routine are sometimes
10817   used in other places. So until I know how to really parse the 
10818   iCode tree, I'm going to not be using this routine :(.
10819 */
10820 static int genMixedOperation (iCode *ic)
10821 {
10822 #if 0
10823   operand *result = IC_RESULT(ic);
10824   sym_link *ctype = operandType(IC_LEFT(ic));
10825   operand *right = IC_RIGHT(ic);
10826   int ret = 0;
10827   int big,small;
10828   int offset;
10829
10830   iCode *nextic;
10831   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10832
10833   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10834
10835   nextic = ic->next;
10836   if(!nextic)
10837     return 0;
10838
10839   nextright = IC_RIGHT(nextic);
10840   nextleft  = IC_LEFT(nextic);
10841   nextresult = IC_RESULT(nextic);
10842
10843   pic16_aopOp(right,ic,FALSE);
10844   pic16_aopOp(result,ic,FALSE);
10845   pic16_aopOp(nextright,  nextic, FALSE);
10846   pic16_aopOp(nextleft,   nextic, FALSE);
10847   pic16_aopOp(nextresult, nextic, FALSE);
10848
10849   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10850
10851     operand *t = right;
10852     right = nextright;
10853     nextright = t; 
10854
10855     pic16_emitcode(";remove right +","");
10856
10857   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10858 /*
10859     operand *t = right;
10860     right = nextleft;
10861     nextleft = t; 
10862 */
10863     pic16_emitcode(";remove left +","");
10864   } else
10865     return 0;
10866
10867   big = AOP_SIZE(nextleft);
10868   small = AOP_SIZE(nextright);
10869
10870   switch(nextic->op) {
10871
10872   case '+':
10873     pic16_emitcode(";optimize a +","");
10874     /* if unsigned or not an integral type */
10875     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10876       pic16_emitcode(";add a bit to something","");
10877     } else {
10878
10879       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10880
10881       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10882         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10883         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10884       } else
10885         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10886
10887       offset = 0;
10888       while(--big) {
10889
10890         offset++;
10891
10892         if(--small) {
10893           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10894             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10895             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10896           }
10897
10898           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10899           emitSKPNC;
10900           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10901                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10902                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10903           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10904           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10905
10906         } else {
10907           pic16_emitcode("rlf","known_zero,w");
10908
10909           /*
10910             if right is signed
10911               btfsc  right,7
10912                addlw ff
10913           */
10914           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10915             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10916             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10917           } else {
10918             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10919           }
10920         }
10921       }
10922       ret = 1;
10923     }
10924   }
10925   ret = 1;
10926
10927 release:
10928   pic16_freeAsmop(right,NULL,ic,TRUE);
10929   pic16_freeAsmop(result,NULL,ic,TRUE);
10930   pic16_freeAsmop(nextright,NULL,ic,TRUE);
10931   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
10932   if(ret)
10933     nextic->generated = 1;
10934
10935   return ret;
10936 #else
10937   return 0;
10938 #endif
10939 }
10940 /*-----------------------------------------------------------------*/
10941 /* genCast - gen code for casting                                  */
10942 /*-----------------------------------------------------------------*/
10943 static void genCast (iCode *ic)
10944 {
10945   operand *result = IC_RESULT(ic);
10946   sym_link *ctype = operandType(IC_LEFT(ic));
10947   sym_link *rtype = operandType(IC_RIGHT(ic));
10948   operand *right = IC_RIGHT(ic);
10949   int size, offset ;
10950
10951         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10952         /* if they are equivalent then do nothing */
10953         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10954                 return ;
10955
10956         pic16_aopOp(right,ic,FALSE) ;
10957         pic16_aopOp(result,ic,FALSE);
10958
10959         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10960
10961         /* if the result is a bit */
10962         if (AOP_TYPE(result) == AOP_CRY) {
10963         
10964                 /* if the right size is a literal then
10965                  * we know what the value is */
10966                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10967
10968                 if (AOP_TYPE(right) == AOP_LIT) {
10969                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10970                                 pic16_popGet(AOP(result),0));
10971
10972                         if (((int) operandLitValue(right))) 
10973                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
10974                                         AOP(result)->aopu.aop_dir,
10975                                         AOP(result)->aopu.aop_dir);
10976                         else
10977                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
10978                                         AOP(result)->aopu.aop_dir,
10979                                         AOP(result)->aopu.aop_dir);
10980                         goto release;
10981                 }
10982
10983                 /* the right is also a bit variable */
10984                 if (AOP_TYPE(right) == AOP_CRY) {
10985                         emitCLRC;
10986                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10987
10988                         pic16_emitcode("clrc","");
10989                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10990                                 AOP(right)->aopu.aop_dir,
10991                                 AOP(right)->aopu.aop_dir);
10992                         pic16_aopPut(AOP(result),"c",0);
10993                         goto release ;
10994                 }
10995
10996                 /* we need to or */
10997                 if (AOP_TYPE(right) == AOP_REG) {
10998                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10999                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
11000                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
11001                 }
11002                 pic16_toBoolean(right);
11003                 pic16_aopPut(AOP(result),"a",0);
11004                 goto release ;
11005         }
11006
11007         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
11008           int offset = 1;
11009
11010                 size = AOP_SIZE(result);
11011
11012                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11013
11014                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
11015                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
11016                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
11017
11018                 while (size--)
11019                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
11020
11021                 goto release;
11022         }
11023
11024         /* if they are the same size : or less */
11025         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
11026
11027                 /* if they are in the same place */
11028                 if (pic16_sameRegs(AOP(right),AOP(result)))
11029                         goto release;
11030
11031                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11032 #if 0
11033                 if (IS_PTR_CONST(rtype))
11034 #else
11035                 if (IS_CODEPTR(rtype))
11036 #endif
11037                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
11038
11039 #if 0
11040                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
11041 #else
11042                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
11043 #endif
11044                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
11045
11046 #if 0
11047                 if(AOP_TYPE(right) == AOP_IMMD) {
11048                   pCodeOp *pcop0, *pcop1, *pcop2;
11049                   symbol *sym = OP_SYMBOL( right );
11050
11051                         size = AOP_SIZE(result);
11052                         /* low */
11053                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11054                         /* high */
11055                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11056                         /* upper */
11057                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11058         
11059                         if (size == 3) {
11060                                 pic16_emitpcode(POC_MOVLW, pcop0);
11061                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11062                                 pic16_emitpcode(POC_MOVLW, pcop1);
11063                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
11064                                 pic16_emitpcode(POC_MOVLW, pcop2);
11065                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
11066                         } else
11067                         if (size == 2) {
11068                                 pic16_emitpcode(POC_MOVLW, pcop0);
11069                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11070                                 pic16_emitpcode(POC_MOVLW, pcop1);
11071                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11072                         } else {
11073                                 pic16_emitpcode(POC_MOVLW, pcop0);
11074                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11075                         }
11076                 } else
11077 #endif
11078                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11079                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
11080                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11081                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
11082                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11083                         if(AOP_SIZE(result) <2)
11084                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
11085                 } else {
11086                         /* if they in different places then copy */
11087                         size = AOP_SIZE(result);
11088                         offset = 0 ;
11089                         while (size--) {
11090                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11091                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11092                                 offset++;
11093                         }
11094                 }
11095                 goto release;
11096         }
11097
11098         /* if the result is of type pointer */
11099         if (IS_PTR(ctype)) {
11100           int p_type;
11101           sym_link *type = operandType(right);
11102           sym_link *etype = getSpec(type);
11103
11104                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
11105
11106                 /* pointer to generic pointer */
11107                 if (IS_GENPTR(ctype)) {
11108                   char *l = zero;
11109             
11110                         if (IS_PTR(type)) 
11111                                 p_type = DCL_TYPE(type);
11112                         else {
11113                 /* we have to go by the storage class */
11114                 p_type = PTR_TYPE(SPEC_OCLS(etype));
11115
11116 /*              if (SPEC_OCLS(etype)->codesp )  */
11117 /*                  p_type = CPOINTER ;  */
11118 /*              else */
11119 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11120 /*                      p_type = FPOINTER ; */
11121 /*                  else */
11122 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11123 /*                          p_type = PPOINTER; */
11124 /*                      else */
11125 /*                          if (SPEC_OCLS(etype) == idata ) */
11126 /*                              p_type = IPOINTER ; */
11127 /*                          else */
11128 /*                              p_type = POINTER ; */
11129             }
11130                 
11131             /* the first two bytes are known */
11132       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
11133             size = GPTRSIZE - 1; 
11134             offset = 0 ;
11135             while (size--) {
11136               if(offset < AOP_SIZE(right)) {
11137       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
11138                 if ((AOP_TYPE(right) == AOP_PCODE) && 
11139                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11140                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11141                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11142                 } else { 
11143                   pic16_aopPut(AOP(result),
11144                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11145                          offset);
11146                 }
11147               } else 
11148                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
11149               offset++;
11150             }
11151             /* the last byte depending on type */
11152             switch (p_type) {
11153             case IPOINTER:
11154             case POINTER:
11155                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
11156                 break;
11157             case FPOINTER:
11158               pic16_emitcode(";BUG!? ","%d",__LINE__);
11159                 l = one;
11160                 break;
11161             case CPOINTER:
11162               pic16_emitcode(";BUG!? ","%d",__LINE__);
11163                 l = "#0x02";
11164                 break;                          
11165             case PPOINTER:
11166               pic16_emitcode(";BUG!? ","%d",__LINE__);
11167                 l = "#0x03";
11168                 break;
11169                 
11170             default:
11171                 /* this should never happen */
11172                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11173                        "got unknown pointer type");
11174                 exit(1);
11175             }
11176             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
11177             goto release ;
11178         }
11179         
11180         /* just copy the pointers */
11181         size = AOP_SIZE(result);
11182         offset = 0 ;
11183         while (size--) {
11184             pic16_aopPut(AOP(result),
11185                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11186                    offset);
11187             offset++;
11188         }
11189         goto release ;
11190     }
11191     
11192
11193
11194     /* so we now know that the size of destination is greater
11195     than the size of the source.
11196     Now, if the next iCode is an operator then we might be
11197     able to optimize the operation without performing a cast.
11198     */
11199     if(genMixedOperation(ic))
11200       goto release;
11201
11202     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11203     
11204     /* we move to result for the size of source */
11205     size = AOP_SIZE(right);
11206     offset = 0 ;
11207     while (size--) {
11208       pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
11209       pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
11210       offset++;
11211     }
11212
11213     /* now depending on the sign of the destination */
11214     size = AOP_SIZE(result) - AOP_SIZE(right);
11215     /* if unsigned or not an integral type */
11216     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
11217       while (size--)
11218         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
11219     } else {
11220       /* we need to extend the sign :( */
11221
11222       if(size == 1) {
11223         /* Save one instruction of casting char to int */
11224         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
11225         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11226         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
11227       } else {
11228         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
11229
11230         if(offset)
11231           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11232         else
11233           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11234         
11235         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
11236
11237         while (size--)
11238           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
11239       }
11240     }
11241
11242 release:
11243     pic16_freeAsmop(right,NULL,ic,TRUE);
11244     pic16_freeAsmop(result,NULL,ic,TRUE);
11245
11246 }
11247
11248 /*-----------------------------------------------------------------*/
11249 /* genDjnz - generate decrement & jump if not zero instrucion      */
11250 /*-----------------------------------------------------------------*/
11251 static int genDjnz (iCode *ic, iCode *ifx)
11252 {
11253     symbol *lbl, *lbl1;
11254     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11255
11256     if (!ifx)
11257         return 0;
11258     
11259     /* if the if condition has a false label
11260        then we cannot save */
11261     if (IC_FALSE(ifx))
11262         return 0;
11263
11264     /* if the minus is not of the form 
11265        a = a - 1 */
11266     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
11267         !IS_OP_LITERAL(IC_RIGHT(ic)))
11268         return 0;
11269
11270     if (operandLitValue(IC_RIGHT(ic)) != 1)
11271         return 0;
11272
11273     /* if the size of this greater than one then no
11274        saving */
11275     if (getSize(operandType(IC_RESULT(ic))) > 1)
11276         return 0;
11277
11278     /* otherwise we can save BIG */
11279     lbl = newiTempLabel(NULL);
11280     lbl1= newiTempLabel(NULL);
11281
11282     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11283     
11284     if (IS_AOP_PREG(IC_RESULT(ic))) {
11285         pic16_emitcode("dec","%s",
11286                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11287         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11288         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
11289     } else {    
11290
11291
11292       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
11293       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
11294
11295       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11296       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
11297
11298     }
11299 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
11300 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
11301 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
11302 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
11303
11304     
11305     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11306     ifx->generated = 1;
11307     return 1;
11308 }
11309
11310 /*-----------------------------------------------------------------*/
11311 /* genReceive - generate code for a receive iCode                  */
11312 /*-----------------------------------------------------------------*/
11313 static void genReceive (iCode *ic)
11314 {    
11315         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11316
11317 #if 0
11318         fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
11319                 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
11320 #endif
11321 //      pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
11322
11323         if (isOperandInFarSpace(IC_RESULT(ic)) &&
11324                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
11325                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
11326
11327           int size = getSize(operandType(IC_RESULT(ic)));
11328           int offset =  pic16_fReturnSizePic - size;
11329
11330                 assert( 0 );
11331                 while (size--) {
11332                         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
11333                                         fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
11334                         offset++;
11335                 }
11336
11337                 DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
11338
11339                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11340                 size = AOP_SIZE(IC_RESULT(ic));
11341                 offset = 0;
11342                 while (size--) {
11343                         pic16_emitcode ("pop","acc");
11344                         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
11345                 }
11346         } else {
11347                 DEBUGpic16_emitcode ("; ***","2 %s  %d",__FUNCTION__,__LINE__);
11348
11349                 _G.accInUse++;
11350                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11351                 _G.accInUse--;
11352                 assignResultValue(IC_RESULT(ic), 0);
11353         }
11354
11355         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11356 }
11357
11358 /*-----------------------------------------------------------------*/
11359 /* genDummyRead - generate code for dummy read of volatiles        */
11360 /*-----------------------------------------------------------------*/
11361 static void
11362 genDummyRead (iCode * ic)
11363 {
11364   pic16_emitcode ("; genDummyRead","");
11365   pic16_emitcode ("; not implemented","");
11366
11367   ic = ic;
11368 }
11369
11370 /*-----------------------------------------------------------------*/
11371 /* genpic16Code - generate code for pic16 based controllers        */
11372 /*-----------------------------------------------------------------*/
11373 /*
11374  * At this point, ralloc.c has gone through the iCode and attempted
11375  * to optimize in a way suitable for a PIC. Now we've got to generate
11376  * PIC instructions that correspond to the iCode.
11377  *
11378  * Once the instructions are generated, we'll pass through both the
11379  * peep hole optimizer and the pCode optimizer.
11380  *-----------------------------------------------------------------*/
11381
11382 void genpic16Code (iCode *lic)
11383 {
11384     iCode *ic;
11385     int cln = 0;
11386
11387     lineHead = lineCurr = NULL;
11388
11389     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
11390     pic16_addpBlock(pb);
11391
11392 #if 0
11393     /* if debug information required */
11394     if (options.debug && currFunc) {
11395       if (currFunc) {
11396         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
11397       }
11398     }
11399 #endif
11400
11401     for (ic = lic ; ic ; ic = ic->next ) {
11402
11403       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
11404         if ( cln != ic->lineno ) {
11405             if ( options.debug ) {
11406               debugFile->writeCLine (ic);
11407             }
11408             
11409             if(!options.noCcodeInAsm) {
11410                 pic16_addpCode2pBlock(pb,
11411                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
11412                                 printCLine(ic->filename, ic->lineno)));
11413             }
11414
11415             cln = ic->lineno ;
11416         }
11417         
11418         if(options.iCodeInAsm) {
11419                 char *l;
11420                 /* insert here code to print iCode as comment */
11421                 l = Safe_strdup(printILine(ic));
11422                 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
11423         }
11424         
11425         /* if the result is marked as
11426            spilt and rematerializable or code for
11427            this has already been generated then
11428            do nothing */
11429         if (resultRemat(ic) || ic->generated ) 
11430             continue ;
11431         
11432         /* depending on the operation */
11433         switch (ic->op) {
11434         case '!' :
11435             pic16_genNot(ic);
11436             break;
11437             
11438         case '~' :
11439             pic16_genCpl(ic);
11440             break;
11441             
11442         case UNARYMINUS:
11443             genUminus (ic);
11444             break;
11445             
11446         case IPUSH:
11447             genIpush (ic);
11448             break;
11449             
11450         case IPOP:
11451             /* IPOP happens only when trying to restore a 
11452                spilt live range, if there is an ifx statement
11453                following this pop then the if statement might
11454                be using some of the registers being popped which
11455                would destroy the contents of the register so
11456                we need to check for this condition and handle it */
11457             if (ic->next            && 
11458                 ic->next->op == IFX &&
11459                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
11460                 genIfx (ic->next,ic);
11461             else
11462                 genIpop (ic);
11463             break; 
11464             
11465         case CALL:
11466             genCall (ic);
11467             break;
11468             
11469         case PCALL:
11470             genPcall (ic);
11471             break;
11472             
11473         case FUNCTION:
11474             genFunction (ic);
11475             break;
11476             
11477         case ENDFUNCTION:
11478             genEndFunction (ic);
11479             break;
11480             
11481         case RETURN:
11482             genRet (ic);
11483             break;
11484             
11485         case LABEL:
11486             genLabel (ic);
11487             break;
11488             
11489         case GOTO:
11490             genGoto (ic);
11491             break;
11492             
11493         case '+' :
11494             pic16_genPlus (ic) ;
11495             break;
11496             
11497         case '-' :
11498             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11499                 pic16_genMinus (ic);
11500             break;
11501             
11502         case '*' :
11503             genMult (ic);
11504             break;
11505             
11506         case '/' :
11507             genDiv (ic) ;
11508             break;
11509             
11510         case '%' :
11511             genMod (ic);
11512             break;
11513             
11514         case '>' :
11515             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
11516             break;
11517             
11518         case '<' :
11519             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11520             break;
11521             
11522         case LE_OP:
11523         case GE_OP:
11524         case NE_OP:
11525             
11526             /* note these two are xlated by algebraic equivalence
11527                during parsing SDCC.y */
11528             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11529                    "got '>=' or '<=' shouldn't have come here");
11530             break;      
11531             
11532         case EQ_OP:
11533             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11534             break;          
11535             
11536         case AND_OP:
11537             genAndOp (ic);
11538             break;
11539             
11540         case OR_OP:
11541             genOrOp (ic);
11542             break;
11543             
11544         case '^' :
11545             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11546             break;
11547             
11548         case '|' :
11549                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11550             break;
11551             
11552         case BITWISEAND:
11553             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11554             break;
11555             
11556         case INLINEASM:
11557             genInline (ic);
11558             break;
11559             
11560         case RRC:
11561             genRRC (ic);
11562             break;
11563             
11564         case RLC:
11565             genRLC (ic);
11566             break;
11567             
11568         case GETHBIT:
11569             genGetHbit (ic);
11570             break;
11571             
11572         case LEFT_OP:
11573             genLeftShift (ic);
11574             break;
11575             
11576         case RIGHT_OP:
11577             genRightShift (ic);
11578             break;
11579             
11580         case GET_VALUE_AT_ADDRESS:
11581             genPointerGet(ic);
11582             break;
11583             
11584         case '=' :
11585             if (POINTER_SET(ic))
11586                 genPointerSet(ic);
11587             else
11588                 genAssign(ic);
11589             break;
11590             
11591         case IFX:
11592             genIfx (ic,NULL);
11593             break;
11594             
11595         case ADDRESS_OF:
11596             genAddrOf (ic);
11597             break;
11598             
11599         case JUMPTABLE:
11600             genJumpTab (ic);
11601             break;
11602             
11603         case CAST:
11604             genCast (ic);
11605             break;
11606             
11607         case RECEIVE:
11608             genReceive(ic);
11609             break;
11610             
11611         case SEND:
11612             addSet(&_G.sendSet,ic);
11613             break;
11614
11615         case DUMMY_READ_VOLATILE:
11616           genDummyRead (ic);
11617           break;
11618
11619         default :
11620             ic = ic;
11621         }
11622     }
11623
11624
11625     /* now we are ready to call the
11626        peep hole optimizer */
11627     if (!options.nopeep) {
11628       peepHole (&lineHead);
11629     }
11630     /* now do the actual printing */
11631     printLine (lineHead,codeOutFile);
11632
11633 #ifdef PCODE_DEBUG
11634     DFPRINTF((stderr,"printing pBlock\n\n"));
11635     pic16_printpBlock(stdout,pb);
11636 #endif
11637
11638     return;
11639 }
11640