* src/pic16/device.c (pic16_dump_section): fixed a bug that allowed
[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   
10   This program is free software; you can redistribute it and/or modify it
11   under the terms of the GNU General Public License as published by the
12   Free Software Foundation; either version 2, or (at your option) any
13   later version.
14   
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License for more details.
19   
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23   
24   In other words, you are welcome to use, share and improve this program.
25   You are forbidden to forbid anyone else to use, share and improve
26   what you give them.   Help stamp out software-hoarding!
27   
28   Notes:
29   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
30                 Made everything static
31 -------------------------------------------------------------------------*/
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include "SDCCglobl.h"
38 #include "newalloc.h"
39
40 #include "common.h"
41 #include "SDCCpeeph.h"
42 #include "ralloc.h"
43 #include "pcode.h"
44 #include "gen.h"
45 #include "genutils.h"
46 #include "device.h"
47 #include "main.h"
48
49 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
50 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
51 void pic16_genMult8X8_8 (operand *, operand *,operand *);
52 pCode *pic16_AssembleLine(char *line, int peeps);
53 extern void pic16_printpBlock(FILE *of, pBlock *pb);
54 static asmop *newAsmop (short type);
55 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset);
56 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
57 static void mov2w (asmop *aop, int offset);
58 static int aopIdx (asmop *aop, int offset);
59
60 static int labelOffset=0;
61 extern int pic16_debug_verbose;
62 static int optimized_for_speed = 0;
63 /*
64   hack hack
65
66 */
67
68 /* max_key keeps track of the largest label number used in 
69    a function. This is then used to adjust the label offset
70    for the next function.
71 */
72 static int max_key=0;
73 static int GpsuedoStkPtr=0;
74
75 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
76 unsigned int pic16aopLiteral (value *val, int offset);
77 const char *pic16_AopType(short type);
78 static iCode *ifxForOp ( operand *op, iCode *ic );
79
80 void pic16_pushpCodeOp(pCodeOp *pcop);
81 void pic16_poppCodeOp(pCodeOp *pcop);
82
83
84
85 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
86
87 /* this is the down and dirty file with all kinds of 
88    kludgy & hacky stuff. This is what it is all about
89    CODE GENERATION for a specific MCU . some of the
90    routines may be reusable, will have to see */
91
92 static char *zero = "#0x00";
93 static char *one  = "#0x01";
94 static char *spname = "sp";
95
96
97 /*
98  * Function return value policy (MSB-->LSB):
99  *  8 bits      -> WREG
100  * 16 bits      -> PRODL:WREG
101  * 24 bits      -> PRODH:PRODL:WREG
102  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
103  * >32 bits     -> on stack, and FSR0 points to the beginning
104  *
105  */
106  
107
108 char *fReturnpic16[] = {"temp1","temp2","temp3","temp4" };
109 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
110 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
111 static char **fReturn = fReturnpic16;
112
113 static char *accUse[] = {"WREG"};
114
115 //static short rbank = -1;
116
117 static struct {
118     short r0Pushed;
119     short r1Pushed;
120     short accInUse;
121     short inLine;
122     short debugLine;
123     short nRegsSaved;
124     set *sendSet;
125 } _G;
126
127 /* Resolved ifx structure. This structure stores information
128    about an iCode ifx that makes it easier to generate code.
129 */
130 typedef struct resolvedIfx {
131   symbol *lbl;     /* pointer to a label */
132   int condition;   /* true or false ifx */
133   int generated;   /* set true when the code associated with the ifx
134                     * is generated */
135 } resolvedIfx;
136
137 extern int pic16_ptrRegReq ;
138 extern int pic16_nRegs;
139 extern FILE *codeOutFile;
140 static void saverbank (int, iCode *,bool);
141
142 static lineNode *lineHead = NULL;
143 static lineNode *lineCurr = NULL;
144
145 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
146 0xE0, 0xC0, 0x80, 0x00};
147 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
148 0x07, 0x03, 0x01, 0x00};
149
150 static  pBlock *pb;
151
152 /*-----------------------------------------------------------------*/
153 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
154 /*                 exponent of 2 is returned, otherwise -1 is      */
155 /*                 returned.                                       */
156 /* note that this is similar to the function `powof2' in SDCCsymt  */
157 /* if(n == 2^y)                                                    */
158 /*   return y;                                                     */
159 /* return -1;                                                      */
160 /*-----------------------------------------------------------------*/
161 static int my_powof2 (unsigned long num)
162 {
163   if(num) {
164     if( (num & (num-1)) == 0) {
165       int nshifts = -1;
166       while(num) {
167         num>>=1;
168         nshifts++;
169       }
170       return nshifts;
171     }
172   }
173
174   return -1;
175 }
176
177 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
178 {
179   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
180                        line_no,
181                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
182                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
183                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
184                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
185                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
186                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
187                        ((result) ? AOP_SIZE(result) : 0));
188 }
189
190 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
191 {
192
193   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
194                        line_no,
195                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
196                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
197                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
198                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
199                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
200                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
201
202 }
203
204 void pic16_emitpcomment (char *fmt, ...)
205 {
206     va_list ap;
207     char lb[INITIAL_INLINEASM];  
208     char *lbp = lb;
209
210     va_start(ap,fmt);   
211
212     lb[0] = ';';
213     vsprintf(lb+1,fmt,ap);
214
215     while (isspace(*lbp)) lbp++;
216
217     if (lbp && *lbp) 
218         lineCurr = (lineCurr ?
219                     connectLine(lineCurr,newLineNode(lb)) :
220                     (lineHead = newLineNode(lb)));
221     lineCurr->isInline = _G.inLine;
222     lineCurr->isDebug  = _G.debugLine;
223
224     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
225     va_end(ap);
226
227 //      fprintf(stderr, "%s\n", lb);
228 }
229
230 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
231 {
232     va_list ap;
233     char lb[INITIAL_INLINEASM];  
234     char *lbp = lb;
235
236     if(!pic16_debug_verbose)
237       return;
238
239     va_start(ap,fmt);   
240
241     if (inst && *inst) {
242         if (fmt && *fmt)
243             sprintf(lb,"%s\t",inst);
244         else
245             sprintf(lb,"%s",inst);
246         vsprintf(lb+(strlen(lb)),fmt,ap);
247     }  else
248         vsprintf(lb,fmt,ap);
249
250     while (isspace(*lbp)) lbp++;
251
252     if (lbp && *lbp) 
253         lineCurr = (lineCurr ?
254                     connectLine(lineCurr,newLineNode(lb)) :
255                     (lineHead = newLineNode(lb)));
256     lineCurr->isInline = _G.inLine;
257     lineCurr->isDebug  = _G.debugLine;
258
259     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
260     va_end(ap);
261
262 //      fprintf(stderr, "%s\n", lb);
263 }
264
265 void pic16_emitpLabel(int key)
266 {
267   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+labelOffset));
268 }
269
270 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
271 {
272
273   if(pcop)
274     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
275   else
276     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
277     
278 //    fprintf(stderr, "%s\n", pcop->name);
279 }
280
281 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
282 {
283
284   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
285
286 }
287
288
289 #if 1
290 #define pic16_emitcode  DEBUGpic16_emitcode
291 #else
292 /*-----------------------------------------------------------------*/
293 /* pic16_emitcode - writes the code into a file : for now it is simple    */
294 /*-----------------------------------------------------------------*/
295 void pic16_emitcode (char *inst,char *fmt, ...)
296 {
297     va_list ap;
298     char lb[INITIAL_INLINEASM];  
299     char *lbp = lb;
300
301     va_start(ap,fmt);   
302
303     if (inst && *inst) {
304         if (fmt && *fmt)
305             sprintf(lb,"%s\t",inst);
306         else
307             sprintf(lb,"%s",inst);
308         vsprintf(lb+(strlen(lb)),fmt,ap);
309     }  else
310         vsprintf(lb,fmt,ap);
311
312     while (isspace(*lbp)) lbp++;
313
314     if (lbp && *lbp) 
315         lineCurr = (lineCurr ?
316                     connectLine(lineCurr,newLineNode(lb)) :
317                     (lineHead = newLineNode(lb)));
318     lineCurr->isInline = _G.inLine;
319     lineCurr->isDebug  = _G.debugLine;
320
321 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
322
323 //    if(pic16_debug_verbose)
324 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
325
326     va_end(ap);
327 }
328 #endif
329
330
331 /*-----------------------------------------------------------------*/
332 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
333 /*-----------------------------------------------------------------*/
334 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
335 {
336     bool r0iu = FALSE , r1iu = FALSE;
337     bool r0ou = FALSE , r1ou = FALSE;
338
339         //fprintf(stderr, "%s:%d: getting free ptr from ic = %c\n", __FUNCTION__, __LINE__, ic->op);
340
341     /* the logic: if r0 & r1 used in the instruction
342     then we are in trouble otherwise */
343
344     /* first check if r0 & r1 are used by this
345     instruction, in which case we are in trouble */
346     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
347         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
348     {
349         goto endOfWorld;      
350     }
351
352     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
353     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
354
355     /* if no usage of r0 then return it */
356     if (!r0iu && !r0ou) {
357         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
358         (*aopp)->type = AOP_R0;
359         
360         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
361     }
362
363     /* if no usage of r1 then return it */
364     if (!r1iu && !r1ou) {
365         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
366         (*aopp)->type = AOP_R1;
367
368         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
369     }    
370
371     /* now we know they both have usage */
372     /* if r0 not used in this instruction */
373     if (!r0iu) {
374         /* push it if not already pushed */
375         if (!_G.r0Pushed) {
376           //pic16_emitcode ("push","%s",
377           //          pic16_regWithIdx(R0_IDX)->dname);
378             _G.r0Pushed++ ;
379         }
380         
381         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
382         (*aopp)->type = AOP_R0;
383
384         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
385     }
386
387     /* if r1 not used then */
388
389     if (!r1iu) {
390         /* push it if not already pushed */
391         if (!_G.r1Pushed) {
392           //pic16_emitcode ("push","%s",
393           //          pic16_regWithIdx(R1_IDX)->dname);
394             _G.r1Pushed++ ;
395         }
396         
397         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
398         (*aopp)->type = AOP_R1;
399         return pic16_regWithIdx(R1_IDX);
400     }
401
402 endOfWorld :
403     /* I said end of world but not quite end of world yet */
404     /* if this is a result then we can push it on the stack*/
405     if (result) {
406         (*aopp)->type = AOP_STK;    
407         return NULL;
408     }
409
410     /* other wise this is true end of the world */
411     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
412            "getFreePtr should never reach here");
413     exit(0);
414 }
415
416 /*-----------------------------------------------------------------*/
417 /* newAsmop - creates a new asmOp                                  */
418 /*-----------------------------------------------------------------*/
419 static asmop *newAsmop (short type)
420 {
421     asmop *aop;
422
423     aop = Safe_calloc(1,sizeof(asmop));
424     aop->type = type;
425     return aop;
426 }
427
428 static void genSetDPTR(int n)
429 {
430     if (!n)
431     {
432         pic16_emitcode(";", "Select standard DPTR");
433         pic16_emitcode("mov", "dps, #0x00");
434     }
435     else
436     {
437         pic16_emitcode(";", "Select alternate DPTR");
438         pic16_emitcode("mov", "dps, #0x01");
439     }
440 }
441
442 /*-----------------------------------------------------------------*/
443 /* resolveIfx - converts an iCode ifx into a form more useful for  */
444 /*              generating code                                    */
445 /*-----------------------------------------------------------------*/
446 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
447 {
448   if(!resIfx) 
449     return;
450
451   //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
452
453   resIfx->condition = 1;    /* assume that the ifx is true */
454   resIfx->generated = 0;    /* indicate that the ifx has not been used */
455
456   if(!ifx) {
457     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
458 /*
459     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
460                         __FUNCTION__,__LINE__,resIfx->lbl->key);
461 */
462   } else {
463     if(IC_TRUE(ifx)) {
464       resIfx->lbl = IC_TRUE(ifx);
465     } else {
466       resIfx->lbl = IC_FALSE(ifx);
467       resIfx->condition = 0;
468     }
469 /*
470     if(IC_TRUE(ifx)) 
471       DEBUGpic16_emitcode("; ***","ifx true is non-null");
472     if(IC_FALSE(ifx)) 
473       DEBUGpic16_emitcode("; ***","ifx false is non-null");
474 */
475   }
476
477   //  DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
478
479 }
480 #if 0
481 /*-----------------------------------------------------------------*/
482 /* pointerCode - returns the code for a pointer type               */
483 /*-----------------------------------------------------------------*/
484 static int pointerCode (sym_link *etype)
485 {
486
487     return PTR_TYPE(SPEC_OCLS(etype));
488
489 }
490 #endif
491 /*-----------------------------------------------------------------*/
492 /* aopForSym - for a true symbol                                   */
493 /*-----------------------------------------------------------------*/
494 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
495 {
496     asmop *aop;
497     memmap *space= SPEC_OCLS(sym->etype);
498
499     DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
500     /* if already has one */
501     if (sym->aop) {
502             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
503         return sym->aop;
504     }
505
506     /* assign depending on the storage class */
507     /* if it is on the stack or indirectly addressable */
508     /* space we need to assign either r0 or r1 to it   */    
509     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
510
511         DEBUGpic16_emitcode("; ***", "sum->onStack || sym->iaccess");
512         
513         sym->aop = aop = newAsmop(0);
514         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
515         aop->size = getSize(sym->type);
516
517         /* now assign the address of the variable to 
518         the pointer register */
519         if (aop->type != AOP_STK) {
520
521             if (sym->onStack) {
522                     if ( _G.accInUse )
523                         pic16_emitcode("push","acc");
524
525                     pic16_emitcode("mov","a,_bp");
526                     pic16_emitcode("add","a,#0x%02x",
527                              ((sym->stack < 0) ?
528                               ((char)(sym->stack - _G.nRegsSaved )) :
529                               ((char)sym->stack)) & 0xff);
530                     pic16_emitcode("mov","%s,a",
531                              aop->aopu.aop_ptr->name);
532
533                     if ( _G.accInUse )
534                         pic16_emitcode("pop","acc");
535             } else
536                 pic16_emitcode("mov","%s,#%s",
537                          aop->aopu.aop_ptr->name,
538                          sym->rname);
539             aop->paged = space->paged;
540         } else
541             aop->aopu.aop_stk = sym->stack;
542         return aop;
543     }
544     
545     if (sym->onStack && options.stack10bit)
546     {
547         /* It's on the 10 bit stack, which is located in
548          * far data space.
549          */
550          
551       //DEBUGpic16_emitcode(";","%d",__LINE__);
552
553         if ( _G.accInUse )
554                 pic16_emitcode("push","acc");
555
556         pic16_emitcode("mov","a,_bp");
557         pic16_emitcode("add","a,#0x%02x",
558                  ((sym->stack < 0) ?
559                    ((char)(sym->stack - _G.nRegsSaved )) :
560                    ((char)sym->stack)) & 0xff);
561         
562         genSetDPTR(1);
563         pic16_emitcode ("mov","dpx1,#0x40");
564         pic16_emitcode ("mov","dph1,#0x00");
565         pic16_emitcode ("mov","dpl1, a");
566         genSetDPTR(0);
567         
568         if ( _G.accInUse )
569             pic16_emitcode("pop","acc");
570             
571         sym->aop = aop = newAsmop(AOP_DPTR2);
572         aop->size = getSize(sym->type); 
573         return aop;
574     }
575
576     //DEBUGpic16_emitcode(";","%d",__LINE__);
577     /* if in bit space */
578     if (IN_BITSPACE(space)) {
579         sym->aop = aop = newAsmop (AOP_CRY);
580         aop->aopu.aop_dir = sym->rname ;
581         aop->size = getSize(sym->type);
582         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
583         return aop;
584     }
585     /* if it is in direct space */
586     if (IN_DIRSPACE(space)) {
587         sym->aop = aop = newAsmop (AOP_DIR);
588         aop->aopu.aop_dir = sym->rname ;
589         aop->size = getSize(sym->type);
590         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
591         pic16_allocDirReg( IC_LEFT(ic) );
592         return aop;
593     }
594
595 #if 0                                                                                           // patch 14
596     /* special case for a function */
597     if (IS_FUNC(sym->type)) {   
598         sym->aop = aop = newAsmop(AOP_IMMD);    
599         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
600         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
601         strcpy(aop->aopu.aop_immd,sym->rname);
602         aop->size = FPTRSIZE; 
603         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
604         return aop;
605     }
606 #endif                                                                                          // patch 14
607
608
609     /* only remaining is far space */
610     /* in which case DPTR gets the address */
611     sym->aop = aop = newAsmop(AOP_PCODE);
612
613 /* change the next if to 1 to revert to good old immediate code */
614         if(IN_CODESPACE(space)) {
615                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
616                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
617                 PCOI(aop->aopu.pcop)->index = 0;
618         } else {
619                 /* try to allocate via direct register */
620                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset); // Patch 8
621 //              aop->size = getSize( sym->type );
622         }
623
624         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
625                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
626
627 #if 0
628         if(!pic16_allocDirReg (IC_LEFT(ic)))
629                 return NULL;
630 #endif
631
632         if(IN_DIRSPACE( space ))
633                 aop->size = PTRSIZE;
634         else if(IN_CODESPACE( space ))
635                 aop->size = FPTRSIZE;
636         else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
637         else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
638         else {
639                 assert( 0 );
640         }
641
642     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
643
644     /* if it is in code space */
645     if (IN_CODESPACE(space))
646         aop->code = 1;
647
648     return aop;     
649 }
650
651 /*-----------------------------------------------------------------*/
652 /* aopForRemat - rematerialzes an object                           */
653 /*-----------------------------------------------------------------*/
654 static asmop *aopForRemat (operand *op) // x symbol *sym)
655 {
656   symbol *sym = OP_SYMBOL(op);
657   iCode *ic = NULL, *oldic;
658   asmop *aop = newAsmop(AOP_PCODE);
659   int val = 0;
660   int offset = 0;
661   int viaimmd=0;
662
663
664         ic = sym->rematiCode;
665
666         DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
667         
668         if(IS_OP_POINTER(op)) {
669                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
670         }
671
672         for (;;) {
673                 oldic = ic;
674
675 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
676         
677                 if (ic->op == '+') {
678                         val += (int) operandLitValue(IC_RIGHT(ic));
679                 } else if (ic->op == '-') {
680                         val -= (int) operandLitValue(IC_RIGHT(ic));
681                 } else
682                         break;
683                 
684                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
685         }
686
687         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
688
689         if(!op->isaddr)viaimmd++; else viaimmd=0;
690                 
691 /* set the following if to 1 to revert to good old immediate code */
692         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))
693                 || viaimmd) {
694
695                 pic16_emitpcomment("%s:%d immediate", __FILE__, __LINE__);
696
697                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
698
699 #if 0
700                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
701 #else
702                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
703 #endif
704
705                 PCOI(aop->aopu.pcop)->index = val;
706         } else {
707                 pic16_emitpcomment("%s:%d dir", __FILE__, __LINE__);
708
709                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname, getSize( OP_SYMBOL( IC_LEFT(ic))->type), val);
710 //              aop->size = AOP_SIZE( IC_LEFT(ic) );
711         }
712
713
714         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
715                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
716 #if 0
717                 val, IS_PTR_CONST(operandType(op)));
718 #else
719                 val, IS_CODEPTR(operandType(op)));
720 #endif
721
722 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
723
724         pic16_allocDirReg (IC_LEFT(ic));
725
726         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
727                 aop->code = 1;
728
729   return aop;        
730 }
731
732 static int aopIdx (asmop *aop, int offset)
733 {
734   if(!aop)
735     return -1;
736
737   if(aop->type !=  AOP_REG)
738     return -2;
739         
740   return aop->aopu.aop_reg[offset]->rIdx;
741
742 }
743 /*-----------------------------------------------------------------*/
744 /* regsInCommon - two operands have some registers in common       */
745 /*-----------------------------------------------------------------*/
746 static bool regsInCommon (operand *op1, operand *op2)
747 {
748     symbol *sym1, *sym2;
749     int i;
750
751     /* if they have registers in common */
752     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
753         return FALSE ;
754
755     sym1 = OP_SYMBOL(op1);
756     sym2 = OP_SYMBOL(op2);
757
758     if (sym1->nRegs == 0 || sym2->nRegs == 0)
759         return FALSE ;
760
761     for (i = 0 ; i < sym1->nRegs ; i++) {
762         int j;
763         if (!sym1->regs[i])
764             continue ;
765
766         for (j = 0 ; j < sym2->nRegs ;j++ ) {
767             if (!sym2->regs[j])
768                 continue ;
769
770             if (sym2->regs[j] == sym1->regs[i])
771                 return TRUE ;
772         }
773     }
774
775     return FALSE ;
776 }
777
778 /*-----------------------------------------------------------------*/
779 /* operandsEqu - equivalent                                        */
780 /*-----------------------------------------------------------------*/
781 static bool operandsEqu ( operand *op1, operand *op2)
782 {
783     symbol *sym1, *sym2;
784
785     /* if they not symbols */
786     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
787         return FALSE;
788
789     sym1 = OP_SYMBOL(op1);
790     sym2 = OP_SYMBOL(op2);
791
792     /* if both are itemps & one is spilt
793        and the other is not then false */
794     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
795         sym1->isspilt != sym2->isspilt )
796         return FALSE ;
797
798     /* if they are the same */
799     if (sym1 == sym2)
800         return TRUE ;
801
802     if (strcmp(sym1->rname,sym2->rname) == 0)
803         return TRUE;
804
805
806     /* if left is a tmp & right is not */
807     if (IS_ITEMP(op1)  && 
808         !IS_ITEMP(op2) &&
809         sym1->isspilt  &&
810         (sym1->usl.spillLoc == sym2))
811         return TRUE;
812
813     if (IS_ITEMP(op2)  && 
814         !IS_ITEMP(op1) &&
815         sym2->isspilt  &&
816         sym1->level > 0 &&
817         (sym2->usl.spillLoc == sym1))
818         return TRUE ;
819
820     return FALSE ;
821 }
822
823 /*-----------------------------------------------------------------*/
824 /* pic16_sameRegs - two asmops have the same registers                   */
825 /*-----------------------------------------------------------------*/
826 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
827 {
828     int i;
829
830     if (aop1 == aop2)
831         return TRUE ;
832
833     if (aop1->type != AOP_REG ||
834         aop2->type != AOP_REG )
835         return FALSE ;
836
837     if (aop1->size != aop2->size )
838         return FALSE ;
839
840     for (i = 0 ; i < aop1->size ; i++ )
841         if (aop1->aopu.aop_reg[i] !=
842             aop2->aopu.aop_reg[i] )
843             return FALSE ;
844
845     return TRUE ;
846 }
847
848 /*-----------------------------------------------------------------*/
849 /* pic16_aopOp - allocates an asmop for an operand  :                    */
850 /*-----------------------------------------------------------------*/
851 void pic16_aopOp (operand *op, iCode *ic, bool result)
852 {
853     asmop *aop;
854     symbol *sym;
855     int i;
856
857     if (!op)
858         return ;
859
860 //      DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
861
862     /* if this a literal */
863     if (IS_OP_LITERAL(op)) {
864         op->aop = aop = newAsmop(AOP_LIT);
865         aop->aopu.aop_lit = op->operand.valOperand;
866         aop->size = getSize(operandType(op));
867         return;
868     }
869
870     {
871       sym_link *type = operandType(op);
872 #if 0
873       if(IS_PTR_CONST(type))
874 #else
875       if(IS_CODEPTR(type))
876 #endif
877         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
878     }
879
880     /* if already has a asmop then continue */
881     if (op->aop)
882         return ;
883
884     /* if the underlying symbol has a aop */
885     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
886       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
887         op->aop = OP_SYMBOL(op)->aop;
888         return;
889     }
890
891     /* if this is a true symbol */
892     if (IS_TRUE_SYMOP(op)) {    
893         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
894       op->aop = aopForSym(ic,OP_SYMBOL(op),result);
895       return ;
896     }
897
898     /* this is a temporary : this has
899     only four choices :
900     a) register
901     b) spillocation
902     c) rematerialize 
903     d) conditional   
904     e) can be a return use only */
905
906     sym = OP_SYMBOL(op);
907
908         DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
909     /* if the type is a conditional */
910     if (sym->regType == REG_CND) {
911         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
912         aop->size = 0;
913         return;
914     }
915
916     /* if it is spilt then two situations
917     a) is rematerialize 
918     b) has a spill location */
919     if (sym->isspilt || sym->nRegs == 0) {
920
921       DEBUGpic16_emitcode(";","%d",__LINE__);
922         /* rematerialize it NOW */
923         if (sym->remat) {
924
925             sym->aop = op->aop = aop =
926                                       aopForRemat (op);
927             aop->size = getSize(sym->type);
928             //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
929             return;
930         }
931
932 #if 1
933         if (sym->accuse) {
934             int i;
935             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
936             aop->size = getSize(sym->type);
937             for ( i = 0 ; i < 1 ; i++ ) {
938                 aop->aopu.aop_str[i] = accUse[i];
939 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
940             }
941             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
942             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
943             return;  
944         }
945 #endif
946
947 #if 1
948         if (sym->ruonly ) {
949           /*
950           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
951           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
952           //pic16_allocDirReg (IC_LEFT(ic));
953           aop->size = getSize(sym->type);
954           */
955
956           unsigned i;
957
958           aop = op->aop = sym->aop = newAsmop(AOP_STR);
959           aop->size = getSize(sym->type);
960           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
961             aop->aopu.aop_str[i] = fReturn[i];
962
963           DEBUGpic16_emitcode(";","%d",__LINE__);
964           return;
965         }
966 #endif
967         /* else spill location  */
968         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
969             /* force a new aop if sizes differ */
970             sym->usl.spillLoc->aop = NULL;
971         }
972         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
973                             __FUNCTION__,__LINE__,
974                             sym->usl.spillLoc->rname,
975                             sym->rname, sym->usl.spillLoc->offset);
976
977         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
978         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
979         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
980                                           getSize(sym->type), 
981                                           sym->usl.spillLoc->offset);
982         aop->size = getSize(sym->type);
983
984         return;
985     }
986
987     {
988       sym_link *type = operandType(op);
989 #if 0
990       if(IS_PTR_CONST(type)) 
991 #else
992       if(IS_CODEPTR(type)) 
993 #endif
994         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
995     }
996
997     /* must be in a register */
998     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
999     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1000     aop->size = sym->nRegs;
1001     for ( i = 0 ; i < sym->nRegs ;i++)
1002         aop->aopu.aop_reg[i] = sym->regs[i];
1003 }
1004
1005 /*-----------------------------------------------------------------*/
1006 /* pic16_freeAsmop - free up the asmop given to an operand               */
1007 /*----------------------------------------------------------------*/
1008 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1009 {   
1010     asmop *aop ;
1011
1012     if (!op)
1013         aop = aaop;
1014     else 
1015         aop = op->aop;
1016
1017     if (!aop)
1018         return ;
1019
1020     if (aop->freed)
1021         goto dealloc; 
1022
1023     aop->freed = 1;
1024
1025     /* depending on the asmop type only three cases need work AOP_RO
1026        , AOP_R1 && AOP_STK */
1027 #if 0
1028     switch (aop->type) {
1029         case AOP_R0 :
1030             if (_G.r0Pushed ) {
1031                 if (pop) {
1032                     pic16_emitcode ("pop","ar0");     
1033                     _G.r0Pushed--;
1034                 }
1035             }
1036             bitVectUnSetBit(ic->rUsed,R0_IDX);
1037             break;
1038
1039         case AOP_R1 :
1040             if (_G.r1Pushed ) {
1041                 if (pop) {
1042                     pic16_emitcode ("pop","ar1");
1043                     _G.r1Pushed--;
1044                 }
1045             }
1046             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1047             break;
1048
1049         case AOP_STK :
1050         {
1051             int sz = aop->size;    
1052             int stk = aop->aopu.aop_stk + aop->size;
1053             bitVectUnSetBit(ic->rUsed,R0_IDX);
1054             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1055
1056             getFreePtr(ic,&aop,FALSE);
1057             
1058             if (options.stack10bit)
1059             {
1060                 /* I'm not sure what to do here yet... */
1061                 /* #STUB */
1062                 fprintf(stderr, 
1063                         "*** Warning: probably generating bad code for "
1064                         "10 bit stack mode.\n");
1065             }
1066             
1067             if (stk) {
1068                 pic16_emitcode ("mov","a,_bp");
1069                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1070                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1071             } else {
1072                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1073             }
1074
1075             while (sz--) {
1076                 pic16_emitcode("pop","acc");
1077                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1078                 if (!sz) break;
1079                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1080             }
1081             op->aop = aop;
1082             pic16_freeAsmop(op,NULL,ic,TRUE);
1083             if (_G.r0Pushed) {
1084                 pic16_emitcode("pop","ar0");
1085                 _G.r0Pushed--;
1086             }
1087
1088             if (_G.r1Pushed) {
1089                 pic16_emitcode("pop","ar1");
1090                 _G.r1Pushed--;
1091             }       
1092         }
1093     }
1094 #endif
1095
1096 dealloc:
1097     /* all other cases just dealloc */
1098     if (op ) {
1099         op->aop = NULL;
1100         if (IS_SYMOP(op)) {
1101             OP_SYMBOL(op)->aop = NULL;    
1102             /* if the symbol has a spill */
1103             if (SPIL_LOC(op))
1104                 SPIL_LOC(op)->aop = NULL;
1105         }
1106     }
1107 }
1108
1109 /*-----------------------------------------------------------------*/
1110 /* pic16_aopGet - for fetching value of the aop                          */
1111 /*-----------------------------------------------------------------*/
1112 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1113 {
1114     char *s = buffer ;
1115     char *rs;
1116
1117     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1118
1119     /* offset is greater than size then zero */
1120     if (offset > (aop->size - 1) &&
1121         aop->type != AOP_LIT)
1122         return zero;
1123
1124     /* depending on type */
1125     switch (aop->type) {
1126         
1127     case AOP_R0:
1128     case AOP_R1:
1129         DEBUGpic16_emitcode(";","%d",__LINE__);
1130         /* if we need to increment it */       
1131         while (offset > aop->coff) {        
1132             pic16_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
1133             aop->coff++;
1134         }
1135         
1136         while (offset < aop->coff) {
1137             pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1138             aop->coff--;
1139         }
1140         
1141         aop->coff = offset ;
1142         if (aop->paged) {
1143             pic16_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1144             return (dname ? "acc" : "a");
1145         }       
1146         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1147         rs = Safe_calloc(1,strlen(s)+1);
1148         strcpy(rs,s);   
1149         return rs;
1150         
1151     case AOP_DPTR:
1152     case AOP_DPTR2:
1153         DEBUGpic16_emitcode(";","%d",__LINE__);
1154     if (aop->type == AOP_DPTR2)
1155     {
1156         genSetDPTR(1);
1157     }
1158     
1159         while (offset > aop->coff) {
1160             pic16_emitcode ("inc","dptr");
1161             aop->coff++;
1162         }
1163         
1164         while (offset < aop->coff) {        
1165             pic16_emitcode("lcall","__decdptr");
1166             aop->coff--;
1167         }
1168         
1169         aop->coff = offset;
1170         if (aop->code) {
1171             pic16_emitcode("clr","a");
1172             pic16_emitcode("movc","a,@a+dptr");
1173         }
1174     else {
1175             pic16_emitcode("movx","a,@dptr");
1176     }
1177             
1178     if (aop->type == AOP_DPTR2)
1179     {
1180         genSetDPTR(0);
1181     }
1182             
1183     return (dname ? "acc" : "a");
1184         
1185         
1186     case AOP_IMMD:
1187         if (bit16) 
1188             sprintf (s,"%s",aop->aopu.aop_immd);
1189         else
1190             if (offset) 
1191                 sprintf(s,"(%s >> %d)",
1192                         aop->aopu.aop_immd,
1193                         offset*8);
1194             else
1195                 sprintf(s,"%s",
1196                         aop->aopu.aop_immd);
1197         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1198         rs = Safe_calloc(1,strlen(s)+1);
1199         strcpy(rs,s);   
1200         return rs;
1201         
1202     case AOP_DIR:
1203       if (offset) {
1204         sprintf(s,"(%s + %d)",
1205                 aop->aopu.aop_dir,
1206                 offset);
1207         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1208       } else
1209             sprintf(s,"%s",aop->aopu.aop_dir);
1210         rs = Safe_calloc(1,strlen(s)+1);
1211         strcpy(rs,s);   
1212         return rs;
1213         
1214     case AOP_REG:
1215       //if (dname) 
1216       //    return aop->aopu.aop_reg[offset]->dname;
1217       //else
1218             return aop->aopu.aop_reg[offset]->name;
1219         
1220     case AOP_CRY:
1221       //pic16_emitcode(";","%d",__LINE__);
1222       return aop->aopu.aop_dir;
1223         
1224     case AOP_ACC:
1225         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1226 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1227 //        assert( 0 );
1228         return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1229
1230     case AOP_LIT:
1231         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1232         rs = Safe_calloc(1,strlen(s)+1);
1233         strcpy(rs,s);   
1234         return rs;
1235         
1236     case AOP_STR:
1237         aop->coff = offset ;
1238         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1239             dname)
1240             return "acc";
1241         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1242         
1243         return aop->aopu.aop_str[offset];
1244         
1245     case AOP_PCODE:
1246       {
1247         pCodeOp *pcop = aop->aopu.pcop;
1248         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1249         if(pcop->name) {
1250           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1251           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1252           sprintf(s,"%s", pcop->name);
1253         } else
1254           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1255
1256       }
1257       rs = Safe_calloc(1,strlen(s)+1);
1258       strcpy(rs,s);   
1259       return rs;
1260
1261     }
1262
1263     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1264            "aopget got unsupported aop->type");
1265     exit(0);
1266 }
1267
1268
1269 /*-----------------------------------------------------------------*/
1270 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1271 /*-----------------------------------------------------------------*/
1272 pCodeOp *pic16_popGetTempReg(void)
1273 {
1274   pCodeOp *pcop;
1275
1276         pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1277         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1278                 PCOR(pcop)->r->wasUsed=1;
1279                 PCOR(pcop)->r->isFree=0;
1280
1281                 /* push value on stack */
1282                 pic16_pushpCodeOp( pcop );
1283         }
1284
1285   return pcop;
1286 }
1287
1288 /*-----------------------------------------------------------------*/
1289 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1290 /*-----------------------------------------------------------------*/
1291 void pic16_popReleaseTempReg(pCodeOp *pcop)
1292 {
1293         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1294                 PCOR(pcop)->r->isFree = 1;
1295                 
1296                 pic16_poppCodeOp( pcop );
1297         }
1298 }
1299 /*-----------------------------------------------------------------*/
1300 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1301 /*-----------------------------------------------------------------*/
1302 pCodeOp *pic16_popGetLabel(unsigned int key)
1303 {
1304
1305   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1306
1307   if(key>max_key)
1308     max_key = key;
1309
1310   return pic16_newpCodeOpLabel(NULL,key+100+labelOffset);
1311 }
1312
1313 /*-----------------------------------------------------------------*/
1314 /* pic16_popCopyReg - copy a pcode operator                              */
1315 /*-----------------------------------------------------------------*/
1316 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1317 {
1318   pCodeOpReg *pcor;
1319
1320   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1321   pcor->pcop.type = pc->pcop.type;
1322   if(pc->pcop.name) {
1323     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1324       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1325   } else
1326     pcor->pcop.name = NULL;
1327
1328   pcor->r = pc->r;
1329   pcor->rIdx = pc->rIdx;
1330   pcor->r->wasUsed=1;
1331
1332 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1333
1334   return PCOP(pcor);
1335 }
1336
1337 /*-----------------------------------------------------------------*/
1338 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1339 /*-----------------------------------------------------------------*/
1340 pCodeOp *pic16_popGetLit(unsigned int lit)
1341 {
1342   return pic16_newpCodeOpLit(lit);
1343 }
1344
1345 /*-----------------------------------------------------------------*/
1346 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1347 /*-----------------------------------------------------------------*/
1348 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1349 {
1350   return pic16_newpCodeOpLit2(lit, arg2);
1351 }
1352
1353
1354 /*-----------------------------------------------------------------*/
1355 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1356 /*-----------------------------------------------------------------*/
1357 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1358 {
1359   return pic16_newpCodeOpImmd(name, offset,index, 0);
1360 }
1361
1362
1363 /*-----------------------------------------------------------------*/
1364 /* pic16_popGet - asm operator to pcode operator conversion              */
1365 /*-----------------------------------------------------------------*/
1366 pCodeOp *pic16_popGetWithString(char *str)
1367 {
1368   pCodeOp *pcop;
1369
1370
1371   if(!str) {
1372     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1373     exit (1);
1374   }
1375
1376   pcop = pic16_newpCodeOp(str,PO_STR);
1377
1378   return pcop;
1379 }
1380
1381 /*-----------------------------------------------------------------*/
1382 /* pic16_popRegFromString -                                        */
1383 /*-----------------------------------------------------------------*/
1384 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset)
1385 {
1386
1387   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1388   pcop->type = PO_DIR;
1389
1390   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1391   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1392
1393   if(!str)
1394     str = "BAD_STRING";
1395
1396   pcop->name = Safe_calloc(1,strlen(str)+1);
1397   strcpy(pcop->name,str);
1398
1399   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1400
1401   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1402   if(PCOR(pcop)->r == NULL) {
1403 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1404 //              __FUNCTION__, __LINE__, str, size, offset);
1405     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size);
1406
1407         //fprintf(stderr, "allocating new register -> %s\n", str);
1408
1409 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d - had to alloc by reg name",__LINE__,pcop->name,size,offset);
1410   } else {
1411 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d",__LINE__,pcop->name,size,offset);
1412   }
1413   PCOR(pcop)->instance = offset;
1414
1415   return pcop;
1416 }
1417
1418 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1419 {
1420   pCodeOp *pcop;
1421
1422 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1423
1424         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1425         PCOR(pcop)->rIdx = rIdx;
1426         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1427         PCOR(pcop)->r->isFree = 0;
1428         PCOR(pcop)->r->wasUsed = 1;
1429
1430         pcop->type = PCOR(pcop)->r->pc_type;
1431
1432   return pcop;
1433 }
1434
1435 /*---------------------------------------------------------------------------------*/
1436 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1437 /*                 VR 030601                                                       */
1438 /*---------------------------------------------------------------------------------*/
1439 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1440 {
1441   pCodeOpReg2 *pcop2;
1442   pCodeOp *temp;
1443   
1444         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1445
1446         /* comment the following check, so errors to throw up */
1447 //      if(!pcop2)return NULL;
1448
1449         temp = pic16_popGet(aop_dst, offset);
1450         pcop2->pcop2 = temp;
1451         
1452   return PCOP(pcop2);
1453 }
1454
1455
1456
1457 /*--------------------------------------------------------------------------------.-*/
1458 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1459 /*                  VR 030601 , adapted by Hans Dorn                                */
1460 /*--------------------------------------------------------------------------------.-*/
1461 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1462 {
1463   pCodeOpReg2 *pcop2;
1464  
1465         pcop2 = (pCodeOpReg2 *)src;
1466         pcop2->pcop2 = dst;
1467         
1468         return PCOP(pcop2);
1469 }
1470
1471
1472
1473 /*---------------------------------------------------------------------------------*/
1474 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1475 /*                     movff instruction                                           */
1476 /*---------------------------------------------------------------------------------*/
1477 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1478 {
1479   pCodeOpReg2 *pcop2;
1480
1481         if(!noalloc) {
1482                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1483                 pcop2->pcop2 = pic16_popCopyReg(dst);
1484         } else {
1485                 /* the pCodeOp may be already allocated */
1486                 pcop2 = (pCodeOpReg2 *)(src);
1487                 pcop2->pcop2 = (pCodeOp *)(dst);
1488         }
1489
1490   return PCOP(pcop2);
1491 }
1492
1493
1494 /*-----------------------------------------------------------------*/
1495 /* pic16_popGet - asm operator to pcode operator conversion              */
1496 /*-----------------------------------------------------------------*/
1497 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1498 {
1499   //char *s = buffer ;
1500   char *rs;
1501   pCodeOp *pcop;
1502
1503     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1504     /* offset is greater than
1505     size then zero */
1506
1507 //    if (offset > (aop->size - 1) &&
1508 //        aop->type != AOP_LIT)
1509 //      return NULL;  //zero;
1510
1511     /* depending on type */
1512     switch (aop->type) {
1513         
1514     case AOP_R0:
1515     case AOP_R1:
1516     case AOP_DPTR:
1517     case AOP_DPTR2:
1518         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1519         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1520         assert( 0 );
1521         return NULL;
1522
1523
1524
1525     case AOP_IMMD:
1526       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1527       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1528
1529     case AOP_ACC:
1530       {
1531         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1532
1533         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1534
1535         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1536         
1537         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1538         PCOR(pcop)->rIdx = rIdx;
1539         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1540         PCOR(pcop)->r->wasUsed=1;
1541         PCOR(pcop)->r->isFree=0;
1542
1543         PCOR(pcop)->instance = offset;
1544         pcop->type = PCOR(pcop)->r->pc_type;
1545 //      rs = aop->aopu.aop_reg[offset]->name;
1546 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1547         return pcop;
1548
1549
1550 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1551 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1552
1553 //      assert( 0 );
1554       }
1555         
1556     case AOP_DIR:
1557       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1558       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1559         
1560     case AOP_REG:
1561       {
1562         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1563
1564         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1565         
1566         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1567         PCOR(pcop)->rIdx = rIdx;
1568         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1569         PCOR(pcop)->r->wasUsed=1;
1570         PCOR(pcop)->r->isFree=0;
1571
1572         PCOR(pcop)->instance = offset;
1573         pcop->type = PCOR(pcop)->r->pc_type;
1574         rs = aop->aopu.aop_reg[offset]->name;
1575         DEBUGpic16_emitcode(";","%d regiser idx = %d name =%s",__LINE__,rIdx,rs);
1576         return pcop;
1577       }
1578
1579     case AOP_CRY:
1580         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1581
1582       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1583       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1584       //if(PCOR(pcop)->r == NULL)
1585       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1586       return pcop;
1587         
1588     case AOP_LIT:
1589         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1590       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1591
1592     case AOP_STR:
1593       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1594       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1595
1596       /*
1597       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1598       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1599       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1600       pcop->type = PCOR(pcop)->r->pc_type;
1601       pcop->name = PCOR(pcop)->r->name;
1602
1603       return pcop;
1604       */
1605
1606     case AOP_PCODE:
1607       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1608                           __LINE__, 
1609                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1610       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1611 #if 1
1612         switch( aop->aopu.pcop->type ) {
1613                 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1614                 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1615                 default:
1616                         assert( 0 );    /* should never reach here */;
1617         }
1618 #else
1619       PCOI(pcop)->offset = offset;
1620 #endif
1621       return pcop;
1622     }
1623
1624     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1625            "pic16_popGet got unsupported aop->type");
1626     exit(0);
1627 }
1628 /*-----------------------------------------------------------------*/
1629 /* pic16_aopPut - puts a string for a aop                                */
1630 /*-----------------------------------------------------------------*/
1631 void pic16_aopPut (asmop *aop, char *s, int offset)
1632 {
1633     char *d = buffer ;
1634     symbol *lbl ;
1635
1636     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1637
1638     if (aop->size && offset > ( aop->size - 1)) {
1639         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1640                "pic16_aopPut got offset > aop->size");
1641         exit(0);
1642     }
1643
1644     /* will assign value to value */
1645     /* depending on where it is ofcourse */
1646     switch (aop->type) {
1647     case AOP_DIR:
1648       if (offset) {
1649         sprintf(d,"(%s + %d)",
1650                 aop->aopu.aop_dir,offset);
1651         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1652
1653       } else
1654             sprintf(d,"%s",aop->aopu.aop_dir);
1655         
1656         if (strcmp(d,s)) {
1657           DEBUGpic16_emitcode(";","%d",__LINE__);
1658           if(strcmp(s,"W"))
1659             pic16_emitcode("movf","%s,w",s);
1660           pic16_emitcode("movwf","%s",d);
1661
1662           if(strcmp(s,"W")) {
1663             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1664             if(offset >= aop->size) {
1665               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1666               break;
1667             } else
1668               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1669           }
1670
1671           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1672
1673
1674         }
1675         break;
1676         
1677     case AOP_REG:
1678       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1679         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1680           /*
1681             if (*s == '@'           ||
1682                 strcmp(s,"r0") == 0 ||
1683                 strcmp(s,"r1") == 0 ||
1684                 strcmp(s,"r2") == 0 ||
1685                 strcmp(s,"r3") == 0 ||
1686                 strcmp(s,"r4") == 0 ||
1687                 strcmp(s,"r5") == 0 ||
1688                 strcmp(s,"r6") == 0 || 
1689                 strcmp(s,"r7") == 0 )
1690                 pic16_emitcode("mov","%s,%s  ; %d",
1691                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1692             else
1693           */
1694
1695           if(strcmp(s,"W")==0 )
1696             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
1697
1698           pic16_emitcode("movwf","%s",
1699                    aop->aopu.aop_reg[offset]->name);
1700
1701           if(strcmp(s,zero)==0) {
1702             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1703
1704           } else if(strcmp(s,"W")==0) {
1705             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1706             pcop->type = PO_GPR_REGISTER;
1707
1708             PCOR(pcop)->rIdx = -1;
1709             PCOR(pcop)->r = NULL;
1710
1711             DEBUGpic16_emitcode(";","%d",__LINE__);
1712             pcop->name = Safe_strdup(s);
1713             pic16_emitpcode(POC_MOVFW,pcop);
1714             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1715           } else if(strcmp(s,one)==0) {
1716             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1717             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1718           } else {
1719             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1720           }
1721         }
1722         break;
1723         
1724     case AOP_DPTR:
1725     case AOP_DPTR2:
1726     
1727     if (aop->type == AOP_DPTR2)
1728     {
1729         genSetDPTR(1);
1730     }
1731     
1732         if (aop->code) {
1733             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1734                    "pic16_aopPut writting to code space");
1735             exit(0);
1736         }
1737         
1738         while (offset > aop->coff) {
1739             aop->coff++;
1740             pic16_emitcode ("inc","dptr");
1741         }
1742         
1743         while (offset < aop->coff) {
1744             aop->coff-- ;
1745             pic16_emitcode("lcall","__decdptr");
1746         }
1747         
1748         aop->coff = offset;
1749         
1750         /* if not in accumulater */
1751         MOVA(s);        
1752         
1753         pic16_emitcode ("movx","@dptr,a");
1754         
1755     if (aop->type == AOP_DPTR2)
1756     {
1757         genSetDPTR(0);
1758     }
1759         break;
1760         
1761     case AOP_R0:
1762     case AOP_R1:
1763         while (offset > aop->coff) {
1764             aop->coff++;
1765             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1766         }
1767         while (offset < aop->coff) {
1768             aop->coff-- ;
1769             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1770         }
1771         aop->coff = offset;
1772         
1773         if (aop->paged) {
1774             MOVA(s);           
1775             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1776             
1777         } else
1778             if (*s == '@') {
1779                 MOVA(s);
1780                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1781             } else
1782                 if (strcmp(s,"r0") == 0 ||
1783                     strcmp(s,"r1") == 0 ||
1784                     strcmp(s,"r2") == 0 ||
1785                     strcmp(s,"r3") == 0 ||
1786                     strcmp(s,"r4") == 0 ||
1787                     strcmp(s,"r5") == 0 ||
1788                     strcmp(s,"r6") == 0 || 
1789                     strcmp(s,"r7") == 0 ) {
1790                     char buffer[10];
1791                     sprintf(buffer,"a%s",s);
1792                     pic16_emitcode("mov","@%s,%s",
1793                              aop->aopu.aop_ptr->name,buffer);
1794                 } else
1795                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1796         
1797         break;
1798         
1799     case AOP_STK:
1800         if (strcmp(s,"a") == 0)
1801             pic16_emitcode("push","acc");
1802         else
1803             pic16_emitcode("push","%s",s);
1804         
1805         break;
1806         
1807     case AOP_CRY:
1808         /* if bit variable */
1809         if (!aop->aopu.aop_dir) {
1810             pic16_emitcode("clr","a");
1811             pic16_emitcode("rlc","a");
1812         } else {
1813             if (s == zero) 
1814                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1815             else
1816                 if (s == one)
1817                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1818                 else
1819                     if (!strcmp(s,"c"))
1820                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1821                     else {
1822                         lbl = newiTempLabel(NULL);
1823                         
1824                         if (strcmp(s,"a")) {
1825                             MOVA(s);
1826                         }
1827                         pic16_emitcode("clr","c");
1828                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1829                         pic16_emitcode("cpl","c");
1830                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
1831                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1832                     }
1833         }
1834         break;
1835         
1836     case AOP_STR:
1837         aop->coff = offset;
1838         if (strcmp(aop->aopu.aop_str[offset],s))
1839             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1840         break;
1841         
1842     case AOP_ACC:
1843         aop->coff = offset;
1844         if (!offset && (strcmp(s,"acc") == 0))
1845             break;
1846         
1847         if (strcmp(aop->aopu.aop_str[offset],s))
1848             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1849         break;
1850
1851     default :
1852         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1853                "pic16_aopPut got unsupported aop->type");
1854         exit(0);    
1855     }    
1856
1857 }
1858
1859 /*-----------------------------------------------------------------*/
1860 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1861 /*-----------------------------------------------------------------*/
1862 static void mov2w (asmop *aop, int offset)
1863 {
1864
1865   if(!aop)
1866     return;
1867
1868   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1869
1870   if ( aop->type == AOP_PCODE ||
1871        aop->type == AOP_LIT )
1872     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1873   else
1874     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1875
1876 }
1877
1878
1879 /* push pcop into stack */
1880 void pic16_pushpCodeOp(pCodeOp *pcop)
1881 {
1882         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
1883 }
1884
1885 /* pop pcop from stack */
1886 void pic16_poppCodeOp(pCodeOp *pcop)
1887 {
1888         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
1889 }
1890
1891
1892 /*-----------------------------------------------------------------*/
1893 /* pushw - pushes wreg to stack                                    */
1894 /*-----------------------------------------------------------------*/
1895 void pushw(void)
1896 {
1897         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1898         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
1899 }
1900
1901                 
1902 /*-----------------------------------------------------------------*/
1903 /* pushaop - pushes aop to stack                                   */
1904 /*-----------------------------------------------------------------*/
1905 void pushaop(asmop *aop, int offset)
1906 {
1907         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1908         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
1909 }
1910
1911 /*-----------------------------------------------------------------*/
1912 /* popaop - pops aop from stack                                    */
1913 /*-----------------------------------------------------------------*/
1914 void popaop(asmop *aop, int offset)
1915 {
1916         DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
1917         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
1918 }
1919
1920 void popaopidx(asmop *aop, int offset, int index)
1921 {
1922   int ofs=1;
1923
1924         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1925
1926         if(STACK_MODEL_LARGE)ofs++;
1927
1928         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
1929         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
1930 }
1931
1932 /*-----------------------------------------------------------------*/
1933 /* reAdjustPreg - points a register back to where it should        */
1934 /*-----------------------------------------------------------------*/
1935 static void reAdjustPreg (asmop *aop)
1936 {
1937     int size ;
1938
1939     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1940     aop->coff = 0;
1941     if ((size = aop->size) <= 1)
1942         return ;
1943     size-- ;
1944     switch (aop->type) {
1945         case AOP_R0 :
1946         case AOP_R1 :
1947             while (size--)
1948                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1949             break;          
1950         case AOP_DPTR :
1951         case AOP_DPTR2:
1952             if (aop->type == AOP_DPTR2)
1953             {
1954                 genSetDPTR(1);
1955             } 
1956             while (size--)
1957             {
1958                 pic16_emitcode("lcall","__decdptr");
1959             }
1960                 
1961             if (aop->type == AOP_DPTR2)
1962             {
1963                 genSetDPTR(0);
1964             }                
1965             break;  
1966
1967     }   
1968
1969 }
1970
1971
1972 #if 0
1973 /*-----------------------------------------------------------------*/
1974 /* opIsGptr: returns non-zero if the passed operand is             */   
1975 /* a generic pointer type.                                         */
1976 /*-----------------------------------------------------------------*/ 
1977 static int opIsGptr(operand *op)
1978 {
1979     sym_link *type = operandType(op);
1980     
1981     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1982     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1983     {
1984         return 1;
1985     }
1986     return 0;        
1987 }
1988 #endif
1989
1990 /*-----------------------------------------------------------------*/
1991 /* pic16_getDataSize - get the operand data size                         */
1992 /*-----------------------------------------------------------------*/
1993 int pic16_getDataSize(operand *op)
1994 {
1995     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1996
1997
1998     return AOP_SIZE(op);
1999
2000     // tsd- in the pic port, the genptr size is 1, so this code here
2001     // fails. ( in the 8051 port, the size was 4).
2002 #if 0
2003     int size;
2004     size = AOP_SIZE(op);
2005     if (size == GPTRSIZE)
2006     {
2007         sym_link *type = operandType(op);
2008         if (IS_GENPTR(type))
2009         {
2010             /* generic pointer; arithmetic operations
2011              * should ignore the high byte (pointer type).
2012              */
2013             size--;
2014     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2015         }
2016     }
2017     return size;
2018 #endif
2019 }
2020
2021 /*-----------------------------------------------------------------*/
2022 /* pic16_outAcc - output Acc                                             */
2023 /*-----------------------------------------------------------------*/
2024 void pic16_outAcc(operand *result)
2025 {
2026   int size,offset;
2027   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2028   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2029
2030
2031   size = pic16_getDataSize(result);
2032   if(size){
2033     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2034     size--;
2035     offset = 1;
2036     /* unsigned or positive */
2037     while(size--)
2038       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2039   }
2040
2041 }
2042
2043 /*-----------------------------------------------------------------*/
2044 /* pic16_outBitC - output a bit C                                        */
2045 /*-----------------------------------------------------------------*/
2046 void pic16_outBitC(operand *result)
2047 {
2048
2049     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2050     /* if the result is bit */
2051     if (AOP_TYPE(result) == AOP_CRY) 
2052         pic16_aopPut(AOP(result),"c",0);
2053     else {
2054         pic16_emitcode("clr","a  ; %d", __LINE__);
2055         pic16_emitcode("rlc","a");
2056         pic16_outAcc(result);
2057     }
2058 }
2059
2060 /*-----------------------------------------------------------------*/
2061 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2062 /*-----------------------------------------------------------------*/
2063 void pic16_toBoolean(operand *oper)
2064 {
2065     int size = AOP_SIZE(oper) - 1;
2066     int offset = 1;
2067
2068     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2069
2070     if ( AOP_TYPE(oper) != AOP_ACC) {
2071       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2072     }
2073     while (size--) {
2074       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2075     }
2076 }
2077
2078
2079 #if !defined(GEN_Not)
2080 /*-----------------------------------------------------------------*/
2081 /* genNot - generate code for ! operation                          */
2082 /*-----------------------------------------------------------------*/
2083 static void pic16_genNot (iCode *ic)
2084 {
2085   symbol *tlbl;
2086   int size;
2087
2088   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2089   /* assign asmOps to operand & result */
2090   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2091   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2092
2093   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2094   /* if in bit space then a special case */
2095   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2096     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2097       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2098       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2099     } else {
2100       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2101       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2102       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2103     }
2104     goto release;
2105   }
2106
2107   size = AOP_SIZE(IC_LEFT(ic));
2108   if(size == 1) {
2109     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2110     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2111     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2112     goto release;
2113   }
2114   pic16_toBoolean(IC_LEFT(ic));
2115
2116   tlbl = newiTempLabel(NULL);
2117   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2118   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2119   pic16_outBitC(IC_RESULT(ic));
2120
2121  release:    
2122   /* release the aops */
2123   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2124   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2125 }
2126 #endif
2127
2128
2129 #if !defined(GEN_Cpl)
2130 /*-----------------------------------------------------------------*/
2131 /* genCpl - generate code for complement                           */
2132 /*-----------------------------------------------------------------*/
2133 static void pic16_genCpl (iCode *ic)
2134 {
2135     int offset = 0;
2136     int size ;
2137
2138
2139     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2140     /* assign asmOps to operand & result */
2141     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2142     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2143
2144     /* if both are in bit space then 
2145     a special case */
2146     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2147         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2148
2149         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2150         pic16_emitcode("cpl","c"); 
2151         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2152         goto release; 
2153     } 
2154
2155     size = AOP_SIZE(IC_RESULT(ic));
2156     while (size--) {
2157 /*
2158         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2159         MOVA(l);       
2160         pic16_emitcode("cpl","a");
2161         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2162 */
2163         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2164               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2165         } else {
2166                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2167                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2168         }
2169         offset++;
2170
2171     }
2172
2173
2174 release:
2175     /* release the aops */
2176     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2177     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2178 }
2179 #endif
2180
2181 /*-----------------------------------------------------------------*/
2182 /* genUminusFloat - unary minus for floating points                */
2183 /*-----------------------------------------------------------------*/
2184 static void genUminusFloat(operand *op,operand *result)
2185 {
2186     int size ,offset =0 ;
2187     char *l;
2188
2189     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2190     /* for this we just need to flip the 
2191     first it then copy the rest in place */
2192     size = AOP_SIZE(op) - 1;
2193     l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2194
2195     MOVA(l);    
2196
2197     pic16_emitcode("cpl","acc.7");
2198     pic16_aopPut(AOP(result),"a",3);    
2199
2200     while(size--) {
2201         pic16_aopPut(AOP(result),
2202                pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2203                offset);
2204         offset++;
2205     }          
2206 }
2207
2208 /*-----------------------------------------------------------------*/
2209 /* genUminus - unary minus code generation                         */
2210 /*-----------------------------------------------------------------*/
2211 static void genUminus (iCode *ic)
2212 {
2213   int size, i;
2214   sym_link *optype, *rtype;
2215
2216
2217   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2218   /* assign asmops */
2219   pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2220   pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2221
2222   /* if both in bit space then special
2223      case */
2224   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2225       AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2226
2227     pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2228     pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2229     pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2230
2231     goto release; 
2232   } 
2233
2234   optype = operandType(IC_LEFT(ic));
2235   rtype = operandType(IC_RESULT(ic));
2236
2237   /* if float then do float stuff */
2238   if (IS_FLOAT(optype)) {
2239     genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2240     goto release;
2241   }
2242
2243   /* otherwise subtract from zero by taking the 2's complement */
2244   size = AOP_SIZE(IC_LEFT(ic));
2245
2246   for(i=0; i<size; i++) {
2247     if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2248       pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2249     else {
2250       pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2251       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2252     }
2253   }
2254
2255   pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2256   for(i=1; i<size; i++) {
2257     emitSKPNZ;
2258     pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2259   }
2260
2261  release:
2262   /* release the aops */
2263   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2264   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2265 }
2266
2267 /*-----------------------------------------------------------------*/
2268 /* saveRegisters - will look for a call and save the registers     */
2269 /*-----------------------------------------------------------------*/
2270 static void saveRegisters(iCode *lic) 
2271 {
2272     int i;
2273     iCode *ic;
2274     bitVect *rsave;
2275     sym_link *dtype;
2276
2277     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2278     /* look for call */
2279     for (ic = lic ; ic ; ic = ic->next) 
2280         if (ic->op == CALL || ic->op == PCALL)
2281             break;
2282
2283     if (!ic) {
2284         fprintf(stderr,"found parameter push with no function call\n");
2285         return ;
2286     }
2287
2288     /* if the registers have been saved already then
2289     do nothing */
2290     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2291         return ;
2292
2293     /* find the registers in use at this time 
2294     and push them away to safety */
2295     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2296                           ic->rUsed);
2297
2298     ic->regsSaved = 1;
2299     if (options.useXstack) {
2300         if (bitVectBitValue(rsave,R0_IDX))
2301             pic16_emitcode("mov","b,r0");
2302         pic16_emitcode("mov","r0,%s",spname);
2303         for (i = 0 ; i < pic16_nRegs ; i++) {
2304             if (bitVectBitValue(rsave,i)) {
2305                 if (i == R0_IDX)
2306                     pic16_emitcode("mov","a,b");
2307                 else
2308                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2309                 pic16_emitcode("movx","@r0,a");
2310                 pic16_emitcode("inc","r0");
2311             }
2312         }
2313         pic16_emitcode("mov","%s,r0",spname);
2314         if (bitVectBitValue(rsave,R0_IDX))
2315             pic16_emitcode("mov","r0,b");           
2316     }// else
2317     //for (i = 0 ; i < pic16_nRegs ; i++) {
2318     //    if (bitVectBitValue(rsave,i))
2319     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2320     //}
2321
2322     dtype = operandType(IC_LEFT(ic));
2323     if (currFunc && dtype && 
2324         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2325         IFFUNC_ISISR(currFunc->type) &&
2326         !ic->bankSaved) 
2327
2328         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2329
2330 }
2331 /*-----------------------------------------------------------------*/
2332 /* unsaveRegisters - pop the pushed registers                      */
2333 /*-----------------------------------------------------------------*/
2334 static void unsaveRegisters (iCode *ic)
2335 {
2336     int i;
2337     bitVect *rsave;
2338
2339     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2340     /* find the registers in use at this time 
2341     and push them away to safety */
2342     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2343                           ic->rUsed);
2344     
2345     if (options.useXstack) {
2346         pic16_emitcode("mov","r0,%s",spname);   
2347         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2348             if (bitVectBitValue(rsave,i)) {
2349                 pic16_emitcode("dec","r0");
2350                 pic16_emitcode("movx","a,@r0");
2351                 if (i == R0_IDX)
2352                     pic16_emitcode("mov","b,a");
2353                 else
2354                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2355             }       
2356
2357         }
2358         pic16_emitcode("mov","%s,r0",spname);
2359         if (bitVectBitValue(rsave,R0_IDX))
2360             pic16_emitcode("mov","r0,b");
2361     } //else
2362     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2363     //    if (bitVectBitValue(rsave,i))
2364     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2365     //}
2366
2367 }  
2368
2369 #if 0  // patch 14
2370 /*-----------------------------------------------------------------*/
2371 /* pushSide -                                                      */
2372 /*-----------------------------------------------------------------*/
2373 static void pushSide(operand * oper, int size)
2374 {
2375         int offset = 0;
2376     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2377         while (size--) {
2378                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2379                 if (AOP_TYPE(oper) != AOP_REG &&
2380                     AOP_TYPE(oper) != AOP_DIR &&
2381                     strcmp(l,"a") ) {
2382                         pic16_emitcode("mov","a,%s",l);
2383                         pic16_emitcode("push","acc");
2384                 } else
2385                         pic16_emitcode("push","%s",l);
2386         }
2387 }
2388 #endif // patch 14
2389
2390 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2391 {
2392 //              (AOP(left)->aopu.pcop->type == PO_DIR)?
2393
2394         if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2395                 pic16_emitpcode(POC_MOVFW, src);
2396                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2397         } else {
2398                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2399                         src, pic16_popGet(AOP(op), offset)));
2400         }
2401 }
2402
2403
2404 /*-----------------------------------------------------------------*/
2405 /* assignResultValue - assign results to oper, rescall==1 is       */
2406 /*                     called from genCall() or genPCall()         */
2407 /*-----------------------------------------------------------------*/
2408 static void assignResultValue(operand * oper, int rescall)
2409 {
2410   int size = AOP_SIZE(oper);
2411
2412         DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2413         DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2414
2415         if(rescall) {
2416                 /* assign result from a call/pcall function() */
2417                 
2418                 /* function results are stored in a special order,
2419                  * see top of file with Function return policy, or manual */
2420
2421                 if(size <= 4) {
2422                         /* 8-bits, result in WREG */
2423                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2424                         
2425                         if(size>1) {
2426                                 /* 16-bits, result in PRODL:WREG */
2427                                 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2428 //                              pic16_emitpcode(POC_MOVFF,
2429 //                                      pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl), pic16_popGet(AOP(oper), 1)));
2430                         }
2431                         
2432                         if(size>2) {
2433                                 /* 24-bits, result in PRODH:PRODL:WREG */
2434                                 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2435
2436 //                              pic16_emitpcode(POC_MOVFF,
2437 //                                      pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodh), pic16_popGet(AOP(oper), 2)));
2438                         }
2439                         
2440                         if(size>3) {
2441                                 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2442                                 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2443
2444 //                              pic16_emitpcode(POC_MOVFF,
2445 //                                      pic16_popGet2p(pic16_popCopyReg(&pic16_pc_fsr0l), pic16_popGet(AOP(oper), 3)));
2446                         }
2447                 } else {
2448                         /* >32-bits, result on stack, and FSR0 points to beginning.
2449                          * Fix stack when done */
2450                          
2451                         while (size--) {
2452 //                              DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2453 //                              DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2454                 
2455                                 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2456                                 GpsuedoStkPtr++;
2457                         }
2458                         
2459                         /* fix stack */
2460                         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2461                         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2462                         if(STACK_MODEL_LARGE) {
2463                                 emitSKPNC;
2464                                 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2465                         }
2466                 }                       
2467         } else {        
2468                 if(!GpsuedoStkPtr) {
2469 //                      DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2470                         /* The last byte in the assignment is in W */
2471                         size--;
2472                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2473                         GpsuedoStkPtr++;
2474                 }
2475
2476                 while (size--) {
2477 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2478 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2479                 
2480                         popaopidx(AOP(oper), size, GpsuedoStkPtr);
2481                         GpsuedoStkPtr++;
2482
2483 #if 0
2484 #if STACK_SUPPORT
2485                 if(!USE_STACK)
2486                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2487 #else
2488                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2489 #endif
2490 #endif
2491
2492                 }
2493         }
2494                 
2495 }
2496
2497
2498 /*-----------------------------------------------------------------*/
2499 /* genIpush - genrate code for pushing this gets a little complex  */
2500 /*-----------------------------------------------------------------*/
2501 static void genIpush (iCode *ic)
2502 {
2503
2504   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2505 #if 0
2506     int size, offset = 0 ;
2507     char *l;
2508
2509
2510     /* if this is not a parm push : ie. it is spill push 
2511     and spill push is always done on the local stack */
2512     if (!ic->parmPush) {
2513
2514         /* and the item is spilt then do nothing */
2515         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2516             return ;
2517
2518         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2519         size = AOP_SIZE(IC_LEFT(ic));
2520         /* push it on the stack */
2521         while(size--) {
2522             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2523             if (*l == '#') {
2524                 MOVA(l);
2525                 l = "acc";
2526             }
2527             pic16_emitcode("push","%s",l);
2528         }
2529         return ;        
2530     }
2531
2532     /* this is a paramter push: in this case we call
2533     the routine to find the call and save those
2534     registers that need to be saved */   
2535     saveRegisters(ic);
2536
2537     /* then do the push */
2538     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2539
2540
2541         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2542     size = AOP_SIZE(IC_LEFT(ic));
2543
2544     while (size--) {
2545         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2546         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2547             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2548             strcmp(l,"a") ) {
2549             pic16_emitcode("mov","a,%s",l);
2550             pic16_emitcode("push","acc");
2551         } else
2552             pic16_emitcode("push","%s",l);
2553     }       
2554
2555     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2556 #endif
2557 }
2558
2559 /*-----------------------------------------------------------------*/
2560 /* genIpop - recover the registers: can happen only for spilling   */
2561 /*-----------------------------------------------------------------*/
2562 static void genIpop (iCode *ic)
2563 {
2564   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2565 #if 0
2566     int size,offset ;
2567
2568
2569     /* if the temp was not pushed then */
2570     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2571         return ;
2572
2573     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2574     size = AOP_SIZE(IC_LEFT(ic));
2575     offset = (size-1);
2576     while (size--) 
2577         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2578                                    FALSE,TRUE));
2579
2580     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2581 #endif
2582 }
2583
2584 /*-----------------------------------------------------------------*/
2585 /* unsaverbank - restores the resgister bank from stack            */
2586 /*-----------------------------------------------------------------*/
2587 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2588 {
2589   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2590 #if 0
2591     int i;
2592     asmop *aop ;
2593     regs *r = NULL;
2594
2595     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2596     if (popPsw) {
2597         if (options.useXstack) {
2598             aop = newAsmop(0);
2599             r = getFreePtr(ic,&aop,FALSE);
2600             
2601             
2602             pic16_emitcode("mov","%s,_spx",r->name);
2603             pic16_emitcode("movx","a,@%s",r->name);
2604             pic16_emitcode("mov","psw,a");
2605             pic16_emitcode("dec","%s",r->name);
2606             
2607         }else
2608             pic16_emitcode ("pop","psw");
2609     }
2610
2611     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2612         if (options.useXstack) {       
2613             pic16_emitcode("movx","a,@%s",r->name);
2614             //pic16_emitcode("mov","(%s+%d),a",
2615             //       regspic16[i].base,8*bank+regspic16[i].offset);
2616             pic16_emitcode("dec","%s",r->name);
2617
2618         } else 
2619           pic16_emitcode("pop",""); //"(%s+%d)",
2620         //regspic16[i].base,8*bank); //+regspic16[i].offset);
2621     }
2622
2623     if (options.useXstack) {
2624
2625         pic16_emitcode("mov","_spx,%s",r->name);
2626         pic16_freeAsmop(NULL,aop,ic,TRUE);
2627
2628     }
2629 #endif 
2630 }
2631
2632 /*-----------------------------------------------------------------*/
2633 /* saverbank - saves an entire register bank on the stack          */
2634 /*-----------------------------------------------------------------*/
2635 static void saverbank (int bank, iCode *ic, bool pushPsw)
2636 {
2637   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2638 #if 0
2639     int i;
2640     asmop *aop ;
2641     regs *r = NULL;
2642
2643     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2644     if (options.useXstack) {
2645
2646         aop = newAsmop(0);
2647         r = getFreePtr(ic,&aop,FALSE);  
2648         pic16_emitcode("mov","%s,_spx",r->name);
2649
2650     }
2651
2652     for (i = 0 ; i < pic16_nRegs ;i++) {
2653         if (options.useXstack) {
2654             pic16_emitcode("inc","%s",r->name);
2655             //pic16_emitcode("mov","a,(%s+%d)",
2656             //         regspic16[i].base,8*bank+regspic16[i].offset);
2657             pic16_emitcode("movx","@%s,a",r->name);           
2658         } else 
2659           pic16_emitcode("push","");// "(%s+%d)",
2660                      //regspic16[i].base,8*bank+regspic16[i].offset);
2661     }
2662     
2663     if (pushPsw) {
2664         if (options.useXstack) {
2665             pic16_emitcode("mov","a,psw");
2666             pic16_emitcode("movx","@%s,a",r->name);     
2667             pic16_emitcode("inc","%s",r->name);
2668             pic16_emitcode("mov","_spx,%s",r->name);       
2669             pic16_freeAsmop (NULL,aop,ic,TRUE);
2670             
2671         } else
2672             pic16_emitcode("push","psw");
2673         
2674         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2675     }
2676     ic->bankSaved = 1;
2677 #endif
2678 }
2679
2680
2681
2682 /*-----------------------------------------------------------------*/
2683 /* genCall - generates a call statement                            */
2684 /*-----------------------------------------------------------------*/
2685 static void genCall (iCode *ic)
2686 {
2687   sym_link *dtype;   
2688   int stackParms=0;
2689   
2690         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2691
2692         /* if caller saves & we have not saved then */
2693         if (!ic->regsSaved)
2694                 saveRegisters(ic);
2695
2696         /* if we are calling a function that is not using
2697          * the same register bank then we need to save the
2698          * destination registers on the stack */
2699         dtype = operandType(IC_LEFT(ic));
2700         if (currFunc && dtype && 
2701                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2702                 IFFUNC_ISISR(currFunc->type) &&
2703                 !ic->bankSaved) 
2704
2705                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2706
2707         /* if send set is not empty the assign */
2708         if (_G.sendSet) {
2709           iCode *sic;
2710
2711                 /* For the Pic port, there is no data stack.
2712                  * So parameters passed to functions are stored
2713                  * in registers. (The pCode optimizer will get
2714                  * rid of most of these :). */
2715
2716           int psuedoStkPtr=-1; 
2717           int firstTimeThruLoop = 1;
2718
2719                 _G.sendSet = reverseSet(_G.sendSet);
2720
2721                 /* First figure how many parameters are getting passed */
2722                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2723                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2724                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2725                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2726                 }
2727
2728                 stackParms = psuedoStkPtr;
2729
2730                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2731                   int size, offset = 0;
2732
2733                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2734                         size = AOP_SIZE(IC_LEFT(sic));
2735
2736                         while (size--) {
2737                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2738                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2739                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2740
2741                                 if(!firstTimeThruLoop) {
2742                                         /* If this is not the first time we've been through the loop
2743                                          * then we need to save the parameter in a temporary
2744                                          * register. The last byte of the last parameter is
2745                                          * passed in W. */
2746
2747                                         pushw();
2748                                         --psuedoStkPtr;         // sanity check
2749                                 }
2750                         
2751                                 firstTimeThruLoop=0;
2752
2753                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2754                                 offset++;
2755                         }
2756                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2757                 }
2758                 _G.sendSet = NULL;
2759         }
2760
2761         /* make the call */
2762         pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2763                         OP_SYMBOL(IC_LEFT(ic))->rname :
2764                         OP_SYMBOL(IC_LEFT(ic))->name));
2765
2766         GpsuedoStkPtr=0;
2767         /* if we need assign a result value */
2768         if ((IS_ITEMP(IC_RESULT(ic)) && 
2769                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2770                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2771                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2772
2773                 _G.accInUse++;
2774                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2775                 _G.accInUse--;
2776
2777                 assignResultValue(IC_RESULT(ic), 1);
2778
2779                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2780                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2781                 
2782                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2783         }
2784
2785         if(stackParms>0) {
2786                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2787                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2788                 if(STACK_MODEL_LARGE) {
2789                         emitSKPNC;
2790                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2791                 }
2792         }
2793
2794         /* adjust the stack for parameters if required */
2795 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2796
2797         if (ic->parmBytes) {
2798           int i;
2799
2800                 if (ic->parmBytes > 3) {
2801                         pic16_emitcode("mov","a,%s",spname);
2802                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2803                         pic16_emitcode("mov","%s,a",spname);
2804                 } else 
2805                         for ( i = 0 ; i <  ic->parmBytes ;i++)
2806                                 pic16_emitcode("dec","%s",spname);
2807         }
2808
2809         /* if register bank was saved then pop them */
2810         if (ic->bankSaved)
2811                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2812
2813         /* if we hade saved some registers then unsave them */
2814         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2815                 unsaveRegisters (ic);
2816 }
2817
2818
2819
2820 /*-----------------------------------------------------------------*/   // patch 14
2821 /* genPcall - generates a call by pointer statement                */
2822 /*-----------------------------------------------------------------*/
2823
2824 // new version, created from genCall
2825
2826 static void genPcall (iCode *ic)
2827 {
2828   sym_link *dtype;   
2829   int stackParms=0;
2830   symbol *retlbl = newiTempLabel(NULL);
2831   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
2832   
2833         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2834
2835         /* if caller saves & we have not saved then */
2836         if (!ic->regsSaved)
2837                 saveRegisters(ic);
2838
2839         /* if we are calling a function that is not using
2840          * the same register bank then we need to save the
2841          * destination registers on the stack */
2842         dtype = operandType(IC_LEFT(ic));
2843         if (currFunc && dtype && 
2844                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2845                 IFFUNC_ISISR(currFunc->type) &&
2846                 !ic->bankSaved) 
2847
2848                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2849
2850         /* if send set is not empty the assign */
2851         if (_G.sendSet) {
2852           iCode *sic;
2853
2854                 /* For the Pic port, there is no data stack.
2855                  * So parameters passed to functions are stored
2856                  * in registers. (The pCode optimizer will get
2857                  * rid of most of these :). */
2858
2859           int psuedoStkPtr=-1; 
2860           int firstTimeThruLoop = 1;
2861
2862                 _G.sendSet = reverseSet(_G.sendSet);
2863
2864                 /* First figure how many parameters are getting passed */
2865                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2866                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2867                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2868                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2869                 }
2870
2871                 stackParms = psuedoStkPtr;
2872
2873                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2874                   int size, offset = 0;
2875
2876                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2877                         size = AOP_SIZE(IC_LEFT(sic));
2878
2879                         while (size--) {
2880                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2881                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2882                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2883
2884                                 if(!firstTimeThruLoop) {
2885                                         /* If this is not the first time we've been through the loop
2886                                          * then we need to save the parameter in a temporary
2887                                          * register. The last byte of the last parameter is
2888                                          * passed in W. */
2889
2890                                         pushw();
2891                                         --psuedoStkPtr;         // sanity check
2892                                 }
2893                         
2894                                 firstTimeThruLoop=0;
2895
2896                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2897                                 offset++;
2898                         }
2899                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2900                 }
2901                 _G.sendSet = NULL;
2902         }
2903
2904         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2905
2906         // push return address
2907         // push $ on return stack, then replace with retlbl
2908
2909         // Note: retlbl is supplied as dummy operand to PUSH
2910         // This has the nice side effect of keeping the label from being optimized out :o)
2911         pic16_emitpcode(POC_PUSH, pic16_popGetLabel(retlbl->key));      
2912
2913         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
2914         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
2915         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
2916         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
2917         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
2918         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
2919
2920         /* make the call by writing the pointer into pc */
2921 // FIXME Disabled writes to PCLATU because of gpsim problems
2922 #if 0
2923         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
2924 #endif
2925         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
2926         // note: MOVFF to PCL not allowed
2927         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
2928         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
2929
2930         /* return address is here: (X) */
2931         pic16_emitpLabel(retlbl->key);
2932
2933         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2934
2935         GpsuedoStkPtr=0;
2936         /* if we need assign a result value */
2937         if ((IS_ITEMP(IC_RESULT(ic)) && 
2938                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2939                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2940                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2941
2942                 _G.accInUse++;
2943                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2944                 _G.accInUse--;
2945
2946                 assignResultValue(IC_RESULT(ic), 1);
2947
2948                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2949                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2950                 
2951                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2952         }
2953
2954         if(stackParms>0) {
2955                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2956                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2957                 if(STACK_MODEL_LARGE) {
2958                         emitSKPNC;
2959                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2960                 }
2961         }
2962
2963         /* adjust the stack for parameters if required */
2964 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2965
2966         if (ic->parmBytes) {
2967           int i;
2968
2969                 if (ic->parmBytes > 3) {
2970                         pic16_emitcode("mov","a,%s",spname);
2971                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2972                         pic16_emitcode("mov","%s,a",spname);
2973                 } else 
2974                         for ( i = 0 ; i <  ic->parmBytes ;i++)
2975                                 pic16_emitcode("dec","%s",spname);
2976         }
2977
2978         /* if register bank was saved then pop them */
2979         if (ic->bankSaved)
2980                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2981
2982         /* if we hade saved some registers then unsave them */
2983         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2984                 unsaveRegisters (ic);
2985 }
2986
2987
2988 #if 0                                                                           // patch 14
2989 // old version, kept for reference
2990
2991 /*-----------------------------------------------------------------*/
2992 /* genPcall - generates a call by pointer statement                */
2993 /*-----------------------------------------------------------------*/
2994 static void genPcall (iCode *ic)
2995 {
2996     sym_link *dtype;
2997     symbol *rlbl = newiTempLabel(NULL);
2998
2999
3000     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3001     /* if caller saves & we have not saved then */
3002     if (!ic->regsSaved)
3003         saveRegisters(ic);
3004
3005     /* if we are calling a function that is not using
3006     the same register bank then we need to save the
3007     destination registers on the stack */
3008     dtype = operandType(IC_LEFT(ic));
3009     if (currFunc && dtype && 
3010         IFFUNC_ISISR(currFunc->type) &&
3011         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3012         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3013
3014
3015     /* push the return address on to the stack */
3016     pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
3017     pic16_emitcode("push","acc");    
3018     pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
3019     pic16_emitcode("push","acc");
3020     
3021     if (options.model == MODEL_FLAT24)
3022     {
3023         pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
3024         pic16_emitcode("push","acc");    
3025     }
3026
3027     /* now push the calling address */
3028     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3029
3030     pushSide(IC_LEFT(ic), FPTRSIZE);
3031
3032     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
3033
3034     /* if send set is not empty the assign */
3035     if (_G.sendSet) {
3036         iCode *sic ;
3037
3038         for (sic = setFirstItem(_G.sendSet) ; sic ; 
3039              sic = setNextItem(_G.sendSet)) {
3040             int size, offset = 0;
3041             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3042             size = AOP_SIZE(IC_LEFT(sic));
3043             while (size--) {
3044                 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
3045                                 FALSE,FALSE);
3046                 if (strcmp(l,fReturn[offset]))
3047                     pic16_emitcode("mov","%s,%s",
3048                              fReturn[offset],
3049                              l);
3050                 offset++;
3051             }
3052             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3053         }
3054         _G.sendSet = NULL;
3055     }
3056
3057     pic16_emitcode("ret","");
3058     pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
3059
3060
3061     /* if we need assign a result value */
3062     if ((IS_ITEMP(IC_RESULT(ic)) &&
3063          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3064           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
3065         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3066
3067         _G.accInUse++;
3068         pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3069         _G.accInUse--;
3070         
3071         assignResultValue(IC_RESULT(ic), 1);
3072
3073         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3074     }
3075
3076     /* adjust the stack for parameters if 
3077     required */
3078     if (ic->parmBytes) {
3079         int i;
3080         if (ic->parmBytes > 3) {
3081             pic16_emitcode("mov","a,%s",spname);
3082             pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3083             pic16_emitcode("mov","%s,a",spname);
3084         } else 
3085             for ( i = 0 ; i <  ic->parmBytes ;i++)
3086                 pic16_emitcode("dec","%s",spname);
3087
3088     }
3089
3090     /* if register bank was saved then unsave them */
3091     if (currFunc && dtype && 
3092         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3093         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3094
3095     /* if we hade saved some registers then
3096     unsave them */
3097     if (ic->regsSaved)
3098         unsaveRegisters (ic);
3099
3100 }
3101 #endif                                                                          // patch 14
3102
3103
3104 /*-----------------------------------------------------------------*/
3105 /* resultRemat - result  is rematerializable                       */
3106 /*-----------------------------------------------------------------*/
3107 static int resultRemat (iCode *ic)
3108 {
3109   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3110   if (SKIP_IC(ic) || ic->op == IFX)
3111     return 0;
3112
3113   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3114     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3115     if (sym->remat && !POINTER_SET(ic)) 
3116       return 1;
3117   }
3118
3119   return 0;
3120 }
3121
3122 #if defined(__BORLANDC__) || defined(_MSC_VER)
3123 #define STRCASECMP stricmp
3124 #else
3125 #define STRCASECMP strcasecmp
3126 #endif
3127
3128 #if 0
3129 /*-----------------------------------------------------------------*/
3130 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3131 /*-----------------------------------------------------------------*/
3132 static bool inExcludeList(char *s)
3133 {
3134   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3135     int i =0;
3136     
3137     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3138     if (options.excludeRegs[i] &&
3139     STRCASECMP(options.excludeRegs[i],"none") == 0)
3140         return FALSE ;
3141
3142     for ( i = 0 ; options.excludeRegs[i]; i++) {
3143         if (options.excludeRegs[i] &&
3144         STRCASECMP(s,options.excludeRegs[i]) == 0)
3145             return TRUE;
3146     }
3147     return FALSE ;
3148 }
3149 #endif
3150
3151 /*-----------------------------------------------------------------*/
3152 /* genFunction - generated code for function entry                 */
3153 /*-----------------------------------------------------------------*/
3154 static void genFunction (iCode *ic)
3155 {
3156   symbol *sym;
3157   sym_link *ftype;
3158
3159         DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
3160
3161         labelOffset += (max_key+4);
3162         max_key=0;
3163         GpsuedoStkPtr=0;
3164         _G.nRegsSaved = 0;
3165
3166         ftype = operandType(IC_LEFT(ic));
3167         sym = OP_SYMBOL(IC_LEFT(ic));
3168
3169         if(/*!IFFUNC_ISNAKED(ftype) &&*/ IFFUNC_ISISR(ftype)) {
3170                 /* create an absolute section at the interrupt vector:
3171                  * that is 0x0008 for interrupt 1, 0x0018 interrupt 2 */
3172           int ivec;
3173           symbol *asym;
3174           char asymname[128];
3175           
3176                 {
3177                   int i, found=-1;
3178
3179                         sym = OP_SYMBOL( IC_LEFT(ic));
3180                         for(i=0;i<=2;i++) {
3181 //                              fprintf(stderr, "comparing name int %d\t%s with %s\n",
3182 //                                              i, interrupts[i]->name, sym->name);
3183                                 if(interrupts[i]->name
3184                                         && !STRCASECMP(interrupts[i]->name, sym->name)) {
3185                                         found = i;
3186                                         break;
3187                                 }
3188                         }
3189                         
3190                         if(found == -1) {
3191                                 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3192                                         __FILE__, __LINE__, sym->name);
3193                                 exit(-1);
3194                         }
3195                         ivec = found;
3196                 }
3197                 sprintf(asymname, "ivec_%d_%s", ivec, sym->name);
3198                 asym = newSymbol(asymname, 0);
3199                 pic16_emitcode(";","-----------------------------------------");
3200                 pic16_emitcode(";"," interrupt vector %d for function %s", ivec, sym->name);
3201                 pic16_emitcode(";","-----------------------------------------");
3202
3203                 pic16_addpCode2pBlock(pb, pic16_newpCodeFunction(moduleName, asym->name));
3204                 pic16_pBlockConvert2Absolute(pb);
3205
3206                 pic16_emitpcode(POC_GOTO, pic16_popGetWithString( sym->rname ));
3207                 
3208                 /* mark the end of this tiny function */
3209                 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3210
3211                 {
3212                   absSym *abSym;
3213
3214                         abSym = Safe_calloc(1, sizeof(absSym));
3215                         abSym->name = Safe_strdup( asymname );
3216
3217                         switch( ivec ) {
3218                                 case 0: abSym->address = 0x000000; break;
3219                                 case 1: abSym->address = 0x000008; break;
3220                                 case 2: abSym->address = 0x000018; break;
3221                         }
3222
3223                         addSet(&absSymSet, abSym);
3224                 }
3225         }
3226
3227
3228         /* create the function header */
3229         pic16_emitcode(";","-----------------------------------------");
3230         pic16_emitcode(";"," function %s",sym->name);
3231         pic16_emitcode(";","-----------------------------------------");
3232
3233         pic16_emitcode("","%s:",sym->rname);
3234         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3235
3236         {
3237           absSym *ab;
3238
3239                 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
3240                         if(!strcmp(ab->name, sym->name)) {
3241                                 pic16_pBlockConvert2Absolute(pb);
3242                                 break;
3243                         }
3244                 
3245         }
3246
3247
3248         if(IFFUNC_ISNAKED(ftype)) {
3249                 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3250                 return;
3251         }
3252         
3253         /* if critical function then turn interrupts off */
3254         if (IFFUNC_ISCRITICAL(ftype))
3255                 pic16_emitcode("clr","ea");
3256
3257         /* if this is an interrupt service routine then
3258          * save acc, b, dpl, dph  */
3259         if (IFFUNC_ISISR(sym->type)) {
3260           int i;
3261                 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3262                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3263                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3264                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3265                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3266                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3267                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3268                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3269
3270                 pic16_pBlockConvert2ISR(pb);
3271                 
3272                 /* if any registers used */
3273                 if (sym->regsUsed) {
3274                         /* save the registers used */
3275                         DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3276                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3277                                 if (bitVectBitValue(sym->regsUsed,i)) {
3278 //                                      fprintf(stderr, "%s:%d function %s uses register %s\n",
3279 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3280 //                                                      pic16_regWithIdx(i)->name);
3281
3282                                         pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3283                                         _G.nRegsSaved++;
3284                                 }
3285                         }
3286                 }
3287         } else {
3288                 /* emit code to setup stack frame if user enabled,
3289                  * and function is not main() */
3290          
3291 //              fprintf(stderr, "function name: %s\n", sym->name);
3292                 if(strcmp(sym->name, "main")) {
3293                         if(!options.ommitFramePtr || sym->regsUsed) {
3294                         /* setup the stack frame */
3295                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3296                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3297                                 if(STACK_MODEL_LARGE)
3298                                         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3299                         }
3300                 }
3301
3302                 /* if callee-save to be used for this function
3303                 * then save the registers being used in this function */
3304                 if (IFFUNC_CALLEESAVES(sym->type)) {
3305                   int i;
3306             
3307 //                      fprintf(stderr, "%s:%d function sym->regsUsed= %p\n", __FILE__, __LINE__, sym->regsUsed);
3308                         
3309                         /* if any registers used */
3310                         if (sym->regsUsed) {
3311                                 /* save the registers used */
3312                                 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3313                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3314                                         if (bitVectBitValue(sym->regsUsed,i)) {
3315 //                                              fprintf(stderr, "%s:%d function %s uses register %s\n",
3316 //                                                              __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3317 //                                                              pic16_regWithIdx(i)->name);
3318
3319                                                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3320 //                                              pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3321 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
3322 //                                                      &pic16_pc_postdec1, 0));
3323                                                 _G.nRegsSaved++;
3324                                         }
3325                                 }
3326                         }
3327                 }
3328         }
3329
3330
3331         
3332 #if 0
3333         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3334
3335                 if (options.useXstack) {
3336                         pic16_emitcode("mov","r0,%s",spname);
3337                         pic16_emitcode("mov","a,_bp");
3338                         pic16_emitcode("movx","@r0,a");
3339                         pic16_emitcode("inc","%s",spname);
3340                 } else {
3341                         /* set up the stack */
3342                         pic16_emitcode ("push","_bp");     /* save the callers stack  */
3343                 }
3344                 pic16_emitcode ("mov","_bp,%s",spname);
3345         }
3346 #endif
3347         DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3348
3349         /* adjust the stack for the function */
3350         if (sym->stack) {
3351           int i = sym->stack;
3352
3353                 if (i > 127 ) 
3354                         werror(W_STACK_OVERFLOW,sym->name);
3355
3356                 if (i > 3 && sym->recvSize < 4) {              
3357                         pic16_emitcode ("mov","a,sp");
3358                         pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3359                         pic16_emitcode ("mov","sp,a");
3360                 } else
3361                         while(i--)
3362                                 pic16_emitcode("inc","sp");
3363         }
3364
3365         if (sym->xstack) {
3366                 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3367
3368                 pic16_emitcode ("mov","a,_spx");
3369                 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3370                 pic16_emitcode ("mov","_spx,a");
3371         }
3372     
3373 }
3374
3375 /*-----------------------------------------------------------------*/
3376 /* genEndFunction - generates epilogue for functions               */
3377 /*-----------------------------------------------------------------*/
3378 static void genEndFunction (iCode *ic)
3379 {
3380     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3381
3382     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3383
3384     if(IFFUNC_ISNAKED(sym->type)) {
3385         DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3386         return;
3387     }
3388
3389 #if 0
3390     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3391     {
3392         pic16_emitcode ("mov","%s,_bp",spname);
3393     }
3394 #endif
3395
3396     /* if use external stack but some variables were
3397     added to the local stack then decrement the
3398     local stack */
3399     if (options.useXstack && sym->stack) {      
3400         pic16_emitcode("mov","a,sp");
3401         pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3402         pic16_emitcode("mov","sp,a");
3403     }
3404
3405
3406 #if 0
3407     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3408         if (options.useXstack) {
3409             pic16_emitcode("mov","r0,%s",spname);
3410             pic16_emitcode("movx","a,@r0");
3411             pic16_emitcode("mov","_bp,a");
3412             pic16_emitcode("dec","%s",spname);
3413         }
3414         else
3415         {
3416             pic16_emitcode ("pop","_bp");
3417         }
3418     }
3419 #endif
3420
3421     /* restore the register bank  */    
3422     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3423         pic16_emitcode ("pop","psw");
3424
3425         if (IFFUNC_ISISR(sym->type)) {
3426
3427                 /* now we need to restore the registers */
3428                 
3429                 /* if any registers used */
3430                 if (sym->regsUsed) {
3431                   int i;
3432
3433                         /* restore registers used */
3434                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3435                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3436                                 if (bitVectBitValue(sym->regsUsed,i)) {
3437 //                                      fprintf(stderr, "%s:%d function %s uses register %s\n",
3438 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3439 //                                                      pic16_regWithIdx(i)->name);
3440         
3441                                         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3442                                                         &pic16_pc_preinc1,
3443                                                         PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3444                                 }
3445                         }
3446                 }
3447         
3448                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3449                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3450                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3451                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3452                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3453                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3454                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3455         
3456
3457                 /* if debug then send end of function */
3458 /*      if (options.debug && currFunc)  */
3459                 if (currFunc) {
3460                         _G.debugLine = 1;
3461                         pic16_emitcode(";","C$%s$%d$%d$%d ==.",
3462                                         FileBaseName(ic->filename),currFunc->lastLine,
3463                                         ic->level,ic->block); 
3464                         if (IS_STATIC(currFunc->etype))     
3465                                 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
3466                         else
3467                                 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
3468                         _G.debugLine = 0;
3469                 }
3470         
3471 #if 0
3472                 pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_status));
3473                 pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_ssave));
3474                 pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_status));
3475                 pic16_emitpcode(POC_SWAPF,  pic16_popCopyReg(&pic16_pc_wsave));
3476                 pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_wsave));
3477 #endif
3478
3479                 pic16_emitpcodeNULLop(POC_RETFIE);
3480         }
3481         else {
3482                 if (IFFUNC_ISCRITICAL(sym->type))
3483                         pic16_emitcode("setb","ea");
3484         
3485         /* if any registers used */
3486         if (sym->regsUsed) {
3487           int i;
3488                 /* save the registers used */
3489                 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3490                 for ( i = sym->regsUsed->size; i >= 0; i--) {
3491                         if (bitVectBitValue(sym->regsUsed,i)) {
3492 //                              fprintf(stderr, "%s:%d function %s uses register %s\n",
3493 //                                              __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3494 //                                              pic16_regWithIdx(i)->name);
3495         
3496                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3497                                         &pic16_pc_preinc1,
3498                                         PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3499                         }
3500                 }
3501         }
3502         
3503
3504         /* if debug then send end of function */
3505         if (currFunc) {
3506             _G.debugLine = 1;
3507             pic16_emitcode(";","C$%s$%d$%d$%d ==.",
3508                      FileBaseName(ic->filename),currFunc->lastLine,
3509                      ic->level,ic->block); 
3510             if (IS_STATIC(currFunc->etype))         
3511                 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
3512             else
3513                 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
3514             _G.debugLine = 0;
3515         }
3516
3517         /* insert code to restore stack frame, if user enabled it
3518          * and function is not main() */
3519          
3520         if(strcmp(sym->name, "main")) {
3521                 if(!options.ommitFramePtr || sym->regsUsed) {
3522                         /* restore stack frame */
3523                         if(STACK_MODEL_LARGE)
3524                                 pic16_emitpcode(POC_MOVFF,
3525                                         pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3526                         pic16_emitpcode(POC_MOVFF,
3527                                         pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3528                 }
3529         }
3530
3531         pic16_emitcode ("return","");
3532         pic16_emitpcodeNULLop(POC_RETURN);
3533
3534         /* Mark the end of a function */
3535         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3536     }
3537
3538 }
3539
3540
3541 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3542 {
3543 //              (AOP(left)->aopu.pcop->type == PO_DIR)?
3544
3545         if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
3546                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12
3547                 pic16_emitpcode(POC_MOVWF, dest);
3548         } else {
3549                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3550                         pic16_popGet(AOP(op), offset), dest));
3551         }
3552 }
3553
3554 /*-----------------------------------------------------------------*/
3555 /* genRet - generate code for return statement                     */
3556 /*-----------------------------------------------------------------*/
3557 static void genRet (iCode *ic)
3558 {
3559   int size;
3560   operand *left;
3561
3562         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3563         /* if we have no return value then
3564          * just generate the "ret" */
3565         
3566         if (!IC_LEFT(ic)) 
3567                 goto jumpret;       
3568     
3569         /* we have something to return then
3570          * move the return value into place */
3571         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3572         size = AOP_SIZE(IC_LEFT(ic));
3573
3574         if(size <= 4) {
3575                 if(size>3) {
3576                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3577 //                      pic16_emitpcode(POC_MOVFF,
3578 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3579                 }
3580                 if(size>2) {
3581                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3582 //                      pic16_emitpcode(POC_MOVFF,
3583 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3584                 }
3585                 if(size>1) {
3586                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3587 //                      pic16_emitpcode(POC_MOVFF,
3588 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3589                 }
3590
3591 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3592
3593                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3594 //              pic16_emitpcode(POC_MOVFF,
3595 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3596
3597         } else {
3598                 /* >32-bits, setup stack and FSR0 */
3599                 while (size--) {
3600 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3601 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3602
3603                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3604
3605 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3606                         GpsuedoStkPtr++;
3607                 }
3608                         
3609                 /* setup FSR0 */
3610                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3611                         pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3612
3613                 if(STACK_MODEL_LARGE) {
3614                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3615                                 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3616                 } else {
3617                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3618                 }
3619         }
3620                                 
3621 #if 0
3622         /* old code, left here for reference -- VR */    
3623         while (size--) {
3624           char *l ;
3625
3626                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3627                         /* #NOCHANGE */
3628                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3629                         pic16_emitpcomment("push %s",l);
3630                         pushed++;
3631                 } else {
3632                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3633                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3634                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3635                         
3636                         if (strcmp(fReturn[offset],l)) {
3637                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3638                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3639                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3640                                 } else {
3641                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3642                                 }
3643                                 
3644                                 if(size) {
3645                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3646                                 }
3647                                 offset++;
3648                         }
3649                 }
3650         }    
3651
3652         if (pushed) {
3653                 while(pushed) {
3654                         pushed--;
3655                         if (strcmp(fReturn[pushed],"a"))
3656                                 pic16_emitcode("pop",fReturn[pushed]);
3657                         else
3658                                 pic16_emitcode("pop","acc");
3659                 }
3660         }
3661 #endif
3662
3663
3664         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3665     
3666 jumpret:
3667         /* generate a jump to the return label
3668          * if the next is not the return statement */
3669         if (!(ic->next && ic->next->op == LABEL
3670                 && IC_LABEL(ic->next) == returnLabel)) {
3671         
3672                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3673                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3674         }
3675 }
3676
3677 /*-----------------------------------------------------------------*/
3678 /* genLabel - generates a label                                    */
3679 /*-----------------------------------------------------------------*/
3680 static void genLabel (iCode *ic)
3681 {
3682     /* special case never generate */
3683     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3684     if (IC_LABEL(ic) == entryLabel)
3685         return ;
3686
3687     pic16_emitpLabel(IC_LABEL(ic)->key);
3688     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3689 }
3690
3691 /*-----------------------------------------------------------------*/
3692 /* genGoto - generates a goto                                      */
3693 /*-----------------------------------------------------------------*/
3694 //tsd
3695 static void genGoto (iCode *ic)
3696 {
3697   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3698   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3699 }
3700
3701
3702 /*-----------------------------------------------------------------*/
3703 /* genMultbits :- multiplication of bits                           */
3704 /*-----------------------------------------------------------------*/
3705 static void genMultbits (operand *left, 
3706                          operand *right, 
3707                          operand *result)
3708 {
3709   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3710
3711   if(!pic16_sameRegs(AOP(result),AOP(right)))
3712     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3713
3714   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3715   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3716   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3717
3718 }
3719
3720
3721 /*-----------------------------------------------------------------*/
3722 /* genMultOneByte : 8 bit multiplication & division                */
3723 /*-----------------------------------------------------------------*/
3724 static void genMultOneByte (operand *left,
3725                             operand *right,
3726                             operand *result)
3727 {
3728   sym_link *opetype = operandType(result);
3729
3730   // symbol *lbl ;
3731   int size,offset;
3732
3733   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3734   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3735   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3736
3737   /* (if two literals, the value is computed before) */
3738   /* if one literal, literal on the right */
3739   if (AOP_TYPE(left) == AOP_LIT){
3740     operand *t = right;
3741     right = left;
3742     left = t;
3743   }
3744
3745   size = AOP_SIZE(result);
3746   if(size == 1) {
3747
3748     if (AOP_TYPE(right) == AOP_LIT){
3749       pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3750                      pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3751                      pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3752                      pic16_aopGet(AOP(result),0,FALSE,FALSE));
3753     } else {
3754       pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3755                      pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3756                      pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3757                      pic16_aopGet(AOP(result),0,FALSE,FALSE));
3758     }
3759     pic16_genMult8X8_8 (left, right,result);
3760   } else {  // (size > 1)
3761
3762     pic16_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3763                    pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3764                    pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3765                    pic16_aopGet(AOP(result),0,FALSE,FALSE));
3766
3767     if (SPEC_USIGN(opetype)){
3768       pic16_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3769       pic16_genUMult8X8_16 (left, right, result, NULL);
3770
3771       if (size > 2) {
3772         /* for filling the MSBs */
3773         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),2));
3774         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),3));
3775       }
3776     }
3777     else{
3778       pic16_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3779
3780       pic16_emitcode("mov","a,b");
3781
3782       /* adjust the MSB if left or right neg */
3783
3784       /* if one literal */
3785       if (AOP_TYPE(right) == AOP_LIT){
3786         pic16_emitcode("multiply ","right is a lit");
3787         /* AND literal negative */
3788         if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3789           /* adjust MSB (c==0 after mul) */
3790           pic16_emitcode("subb","a,%s", pic16_aopGet(AOP(left),0,FALSE,FALSE));
3791         }
3792       }
3793       else{
3794         pic16_genSMult8X8_16 (left, right, result, NULL);
3795       }
3796
3797       if(size > 2){
3798         pic16_emitcode("multiply ","size is greater than 2, so propogate sign");
3799         /* get the sign */
3800         pic16_emitcode("rlc","a");
3801         pic16_emitcode("subb","a,acc");
3802       }
3803     }
3804
3805     size -= 2;   
3806     offset = 2;
3807     if (size > 0)
3808       while (size--)
3809         pic16_emitcode("multiply ","size is way greater than 2, so propogate sign");
3810     //pic16_aopPut(AOP(result),"a",offset++);
3811   }
3812 }
3813
3814 /*-----------------------------------------------------------------*/
3815 /* genMult - generates code for multiplication                     */
3816 /*-----------------------------------------------------------------*/
3817 static void genMult (iCode *ic)
3818 {
3819     operand *left = IC_LEFT(ic);
3820     operand *right = IC_RIGHT(ic);
3821     operand *result= IC_RESULT(ic);   
3822
3823     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3824     /* assign the amsops */
3825     pic16_aopOp (left,ic,FALSE);
3826     pic16_aopOp (right,ic,FALSE);
3827     pic16_aopOp (result,ic,TRUE);
3828
3829   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3830
3831     /* special cases first */
3832     /* both are bits */
3833     if (AOP_TYPE(left) == AOP_CRY &&
3834         AOP_TYPE(right)== AOP_CRY) {
3835         genMultbits(left,right,result);
3836         goto release ;
3837     }
3838
3839     /* if both are of size == 1 */
3840     if (AOP_SIZE(left) == 1 &&
3841         AOP_SIZE(right) == 1 ) {
3842         genMultOneByte(left,right,result);
3843         goto release ;
3844     }
3845
3846     pic16_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3847
3848     /* should have been converted to function call */
3849         assert(0) ;
3850
3851 release :
3852     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3853     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3854     pic16_freeAsmop(result,NULL,ic,TRUE); 
3855 }
3856
3857 /*-----------------------------------------------------------------*/
3858 /* genDivbits :- division of bits                                  */
3859 /*-----------------------------------------------------------------*/
3860 static void genDivbits (operand *left, 
3861                         operand *right, 
3862                         operand *result)
3863 {
3864
3865     char *l;
3866
3867     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3868     /* the result must be bit */    
3869     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3870     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3871
3872     MOVA(l);    
3873
3874     pic16_emitcode("div","ab");
3875     pic16_emitcode("rrc","a");
3876     pic16_aopPut(AOP(result),"c",0);
3877 }
3878
3879 /*-----------------------------------------------------------------*/
3880 /* genDivOneByte : 8 bit division                                  */
3881 /*-----------------------------------------------------------------*/
3882 static void genDivOneByte (operand *left,
3883                            operand *right,
3884                            operand *result)
3885 {
3886     sym_link *opetype = operandType(result);
3887     char *l ;
3888     symbol *lbl ;
3889     int size,offset;
3890
3891     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3892     size = AOP_SIZE(result) - 1;
3893     offset = 1;
3894     /* signed or unsigned */
3895     if (SPEC_USIGN(opetype)) {
3896         /* unsigned is easy */
3897         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3898         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3899         MOVA(l);        
3900         pic16_emitcode("div","ab");
3901         pic16_aopPut(AOP(result),"a",0);
3902         while (size--)
3903             pic16_aopPut(AOP(result),zero,offset++);
3904         return ;
3905     }
3906
3907     /* signed is a little bit more difficult */
3908
3909     /* save the signs of the operands */
3910     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3911     MOVA(l);    
3912     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
3913     pic16_emitcode("push","acc"); /* save it on the stack */
3914
3915     /* now sign adjust for both left & right */
3916     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
3917     MOVA(l);       
3918     lbl = newiTempLabel(NULL);
3919     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3920     pic16_emitcode("cpl","a");   
3921     pic16_emitcode("inc","a");
3922     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3923     pic16_emitcode("mov","b,a");
3924
3925     /* sign adjust left side */
3926     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3927     MOVA(l);
3928
3929     lbl = newiTempLabel(NULL);
3930     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3931     pic16_emitcode("cpl","a");
3932     pic16_emitcode("inc","a");
3933     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3934
3935     /* now the division */
3936     pic16_emitcode("div","ab");
3937     /* we are interested in the lower order
3938     only */
3939     pic16_emitcode("mov","b,a");
3940     lbl = newiTempLabel(NULL);
3941     pic16_emitcode("pop","acc");   
3942     /* if there was an over flow we don't 
3943     adjust the sign of the result */
3944     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3945     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3946     CLRC;
3947     pic16_emitcode("clr","a");
3948     pic16_emitcode("subb","a,b");
3949     pic16_emitcode("mov","b,a");
3950     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3951
3952     /* now we are done */
3953     pic16_aopPut(AOP(result),"b",0);
3954     if(size > 0){
3955         pic16_emitcode("mov","c,b.7");
3956         pic16_emitcode("subb","a,acc");   
3957     }
3958     while (size--)
3959         pic16_aopPut(AOP(result),"a",offset++);
3960
3961 }
3962
3963 /*-----------------------------------------------------------------*/
3964 /* genDiv - generates code for division                            */
3965 /*-----------------------------------------------------------------*/
3966 static void genDiv (iCode *ic)
3967 {
3968     operand *left = IC_LEFT(ic);
3969     operand *right = IC_RIGHT(ic);
3970     operand *result= IC_RESULT(ic);   
3971
3972     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3973     /* assign the amsops */
3974     pic16_aopOp (left,ic,FALSE);
3975     pic16_aopOp (right,ic,FALSE);
3976     pic16_aopOp (result,ic,TRUE);
3977
3978     /* special cases first */
3979     /* both are bits */
3980     if (AOP_TYPE(left) == AOP_CRY &&
3981         AOP_TYPE(right)== AOP_CRY) {
3982         genDivbits(left,right,result);
3983         goto release ;
3984     }
3985
3986     /* if both are of size == 1 */
3987     if (AOP_SIZE(left) == 1 &&
3988         AOP_SIZE(right) == 1 ) {
3989         genDivOneByte(left,right,result);
3990         goto release ;
3991     }
3992
3993     /* should have been converted to function call */
3994     assert(0);
3995 release :
3996     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3997     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3998     pic16_freeAsmop(result,NULL,ic,TRUE); 
3999 }
4000
4001 /*-----------------------------------------------------------------*/
4002 /* genModbits :- modulus of bits                                   */
4003 /*-----------------------------------------------------------------*/
4004 static void genModbits (operand *left, 
4005                         operand *right, 
4006                         operand *result)
4007 {
4008
4009     char *l;
4010
4011     /* the result must be bit */    
4012     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4013     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4014
4015     MOVA(l);       
4016
4017     pic16_emitcode("div","ab");
4018     pic16_emitcode("mov","a,b");
4019     pic16_emitcode("rrc","a");
4020     pic16_aopPut(AOP(result),"c",0);
4021 }
4022
4023 /*-----------------------------------------------------------------*/
4024 /* genModOneByte : 8 bit modulus                                   */
4025 /*-----------------------------------------------------------------*/
4026 static void genModOneByte (operand *left,
4027                            operand *right,
4028                            operand *result)
4029 {
4030     sym_link *opetype = operandType(result);
4031     char *l ;
4032     symbol *lbl ;
4033
4034     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4035     /* signed or unsigned */
4036     if (SPEC_USIGN(opetype)) {
4037         /* unsigned is easy */
4038         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4039         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4040         MOVA(l);    
4041         pic16_emitcode("div","ab");
4042         pic16_aopPut(AOP(result),"b",0);
4043         return ;
4044     }
4045
4046     /* signed is a little bit more difficult */
4047
4048     /* save the signs of the operands */
4049     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4050     MOVA(l);
4051
4052     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4053     pic16_emitcode("push","acc"); /* save it on the stack */
4054
4055     /* now sign adjust for both left & right */
4056     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4057     MOVA(l);
4058
4059     lbl = newiTempLabel(NULL);
4060     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4061     pic16_emitcode("cpl","a");   
4062     pic16_emitcode("inc","a");
4063     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4064     pic16_emitcode("mov","b,a"); 
4065
4066     /* sign adjust left side */
4067     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4068     MOVA(l);
4069
4070     lbl = newiTempLabel(NULL);
4071     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4072     pic16_emitcode("cpl","a");   
4073     pic16_emitcode("inc","a");
4074     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4075
4076     /* now the multiplication */
4077     pic16_emitcode("div","ab");
4078     /* we are interested in the lower order
4079     only */
4080     lbl = newiTempLabel(NULL);
4081     pic16_emitcode("pop","acc");   
4082     /* if there was an over flow we don't 
4083     adjust the sign of the result */
4084     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4085     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4086     CLRC ;
4087     pic16_emitcode("clr","a");
4088     pic16_emitcode("subb","a,b");
4089     pic16_emitcode("mov","b,a");
4090     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4091
4092     /* now we are done */
4093     pic16_aopPut(AOP(result),"b",0);
4094
4095 }
4096
4097 /*-----------------------------------------------------------------*/
4098 /* genMod - generates code for division                            */
4099 /*-----------------------------------------------------------------*/
4100 static void genMod (iCode *ic)
4101 {
4102     operand *left = IC_LEFT(ic);
4103     operand *right = IC_RIGHT(ic);
4104     operand *result= IC_RESULT(ic);  
4105
4106     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4107     /* assign the amsops */
4108     pic16_aopOp (left,ic,FALSE);
4109     pic16_aopOp (right,ic,FALSE);
4110     pic16_aopOp (result,ic,TRUE);
4111
4112     /* special cases first */
4113     /* both are bits */
4114     if (AOP_TYPE(left) == AOP_CRY &&
4115         AOP_TYPE(right)== AOP_CRY) {
4116         genModbits(left,right,result);
4117         goto release ;
4118     }
4119
4120     /* if both are of size == 1 */
4121     if (AOP_SIZE(left) == 1 &&
4122         AOP_SIZE(right) == 1 ) {
4123         genModOneByte(left,right,result);
4124         goto release ;
4125     }
4126
4127     /* should have been converted to function call */
4128     assert(0);
4129
4130 release :
4131     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4132     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4133     pic16_freeAsmop(result,NULL,ic,TRUE); 
4134 }
4135
4136 /*-----------------------------------------------------------------*/
4137 /* genIfxJump :- will create a jump depending on the ifx           */
4138 /*-----------------------------------------------------------------*/
4139 /*
4140   note: May need to add parameter to indicate when a variable is in bit space.
4141 */
4142 static void genIfxJump (iCode *ic, char *jval)
4143 {
4144
4145     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4146     /* if true label then we jump if condition
4147     supplied is true */
4148     if ( IC_TRUE(ic) ) {
4149
4150         if(strcmp(jval,"a") == 0)
4151           emitSKPZ;
4152         else if (strcmp(jval,"c") == 0)
4153           emitSKPC;
4154         else {
4155           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4156           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1));
4157         }
4158
4159         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4160         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
4161
4162     }
4163     else {
4164         /* false label is present */
4165         if(strcmp(jval,"a") == 0)
4166           emitSKPNZ;
4167         else if (strcmp(jval,"c") == 0)
4168           emitSKPNC;
4169         else {
4170           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4171           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1));
4172         }
4173
4174         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4175         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
4176
4177     }
4178
4179
4180     /* mark the icode as generated */
4181     ic->generated = 1;
4182 }
4183
4184 /*-----------------------------------------------------------------*/
4185 /* genSkip                                                         */
4186 /*-----------------------------------------------------------------*/
4187 static void genSkip(iCode *ifx,int status_bit)
4188 {
4189   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4190   if(!ifx)
4191     return;
4192
4193   if ( IC_TRUE(ifx) ) {
4194     switch(status_bit) {
4195     case 'z':
4196       emitSKPNZ;
4197       break;
4198
4199     case 'c':
4200       emitSKPNC;
4201       break;
4202
4203     case 'd':
4204       emitSKPDC;
4205       break;
4206
4207     }
4208
4209     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4210     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4211
4212   } else {
4213
4214     switch(status_bit) {
4215
4216     case 'z':
4217       emitSKPZ;
4218       break;
4219
4220     case 'c':
4221       emitSKPC;
4222       break;
4223
4224     case 'd':
4225       emitSKPDC;
4226       break;
4227     }
4228     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4229     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4230
4231   }
4232
4233 }
4234
4235 /*-----------------------------------------------------------------*/
4236 /* genSkipc                                                        */
4237 /*-----------------------------------------------------------------*/
4238 static void genSkipc(resolvedIfx *rifx)
4239 {
4240   if(!rifx)
4241     return;
4242
4243   if(rifx->condition)
4244     emitSKPC;
4245   else
4246     emitSKPNC;
4247
4248   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4249   rifx->generated = 1;
4250 }
4251
4252 /*-----------------------------------------------------------------*/
4253 /* genSkipz2                                                       */
4254 /*-----------------------------------------------------------------*/
4255 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4256 {
4257   if(!rifx)
4258     return;
4259
4260   if( (rifx->condition ^ invert_condition) & 1)
4261     emitSKPZ;
4262   else
4263     emitSKPNZ;
4264
4265   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4266   rifx->generated = 1;
4267 }
4268
4269 #if 0
4270 /*-----------------------------------------------------------------*/
4271 /* genSkipz                                                        */
4272 /*-----------------------------------------------------------------*/
4273 static void genSkipz(iCode *ifx, int condition)
4274 {
4275   if(!ifx)
4276     return;
4277
4278   if(condition)
4279     emitSKPNZ;
4280   else
4281     emitSKPZ;
4282
4283   if ( IC_TRUE(ifx) )
4284     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4285   else
4286     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4287
4288   if ( IC_TRUE(ifx) )
4289     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4290   else
4291     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4292
4293 }
4294 #endif
4295
4296 /*-----------------------------------------------------------------*/
4297 /* genSkipCond                                                     */
4298 /*-----------------------------------------------------------------*/
4299 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4300 {
4301   if(!rifx)
4302     return;
4303
4304   if(rifx->condition)
4305     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4306   else
4307     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4308
4309
4310   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4311   rifx->generated = 1;
4312 }
4313
4314 #if 0
4315 /*-----------------------------------------------------------------*/
4316 /* genChkZeroes :- greater or less than comparison                 */
4317 /*     For each byte in a literal that is zero, inclusive or the   */
4318 /*     the corresponding byte in the operand with W                */
4319 /*     returns true if any of the bytes are zero                   */
4320 /*-----------------------------------------------------------------*/
4321 static int genChkZeroes(operand *op, int lit,  int size)
4322 {
4323
4324   int i;
4325   int flag =1;
4326
4327   while(size--) {
4328     i = (lit >> (size*8)) & 0xff;
4329
4330     if(i==0) {
4331       if(flag) 
4332         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4333       else
4334         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4335       flag = 0;
4336     }
4337   }
4338
4339   return (flag==0);
4340 }
4341 #endif
4342
4343 /*-----------------------------------------------------------------*/
4344 /* genCmp :- greater or less than comparison                       */
4345 /*-----------------------------------------------------------------*/
4346 static void genCmp (operand *left,operand *right,
4347                     operand *result, iCode *ifx, int sign)
4348 {
4349   int size; //, offset = 0 ;
4350   unsigned long lit = 0L,i = 0;
4351   resolvedIfx rFalseIfx;
4352   //  resolvedIfx rTrueIfx;
4353   symbol *truelbl;
4354   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4355 /*
4356   if(ifx) {
4357     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4358     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4359   }
4360 */
4361
4362   resolveIfx(&rFalseIfx,ifx);
4363   truelbl  = newiTempLabel(NULL);
4364   size = max(AOP_SIZE(left),AOP_SIZE(right));
4365
4366   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4367
4368 #define _swapp
4369
4370   /* if literal is on the right then swap with left */
4371   if ((AOP_TYPE(right) == AOP_LIT)) {
4372     operand *tmp = right ;
4373     unsigned long mask = (0x100 << (8*(size-1))) - 1;
4374     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4375 #ifdef _swapp
4376
4377     lit = (lit - 1) & mask;
4378     right = left;
4379     left = tmp;
4380     rFalseIfx.condition ^= 1;
4381 #endif
4382
4383   } else if ((AOP_TYPE(left) == AOP_LIT)) {
4384     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4385   }
4386
4387
4388   //if(IC_TRUE(ifx) == NULL)
4389   /* if left & right are bit variables */
4390   if (AOP_TYPE(left) == AOP_CRY &&
4391       AOP_TYPE(right) == AOP_CRY ) {
4392     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4393     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4394   } else {
4395     /* subtract right from left if at the
4396        end the carry flag is set then we know that
4397        left is greater than right */
4398
4399     //    {
4400
4401     symbol *lbl  = newiTempLabel(NULL);
4402
4403 #ifndef _swapp
4404     if(AOP_TYPE(right) == AOP_LIT) {
4405
4406       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4407
4408       DEBUGpic16_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4409
4410       /* special cases */
4411
4412       if(lit == 0) {
4413
4414         if(sign != 0) 
4415           genSkipCond(&rFalseIfx,left,size-1,7);
4416         else 
4417           /* no need to compare to 0...*/
4418           /* NOTE: this is a de-generate compare that most certainly 
4419            *       creates some dead code. */
4420           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4421
4422         if(ifx) ifx->generated = 1;
4423         return;
4424
4425       }
4426       size--;
4427
4428       if(size == 0) {
4429         //i = (lit >> (size*8)) & 0xff;
4430         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4431         
4432         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4433
4434         i = ((0-lit) & 0xff);
4435         if(sign) {
4436           if( i == 0x81) { 
4437             /* lit is 0x7f, all signed chars are less than
4438              * this except for 0x7f itself */
4439             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4440             genSkipz2(&rFalseIfx,0);
4441           } else {
4442             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4443             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4444             genSkipc(&rFalseIfx);
4445           }
4446
4447         } else {
4448           if(lit == 1) {
4449             genSkipz2(&rFalseIfx,1);
4450           } else {
4451             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4452             genSkipc(&rFalseIfx);
4453           }
4454         }
4455
4456         if(ifx) ifx->generated = 1;
4457         return;
4458       }
4459
4460       /* chars are out of the way. now do ints and longs */
4461
4462
4463       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4464         
4465       /* special cases */
4466
4467       if(sign) {
4468
4469         if(lit == 0) {
4470           genSkipCond(&rFalseIfx,left,size,7);
4471           if(ifx) ifx->generated = 1;
4472           return;
4473         }
4474
4475         if(lit <0x100) {
4476           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4477
4478           //rFalseIfx.condition ^= 1;
4479           //genSkipCond(&rFalseIfx,left,size,7);
4480           //rFalseIfx.condition ^= 1;
4481
4482           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4483           if(rFalseIfx.condition)
4484             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4485           else
4486             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4487
4488           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4489           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4490           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4491
4492           while(size > 1)
4493             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4494
4495           if(rFalseIfx.condition) {
4496             emitSKPZ;
4497             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4498
4499           } else {
4500             emitSKPNZ;
4501           }
4502
4503           genSkipc(&rFalseIfx);
4504           pic16_emitpLabel(truelbl->key);
4505           if(ifx) ifx->generated = 1;
4506           return;
4507
4508         }
4509
4510         if(size == 1) {
4511
4512           if( (lit & 0xff) == 0) {
4513             /* lower byte is zero */
4514             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4515             i = ((lit >> 8) & 0xff) ^0x80;
4516             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4517             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4518             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4519             genSkipc(&rFalseIfx);
4520
4521
4522             if(ifx) ifx->generated = 1;
4523             return;
4524
4525           }
4526         } else {
4527           /* Special cases for signed longs */
4528           if( (lit & 0xffffff) == 0) {
4529             /* lower byte is zero */
4530             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4531             i = ((lit >> 8*3) & 0xff) ^0x80;
4532             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4533             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4534             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4535             genSkipc(&rFalseIfx);
4536
4537
4538             if(ifx) ifx->generated = 1;
4539             return;
4540
4541           }
4542
4543         }
4544
4545
4546         if(lit & (0x80 << (size*8))) {
4547           /* lit is negative */
4548           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4549
4550           //genSkipCond(&rFalseIfx,left,size,7);
4551
4552           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4553
4554           if(rFalseIfx.condition)
4555             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4556           else
4557             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4558
4559
4560         } else {
4561           /* lit is positive */
4562           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4563           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4564           if(rFalseIfx.condition)
4565             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4566           else
4567             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4568
4569         }
4570
4571         /*
4572           This works, but is only good for ints.
4573           It also requires a "known zero" register.
4574           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4575           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4576           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4577           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4578           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4579           genSkipc(&rFalseIfx);
4580
4581           pic16_emitpLabel(truelbl->key);
4582           if(ifx) ifx->generated = 1;
4583           return;
4584         **/
4585           
4586         /* There are no more special cases, so perform a general compare */
4587   
4588         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4589         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4590
4591         while(size--) {
4592
4593           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4594           emitSKPNZ;
4595           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4596         }
4597         //rFalseIfx.condition ^= 1;
4598         genSkipc(&rFalseIfx);
4599
4600         pic16_emitpLabel(truelbl->key);
4601
4602         if(ifx) ifx->generated = 1;
4603         return;
4604
4605
4606       }
4607
4608
4609       /* sign is out of the way. So now do an unsigned compare */
4610       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4611
4612
4613       /* General case - compare to an unsigned literal on the right.*/
4614
4615       i = (lit >> (size*8)) & 0xff;
4616       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4617       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4618       while(size--) {
4619         i = (lit >> (size*8)) & 0xff;
4620
4621         if(i) {
4622           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4623           emitSKPNZ;
4624           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4625         } else {
4626           /* this byte of the lit is zero, 
4627            *if it's not the last then OR in the variable */
4628           if(size)
4629             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4630         }
4631       }
4632
4633
4634       pic16_emitpLabel(lbl->key);
4635       //if(emitFinalCheck)
4636       genSkipc(&rFalseIfx);
4637       if(sign)
4638         pic16_emitpLabel(truelbl->key);
4639
4640       if(ifx) ifx->generated = 1;
4641       return;
4642
4643
4644     }
4645 #endif  // _swapp
4646
4647     if(AOP_TYPE(left) == AOP_LIT) {
4648       //symbol *lbl = newiTempLabel(NULL);
4649
4650       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4651
4652
4653       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4654
4655       /* Special cases */
4656       if((lit == 0) && (sign == 0)){
4657
4658         size--;
4659         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4660         while(size) 
4661           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4662
4663         genSkipz2(&rFalseIfx,0);
4664         if(ifx) ifx->generated = 1;
4665         return;
4666       }
4667
4668       if(size==1) {
4669         /* Special cases */
4670         lit &= 0xff;
4671         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4672           /* degenerate compare can never be true */
4673           if(rFalseIfx.condition == 0)
4674             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4675
4676           if(ifx) ifx->generated = 1;
4677           return;
4678         }
4679
4680         if(sign) {
4681           /* signed comparisons to a literal byte */
4682
4683           int lp1 = (lit+1) & 0xff;
4684
4685           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4686           switch (lp1) {
4687           case 0:
4688             rFalseIfx.condition ^= 1;
4689             genSkipCond(&rFalseIfx,right,0,7);
4690             break;
4691           case 0x7f:
4692             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4693             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4694             genSkipz2(&rFalseIfx,1);
4695             break;
4696           default:
4697             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4698             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4699             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4700             rFalseIfx.condition ^= 1;
4701             genSkipc(&rFalseIfx);
4702             break;
4703           }
4704         } else {
4705           /* unsigned comparisons to a literal byte */
4706
4707           switch(lit & 0xff ) {
4708           case 0:
4709             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4710             genSkipz2(&rFalseIfx,0);
4711             break;
4712           case 0x7f:
4713             rFalseIfx.condition ^= 1;
4714             genSkipCond(&rFalseIfx,right,0,7);
4715             break;
4716
4717           default:
4718             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4719             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4720             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4721             rFalseIfx.condition ^= 1;
4722             if (AOP_TYPE(result) == AOP_CRY)
4723               genSkipc(&rFalseIfx);
4724             else {
4725               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4726               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4727             }         
4728             break;
4729           }
4730         }
4731
4732         if(ifx) ifx->generated = 1;
4733         //goto check_carry;
4734         return;
4735
4736       } else {
4737
4738         /* Size is greater than 1 */
4739
4740         if(sign) {
4741           int lp1 = lit+1;
4742
4743           size--;
4744
4745           if(lp1 == 0) {
4746             /* this means lit = 0xffffffff, or -1 */
4747
4748
4749             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4750             rFalseIfx.condition ^= 1;
4751             genSkipCond(&rFalseIfx,right,size,7);
4752             if(ifx) ifx->generated = 1;
4753             return;
4754           }
4755
4756           if(lit == 0) {
4757             int s = size;
4758
4759             if(rFalseIfx.condition) {
4760               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4761               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4762             }
4763
4764             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4765             while(size--)
4766               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4767
4768
4769             emitSKPZ;
4770             if(rFalseIfx.condition) {
4771               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4772               pic16_emitpLabel(truelbl->key);
4773             }else {
4774               rFalseIfx.condition ^= 1;
4775               genSkipCond(&rFalseIfx,right,s,7);
4776             }
4777
4778             if(ifx) ifx->generated = 1;
4779             return;
4780           }
4781
4782           if((size == 1) &&  (0 == (lp1&0xff))) {
4783             /* lower byte of signed word is zero */
4784             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4785             i = ((lp1 >> 8) & 0xff) ^0x80;
4786             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4787             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4788             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4789             rFalseIfx.condition ^= 1;
4790             genSkipc(&rFalseIfx);
4791
4792
4793             if(ifx) ifx->generated = 1;
4794             return;
4795           }
4796
4797           if(lit & (0x80 << (size*8))) {
4798             /* Lit is less than zero */
4799             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4800             //rFalseIfx.condition ^= 1;
4801             //genSkipCond(&rFalseIfx,left,size,7);
4802             //rFalseIfx.condition ^= 1;
4803             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4804             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4805
4806             if(rFalseIfx.condition)
4807               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4808             else
4809               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4810
4811
4812           } else {
4813             /* Lit is greater than or equal to zero */
4814             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4815             //rFalseIfx.condition ^= 1;
4816             //genSkipCond(&rFalseIfx,right,size,7);
4817             //rFalseIfx.condition ^= 1;
4818
4819             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4820             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4821
4822             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4823             if(rFalseIfx.condition)
4824               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4825             else
4826               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4827
4828           }
4829
4830
4831           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4832           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4833
4834           while(size--) {
4835
4836             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4837             emitSKPNZ;
4838             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4839           }
4840           rFalseIfx.condition ^= 1;
4841           //rFalseIfx.condition = 1;
4842           genSkipc(&rFalseIfx);
4843
4844           pic16_emitpLabel(truelbl->key);
4845
4846           if(ifx) ifx->generated = 1;
4847           return;
4848           // end of if (sign)
4849         } else {
4850
4851           /* compare word or long to an unsigned literal on the right.*/
4852
4853
4854           size--;
4855           if(lit < 0xff) {
4856             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4857             switch (lit) {
4858             case 0:
4859               break; /* handled above */
4860 /*
4861             case 0xff:
4862               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4863               while(size--)
4864                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4865               genSkipz2(&rFalseIfx,0);
4866               break;
4867 */
4868             default:
4869               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4870               while(--size)
4871                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4872
4873               emitSKPZ;
4874               if(rFalseIfx.condition)
4875                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4876               else
4877                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4878
4879
4880               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
4881               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4882
4883               rFalseIfx.condition ^= 1;
4884               genSkipc(&rFalseIfx);
4885             }
4886
4887             pic16_emitpLabel(truelbl->key);
4888
4889             if(ifx) ifx->generated = 1;
4890             return;
4891           }
4892
4893
4894           lit++;
4895           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4896           i = (lit >> (size*8)) & 0xff;
4897
4898           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4899           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4900
4901           while(size--) {
4902             i = (lit >> (size*8)) & 0xff;
4903
4904             if(i) {
4905               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4906               emitSKPNZ;
4907               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4908             } else {
4909               /* this byte of the lit is zero, 
4910                *if it's not the last then OR in the variable */
4911               if(size)
4912                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4913             }
4914           }
4915
4916
4917           pic16_emitpLabel(lbl->key);
4918
4919           rFalseIfx.condition ^= 1;
4920           genSkipc(&rFalseIfx);
4921         }
4922
4923         if(sign)
4924           pic16_emitpLabel(truelbl->key);
4925         if(ifx) ifx->generated = 1;
4926         return;
4927       }
4928     }
4929     /* Compare two variables */
4930
4931     DEBUGpic16_emitcode(";sign","%d",sign);
4932
4933     size--;
4934     if(sign) {
4935       /* Sigh. thus sucks... */
4936       if(size) {
4937         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4938         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4939         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
4940         pic16_emitpcode(POC_XORWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4941         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
4942         pic16_emitpcode(POC_SUBFW, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4943       } else {
4944         /* Signed char comparison */
4945         /* Special thanks to Nikolai Golovchenko for this snippet */
4946         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4947         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
4948         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
4949         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
4950         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
4951         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4952
4953         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4954         genSkipc(&rFalseIfx);
4955           
4956         if(ifx) ifx->generated = 1;
4957         return;
4958       }
4959
4960     } else {
4961
4962       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4963       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4964     }
4965
4966
4967     /* The rest of the bytes of a multi-byte compare */
4968     while (size) {
4969
4970       emitSKPZ;
4971       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
4972       size--;
4973
4974       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4975       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4976
4977
4978     }
4979
4980     pic16_emitpLabel(lbl->key);
4981
4982     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4983     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4984         (AOP_TYPE(result) == AOP_REG)) {
4985       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4986       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4987     } else {
4988       genSkipc(&rFalseIfx);
4989     }         
4990     //genSkipc(&rFalseIfx);
4991     if(ifx) ifx->generated = 1;
4992
4993     return;
4994
4995   }
4996
4997   // check_carry:
4998   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4999     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5000     pic16_outBitC(result);
5001   } else {
5002     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5003     /* if the result is used in the next
5004        ifx conditional branch then generate
5005        code a little differently */
5006     if (ifx )
5007       genIfxJump (ifx,"c");
5008     else
5009       pic16_outBitC(result);
5010     /* leave the result in acc */
5011   }
5012
5013 }
5014
5015 /*-----------------------------------------------------------------*/
5016 /* genCmpGt :- greater than comparison                             */
5017 /*-----------------------------------------------------------------*/
5018 static void genCmpGt (iCode *ic, iCode *ifx)
5019 {
5020     operand *left, *right, *result;
5021     sym_link *letype , *retype;
5022     int sign ;
5023
5024     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5025     left = IC_LEFT(ic);
5026     right= IC_RIGHT(ic);
5027     result = IC_RESULT(ic);
5028
5029     letype = getSpec(operandType(left));
5030     retype =getSpec(operandType(right));
5031     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5032     /* assign the amsops */
5033     pic16_aopOp (left,ic,FALSE);
5034     pic16_aopOp (right,ic,FALSE);
5035     pic16_aopOp (result,ic,TRUE);
5036
5037     genCmp(right, left, result, ifx, sign);
5038
5039     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5040     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5041     pic16_freeAsmop(result,NULL,ic,TRUE); 
5042 }
5043
5044 /*-----------------------------------------------------------------*/
5045 /* genCmpLt - less than comparisons                                */
5046 /*-----------------------------------------------------------------*/
5047 static void genCmpLt (iCode *ic, iCode *ifx)
5048 {
5049     operand *left, *right, *result;
5050     sym_link *letype , *retype;
5051     int sign ;
5052
5053     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5054     left = IC_LEFT(ic);
5055     right= IC_RIGHT(ic);
5056     result = IC_RESULT(ic);
5057
5058     letype = getSpec(operandType(left));
5059     retype =getSpec(operandType(right));
5060     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5061
5062     /* assign the amsops */
5063     pic16_aopOp (left,ic,FALSE);
5064     pic16_aopOp (right,ic,FALSE);
5065     pic16_aopOp (result,ic,TRUE);
5066
5067     genCmp(left, right, result, ifx, sign);
5068
5069     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5070     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5071     pic16_freeAsmop(result,NULL,ic,TRUE); 
5072 }
5073
5074 /*-----------------------------------------------------------------*/
5075 /* genc16bit2lit - compare a 16 bit value to a literal             */
5076 /*-----------------------------------------------------------------*/
5077 static void genc16bit2lit(operand *op, int lit, int offset)
5078 {
5079   int i;
5080
5081   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
5082   if( (lit&0xff) == 0) 
5083     i=1;
5084   else
5085     i=0;
5086
5087   switch( BYTEofLONG(lit,i)) { 
5088   case 0:
5089     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5090     break;
5091   case 1:
5092     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5093     break;
5094   case 0xff:
5095     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5096     break;
5097   default:
5098     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5099     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5100   }
5101
5102   i ^= 1;
5103
5104   switch( BYTEofLONG(lit,i)) { 
5105   case 0:
5106     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5107     break;
5108   case 1:
5109     emitSKPNZ;
5110     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5111     break;
5112   case 0xff:
5113     emitSKPNZ;
5114     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5115     break;
5116   default:
5117     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5118     emitSKPNZ;
5119     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5120
5121   }
5122
5123 }
5124
5125 /*-----------------------------------------------------------------*/
5126 /* gencjneshort - compare and jump if not equal                    */
5127 /*-----------------------------------------------------------------*/
5128 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5129 {
5130   int size = max(AOP_SIZE(left),AOP_SIZE(right));
5131   int offset = 0;
5132   int res_offset = 0;  /* the result may be a different size then left or right */
5133   int res_size = AOP_SIZE(result);
5134   resolvedIfx rIfx;
5135   symbol *lbl;
5136
5137   unsigned long lit = 0L;
5138   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5139   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5140   if(result)
5141     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
5142   resolveIfx(&rIfx,ifx);
5143   lbl =  newiTempLabel(NULL);
5144
5145
5146   /* if the left side is a literal or 
5147      if the right is in a pointer register and left 
5148      is not */
5149   if ((AOP_TYPE(left) == AOP_LIT) || 
5150       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5151     operand *t = right;
5152     right = left;
5153     left = t;
5154   }
5155   if(AOP_TYPE(right) == AOP_LIT)
5156     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5157
5158   /* if the right side is a literal then anything goes */
5159   if (AOP_TYPE(right) == AOP_LIT &&
5160       AOP_TYPE(left) != AOP_DIR ) {
5161     switch(size) {
5162     case 2:
5163       genc16bit2lit(left, lit, 0);
5164       emitSKPNZ;
5165       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5166       break;
5167     default:
5168       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5169       while (size--) {
5170         if(lit & 0xff) {
5171           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5172           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5173         } else {
5174           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5175         }
5176
5177         emitSKPNZ;
5178         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5179         offset++;
5180         if(res_offset < res_size-1)
5181           res_offset++;
5182         lit >>= 8;
5183       }
5184       break;
5185     }
5186   }
5187
5188   /* if the right side is in a register or in direct space or
5189      if the left is a pointer register & right is not */    
5190   else if (AOP_TYPE(right) == AOP_REG ||
5191            AOP_TYPE(right) == AOP_DIR || 
5192            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5193            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5194     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5195     int lbl_key = lbl->key;
5196
5197     if(result) {
5198       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5199       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5200     }else {
5201       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5202       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5203               __FUNCTION__,__LINE__);
5204       return;
5205     }
5206
5207 /*     switch(size) { */
5208 /*     case 2: */
5209 /*       genc16bit2lit(left, lit, 0); */
5210 /*       emitSKPNZ; */
5211 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5212 /*       break; */
5213 /*     default: */
5214     while (size--) {
5215       int emit_skip=1;
5216       if((AOP_TYPE(left) == AOP_DIR) && 
5217          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5218
5219         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5220         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5221
5222       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5223             
5224         switch (lit & 0xff) {
5225         case 0:
5226           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5227           break;
5228         case 1:
5229           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5230           pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5231           //pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5232           emit_skip=0;
5233           break;
5234         case 0xff:
5235           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5236           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5237           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5238           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5239           emit_skip=0;
5240           break;
5241         default:
5242           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5243           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5244         }
5245         lit >>= 8;
5246
5247       } else {
5248         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5249       }
5250       if(emit_skip) {
5251         if(AOP_TYPE(result) == AOP_CRY) {
5252           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5253           if(rIfx.condition)
5254             emitSKPNZ;
5255           else
5256             emitSKPZ;
5257           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5258         } else {
5259           /* fix me. probably need to check result size too */
5260           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5261           if(rIfx.condition)
5262             emitSKPZ;
5263           else
5264             emitSKPNZ;
5265           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5266           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5267         }
5268         if(ifx)
5269           ifx->generated=1;
5270       }
5271       emit_skip++;
5272       offset++;
5273       if(res_offset < res_size-1)
5274         res_offset++;
5275     }
5276 /*       break; */
5277 /*     } */
5278   } else if(AOP_TYPE(right) == AOP_REG &&
5279             AOP_TYPE(left) != AOP_DIR){
5280
5281     while(size--) {
5282       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5283       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5284       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5285       if(rIfx.condition)
5286         emitSKPNZ;
5287       else
5288         emitSKPZ;
5289       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5290       offset++;
5291       if(res_offset < res_size-1)
5292         res_offset++;
5293     }
5294       
5295   }else{
5296     /* right is a pointer reg need both a & b */
5297     while(size--) {
5298       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5299       if(strcmp(l,"b"))
5300         pic16_emitcode("mov","b,%s",l);
5301       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5302       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5303       offset++;
5304     }
5305   }
5306
5307   pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5308   if(!rIfx.condition)
5309     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5310
5311   pic16_emitpLabel(lbl->key);
5312
5313   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5314
5315   if(ifx)
5316     ifx->generated = 1;
5317 }
5318
5319 #if 0
5320 /*-----------------------------------------------------------------*/
5321 /* gencjne - compare and jump if not equal                         */
5322 /*-----------------------------------------------------------------*/
5323 static void gencjne(operand *left, operand *right, iCode *ifx)
5324 {
5325     symbol *tlbl  = newiTempLabel(NULL);
5326
5327     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5328     gencjneshort(left, right, lbl);
5329
5330     pic16_emitcode("mov","a,%s",one);
5331     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5332     pic16_emitcode("","%05d_DS_:",lbl->key+100);
5333     pic16_emitcode("clr","a");
5334     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5335
5336     pic16_emitpLabel(lbl->key);
5337     pic16_emitpLabel(tlbl->key);
5338
5339 }
5340 #endif
5341
5342 /*-----------------------------------------------------------------*/
5343 /* genCmpEq - generates code for equal to                          */
5344 /*-----------------------------------------------------------------*/
5345 static void genCmpEq (iCode *ic, iCode *ifx)
5346 {
5347     operand *left, *right, *result;
5348     unsigned long lit = 0L;
5349     int size,offset=0;
5350     symbol *falselbl  = newiTempLabel(NULL);
5351
5352
5353     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5354
5355     if(ifx)
5356       DEBUGpic16_emitcode ("; ifx is non-null","");
5357     else
5358       DEBUGpic16_emitcode ("; ifx is null","");
5359
5360     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5361     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5362     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5363
5364     size = max(AOP_SIZE(left),AOP_SIZE(right));
5365
5366     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5367
5368     /* if literal, literal on the right or 
5369     if the right is in a pointer register and left 
5370     is not */
5371     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
5372         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5373       operand *tmp = right ;
5374       right = left;
5375       left = tmp;
5376     }
5377
5378
5379     if(ifx && !AOP_SIZE(result)){
5380         symbol *tlbl;
5381         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
5382         /* if they are both bit variables */
5383         if (AOP_TYPE(left) == AOP_CRY &&
5384             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5385                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
5386             if(AOP_TYPE(right) == AOP_LIT){
5387                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5388                 if(lit == 0L){
5389                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5390                     pic16_emitcode("cpl","c");
5391                 } else if(lit == 1L) {
5392                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5393                 } else {
5394                     pic16_emitcode("clr","c");
5395                 }
5396                 /* AOP_TYPE(right) == AOP_CRY */
5397             } else {
5398                 symbol *lbl = newiTempLabel(NULL);
5399                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5400                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5401                 pic16_emitcode("cpl","c");
5402                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5403             }
5404             /* if true label then we jump if condition
5405             supplied is true */
5406             tlbl = newiTempLabel(NULL);
5407             if ( IC_TRUE(ifx) ) {
5408                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5409                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5410             } else {
5411                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5412                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5413             }
5414             pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5415
5416                 {
5417                 /* left and right are both bit variables, result is carry */
5418                         resolvedIfx rIfx;
5419               
5420                         resolveIfx(&rIfx,ifx);
5421
5422                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5423                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5424                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5425                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5426                         genSkipz2(&rIfx,0);
5427                 }
5428         } else {
5429
5430                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
5431
5432                         /* They're not both bit variables. Is the right a literal? */
5433                         if(AOP_TYPE(right) == AOP_LIT) {
5434                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5435             
5436                         switch(size) {
5437
5438                                 case 1:
5439                                         switch(lit & 0xff) {
5440                                                 case 1:
5441                                                                 if ( IC_TRUE(ifx) ) {
5442                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
5443                                                                         emitSKPNZ;
5444                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5445                                                                 } else {
5446                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5447                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5448                                                                 }
5449                                                                 break;
5450                                                 case 0xff:
5451                                                                 if ( IC_TRUE(ifx) ) {
5452                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
5453                                                                         emitSKPNZ;
5454                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5455                                                                 } else {
5456                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5457                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5458                                                                 }
5459                                                                 break;
5460                                                 default:
5461                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5462                                                                 if(lit)
5463                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5464                                                                 genSkip(ifx,'z');
5465                                         } // switch lit
5466
5467
5468                                         /* end of size == 1 */
5469                                         break;
5470               
5471                                 case 2:
5472                                         genc16bit2lit(left,lit,offset);
5473                                         genSkip(ifx,'z');
5474                                         break;
5475                                         /* end of size == 2 */
5476
5477                                 default:
5478                                         /* size is 4 */
5479                                         if(lit==0) {
5480                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5481                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
5482                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5483                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5484                                                 genSkip(ifx,'z');
5485                                         } else {
5486                                                 /* search for patterns that can be optimized */
5487
5488                                                 genc16bit2lit(left,lit,0);
5489                                                 lit >>= 16;
5490                                                 if(lit) {
5491                                                                 if(IC_TRUE(ifx))
5492                                                                 emitSKPZ; // if hi word unequal
5493                                                                 else
5494                                                                 emitSKPNZ; // if hi word equal
5495                                                                 // fail early
5496                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
5497                                                         genc16bit2lit(left,lit,2);
5498                                                         genSkip(ifx,'z');
5499                                                 } else {
5500                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5501                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5502                                                         genSkip(ifx,'z');
5503                                                 }
5504                                         }
5505                                                 pic16_emitpLabel(falselbl->key);
5506                                                 break;
5507
5508                         } // switch size
5509           
5510                         ifx->generated = 1;
5511                         goto release ;
5512             
5513
5514           } else if(AOP_TYPE(right) == AOP_CRY ) {
5515             /* we know the left is not a bit, but that the right is */
5516             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5517             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5518                       pic16_popGet(AOP(right),offset));
5519             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
5520
5521             /* if the two are equal, then W will be 0 and the Z bit is set
5522              * we could test Z now, or go ahead and check the high order bytes if
5523              * the variable we're comparing is larger than a byte. */
5524
5525             while(--size)
5526               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
5527
5528             if ( IC_TRUE(ifx) ) {
5529               emitSKPNZ;
5530               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5531               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5532             } else {
5533               emitSKPZ;
5534               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5535               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5536             }
5537
5538           } else {
5539             /* They're both variables that are larger than bits */
5540             int s = size;
5541
5542             tlbl = newiTempLabel(NULL);
5543
5544             while(size--) {
5545               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5546               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5547
5548               if ( IC_TRUE(ifx) ) {
5549                 if(size) {
5550                   emitSKPZ;
5551                 
5552                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5553
5554                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5555                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5556                 } else {
5557                   emitSKPNZ;
5558
5559                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5560
5561
5562                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5563                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5564                 }
5565               } else {
5566                 emitSKPZ;
5567
5568                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5569
5570                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5571                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5572               }
5573               offset++;
5574             }
5575             if(s>1 && IC_TRUE(ifx)) {
5576               pic16_emitpLabel(tlbl->key);
5577               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
5578             }
5579           }
5580         }
5581         /* mark the icode as generated */
5582         ifx->generated = 1;
5583         goto release ;
5584     }
5585
5586     /* if they are both bit variables */
5587     if (AOP_TYPE(left) == AOP_CRY &&
5588         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5589         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
5590         if(AOP_TYPE(right) == AOP_LIT){
5591             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5592             if(lit == 0L){
5593                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5594                 pic16_emitcode("cpl","c");
5595             } else if(lit == 1L) {
5596                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5597             } else {
5598                 pic16_emitcode("clr","c");
5599             }
5600             /* AOP_TYPE(right) == AOP_CRY */
5601         } else {
5602             symbol *lbl = newiTempLabel(NULL);
5603             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5604             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5605             pic16_emitcode("cpl","c");
5606             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5607         }
5608         /* c = 1 if egal */
5609         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5610             pic16_outBitC(result);
5611             goto release ;
5612         }
5613         if (ifx) {
5614             genIfxJump (ifx,"c");
5615             goto release ;
5616         }
5617         /* if the result is used in an arithmetic operation
5618         then put the result in place */
5619         pic16_outBitC(result);
5620     } else {
5621       
5622       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
5623       gencjne(left,right,result,ifx);
5624 /*
5625       if(ifx) 
5626         gencjne(left,right,newiTempLabel(NULL));
5627       else {
5628         if(IC_TRUE(ifx)->key)
5629           gencjne(left,right,IC_TRUE(ifx)->key);
5630         else
5631           gencjne(left,right,IC_FALSE(ifx)->key);
5632         ifx->generated = 1;
5633         goto release ;
5634       }
5635       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5636         pic16_aopPut(AOP(result),"a",0);
5637         goto release ;
5638       }
5639
5640       if (ifx) {
5641         genIfxJump (ifx,"a");
5642         goto release ;
5643       }
5644 */
5645       /* if the result is used in an arithmetic operation
5646          then put the result in place */
5647 /*
5648       if (AOP_TYPE(result) != AOP_CRY) 
5649         pic16_outAcc(result);
5650 */
5651       /* leave the result in acc */
5652     }
5653
5654 release:
5655     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5656     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5657     pic16_freeAsmop(result,NULL,ic,TRUE);
5658 }
5659
5660 /*-----------------------------------------------------------------*/
5661 /* ifxForOp - returns the icode containing the ifx for operand     */
5662 /*-----------------------------------------------------------------*/
5663 static iCode *ifxForOp ( operand *op, iCode *ic )
5664 {
5665     /* if true symbol then needs to be assigned */
5666     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5667     if (IS_TRUE_SYMOP(op))
5668         return NULL ;
5669
5670     /* if this has register type condition and
5671     the next instruction is ifx with the same operand
5672     and live to of the operand is upto the ifx only then */
5673     if (ic->next &&
5674         ic->next->op == IFX &&
5675         IC_COND(ic->next)->key == op->key &&
5676         OP_SYMBOL(op)->liveTo <= ic->next->seq )
5677         return ic->next;
5678
5679     if (ic->next &&
5680         ic->next->op == IFX &&
5681         IC_COND(ic->next)->key == op->key) {
5682       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5683       return ic->next;
5684     }
5685
5686     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
5687     if (ic->next &&
5688         ic->next->op == IFX)
5689       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
5690
5691     if (ic->next &&
5692         ic->next->op == IFX &&
5693         IC_COND(ic->next)->key == op->key) {
5694       DEBUGpic16_emitcode ("; "," key is okay");
5695       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
5696                            OP_SYMBOL(op)->liveTo,
5697                            ic->next->seq);
5698     }
5699
5700
5701     return NULL;
5702 }
5703 /*-----------------------------------------------------------------*/
5704 /* genAndOp - for && operation                                     */
5705 /*-----------------------------------------------------------------*/
5706 static void genAndOp (iCode *ic)
5707 {
5708     operand *left,*right, *result;
5709 /*     symbol *tlbl; */
5710
5711     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5712     /* note here that && operations that are in an
5713     if statement are taken away by backPatchLabels
5714     only those used in arthmetic operations remain */
5715     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5716     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5717     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5718
5719     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5720
5721     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5722     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
5723     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
5724
5725     /* if both are bit variables */
5726 /*     if (AOP_TYPE(left) == AOP_CRY && */
5727 /*         AOP_TYPE(right) == AOP_CRY ) { */
5728 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5729 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5730 /*         pic16_outBitC(result); */
5731 /*     } else { */
5732 /*         tlbl = newiTempLabel(NULL); */
5733 /*         pic16_toBoolean(left);     */
5734 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
5735 /*         pic16_toBoolean(right); */
5736 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
5737 /*         pic16_outBitAcc(result); */
5738 /*     } */
5739
5740     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5741     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5742     pic16_freeAsmop(result,NULL,ic,TRUE);
5743 }
5744
5745
5746 /*-----------------------------------------------------------------*/
5747 /* genOrOp - for || operation                                      */
5748 /*-----------------------------------------------------------------*/
5749 /*
5750   tsd pic port -
5751   modified this code, but it doesn't appear to ever get called
5752 */
5753
5754 static void genOrOp (iCode *ic)
5755 {
5756     operand *left,*right, *result;
5757     symbol *tlbl;
5758
5759     /* note here that || operations that are in an
5760     if statement are taken away by backPatchLabels
5761     only those used in arthmetic operations remain */
5762     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5763     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5764     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5765     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5766
5767     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5768
5769     /* if both are bit variables */
5770     if (AOP_TYPE(left) == AOP_CRY &&
5771         AOP_TYPE(right) == AOP_CRY ) {
5772       pic16_emitcode("clrc","");
5773       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5774                AOP(left)->aopu.aop_dir,
5775                AOP(left)->aopu.aop_dir);
5776       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5777                AOP(right)->aopu.aop_dir,
5778                AOP(right)->aopu.aop_dir);
5779       pic16_emitcode("setc","");
5780
5781     } else {
5782         tlbl = newiTempLabel(NULL);
5783         pic16_toBoolean(left);
5784         emitSKPZ;
5785         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5786         pic16_toBoolean(right);
5787         pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5788
5789         pic16_outBitAcc(result);
5790     }
5791
5792     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5793     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5794     pic16_freeAsmop(result,NULL,ic,TRUE);            
5795 }
5796
5797 /*-----------------------------------------------------------------*/
5798 /* isLiteralBit - test if lit == 2^n                               */
5799 /*-----------------------------------------------------------------*/
5800 static int isLiteralBit(unsigned long lit)
5801 {
5802     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5803     0x100L,0x200L,0x400L,0x800L,
5804     0x1000L,0x2000L,0x4000L,0x8000L,
5805     0x10000L,0x20000L,0x40000L,0x80000L,
5806     0x100000L,0x200000L,0x400000L,0x800000L,
5807     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5808     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5809     int idx;
5810     
5811     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5812     for(idx = 0; idx < 32; idx++)
5813         if(lit == pw[idx])
5814             return idx+1;
5815     return 0;
5816 }
5817
5818 /*-----------------------------------------------------------------*/
5819 /* continueIfTrue -                                                */
5820 /*-----------------------------------------------------------------*/
5821 static void continueIfTrue (iCode *ic)
5822 {
5823     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5824     if(IC_TRUE(ic))
5825         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5826     ic->generated = 1;
5827 }
5828
5829 /*-----------------------------------------------------------------*/
5830 /* jmpIfTrue -                                                     */
5831 /*-----------------------------------------------------------------*/
5832 static void jumpIfTrue (iCode *ic)
5833 {
5834     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5835     if(!IC_TRUE(ic))
5836         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5837     ic->generated = 1;
5838 }
5839
5840 /*-----------------------------------------------------------------*/
5841 /* jmpTrueOrFalse -                                                */
5842 /*-----------------------------------------------------------------*/
5843 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5844 {
5845     // ugly but optimized by peephole
5846     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5847     if(IC_TRUE(ic)){
5848         symbol *nlbl = newiTempLabel(NULL);
5849         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5850         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5851         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5852         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
5853     }
5854     else{
5855         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5856         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5857     }
5858     ic->generated = 1;
5859 }
5860
5861 /*-----------------------------------------------------------------*/
5862 /* genAnd  - code for and                                          */
5863 /*-----------------------------------------------------------------*/
5864 static void genAnd (iCode *ic, iCode *ifx)
5865 {
5866   operand *left, *right, *result;
5867   int size, offset=0;  
5868   unsigned long lit = 0L;
5869   int bytelit = 0;
5870   resolvedIfx rIfx;
5871
5872
5873   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5874   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5875   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5876   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5877
5878   resolveIfx(&rIfx,ifx);
5879
5880   /* if left is a literal & right is not then exchange them */
5881   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5882       AOP_NEEDSACC(left)) {
5883     operand *tmp = right ;
5884     right = left;
5885     left = tmp;
5886   }
5887
5888   /* if result = right then exchange them */
5889   if(pic16_sameRegs(AOP(result),AOP(right))){
5890     operand *tmp = right ;
5891     right = left;
5892     left = tmp;
5893   }
5894
5895   /* if right is bit then exchange them */
5896   if (AOP_TYPE(right) == AOP_CRY &&
5897       AOP_TYPE(left) != AOP_CRY){
5898     operand *tmp = right ;
5899     right = left;
5900     left = tmp;
5901   }
5902   if(AOP_TYPE(right) == AOP_LIT)
5903     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5904
5905   size = AOP_SIZE(result);
5906
5907   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5908
5909   // if(bit & yy)
5910   // result = bit & yy;
5911   if (AOP_TYPE(left) == AOP_CRY){
5912     // c = bit & literal;
5913     if(AOP_TYPE(right) == AOP_LIT){
5914       if(lit & 1) {
5915         if(size && pic16_sameRegs(AOP(result),AOP(left)))
5916           // no change
5917           goto release;
5918         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5919       } else {
5920         // bit(result) = 0;
5921         if(size && (AOP_TYPE(result) == AOP_CRY)){
5922           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5923           goto release;
5924         }
5925         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5926           jumpIfTrue(ifx);
5927           goto release;
5928         }
5929         pic16_emitcode("clr","c");
5930       }
5931     } else {
5932       if (AOP_TYPE(right) == AOP_CRY){
5933         // c = bit & bit;
5934         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5935         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5936       } else {
5937         // c = bit & val;
5938         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
5939         // c = lsb
5940         pic16_emitcode("rrc","a");
5941         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5942       }
5943     }
5944     // bit = c
5945     // val = c
5946     if(size)
5947       pic16_outBitC(result);
5948     // if(bit & ...)
5949     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5950       genIfxJump(ifx, "c");           
5951     goto release ;
5952   }
5953
5954   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5955   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5956   if((AOP_TYPE(right) == AOP_LIT) &&
5957      (AOP_TYPE(result) == AOP_CRY) &&
5958      (AOP_TYPE(left) != AOP_CRY)){
5959     int posbit = isLiteralBit(lit);
5960     /* left &  2^n */
5961     if(posbit){
5962       posbit--;
5963       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5964       // bit = left & 2^n
5965       if(size)
5966         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
5967       // if(left &  2^n)
5968       else{
5969         if(ifx){
5970 /*
5971           if(IC_TRUE(ifx)) {
5972             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5973             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
5974           } else {
5975             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5976             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5977           }
5978 */
5979           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5980                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5981           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5982           
5983           ifx->generated = 1;
5984         }
5985         goto release;
5986       }
5987     } else {
5988       symbol *tlbl = newiTempLabel(NULL);
5989       int sizel = AOP_SIZE(left);
5990       if(size)
5991         pic16_emitcode("setb","c");
5992       while(sizel--){
5993         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5994           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5995           // byte ==  2^n ?
5996           if((posbit = isLiteralBit(bytelit)) != 0)
5997             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5998           else{
5999             if(bytelit != 0x0FFL)
6000               pic16_emitcode("anl","a,%s",
6001                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6002             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6003           }
6004         }
6005         offset++;
6006       }
6007       // bit = left & literal
6008       if(size){
6009         pic16_emitcode("clr","c");
6010         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6011       }
6012       // if(left & literal)
6013       else{
6014         if(ifx)
6015           jmpTrueOrFalse(ifx, tlbl);
6016         goto release ;
6017       }
6018     }
6019     pic16_outBitC(result);
6020     goto release ;
6021   }
6022
6023   /* if left is same as result */
6024   if(pic16_sameRegs(AOP(result),AOP(left))){
6025     int know_W = -1;
6026     for(;size--; offset++,lit>>=8) {
6027       if(AOP_TYPE(right) == AOP_LIT){
6028         switch(lit & 0xff) {
6029         case 0x00:
6030           /*  and'ing with 0 has clears the result */
6031 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6032           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6033           break;
6034         case 0xff:
6035           /* and'ing with 0xff is a nop when the result and left are the same */
6036           break;
6037
6038         default:
6039           {
6040             int p = my_powof2( (~lit) & 0xff );
6041             if(p>=0) {
6042               /* only one bit is set in the literal, so use a bcf instruction */
6043 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6044               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6045
6046             } else {
6047               pic16_emitcode("movlw","0x%x", (lit & 0xff));
6048               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6049               if(know_W != (lit&0xff))
6050                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6051               know_W = lit &0xff;
6052               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6053             }
6054           }    
6055         }
6056       } else {
6057         if (AOP_TYPE(left) == AOP_ACC) {
6058           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6059         } else {                    
6060           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6061           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6062
6063         }
6064       }
6065     }
6066
6067   } else {
6068     // left & result in different registers
6069     if(AOP_TYPE(result) == AOP_CRY){
6070       // result = bit
6071       // if(size), result in bit
6072       // if(!size && ifx), conditional oper: if(left & right)
6073       symbol *tlbl = newiTempLabel(NULL);
6074       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6075       if(size)
6076         pic16_emitcode("setb","c");
6077       while(sizer--){
6078         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6079         pic16_emitcode("anl","a,%s",
6080                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6081         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6082         offset++;
6083       }
6084       if(size){
6085         CLRC;
6086         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6087         pic16_outBitC(result);
6088       } else if(ifx)
6089         jmpTrueOrFalse(ifx, tlbl);
6090     } else {
6091       for(;(size--);offset++) {
6092         // normal case
6093         // result = left & right
6094         if(AOP_TYPE(right) == AOP_LIT){
6095           int t = (lit >> (offset*8)) & 0x0FFL;
6096           switch(t) { 
6097           case 0x00:
6098             pic16_emitcode("clrf","%s",
6099                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6100             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6101             break;
6102           case 0xff:
6103             pic16_emitcode("movf","%s,w",
6104                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6105             pic16_emitcode("movwf","%s",
6106                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6107             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6108             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6109             break;
6110           default:
6111             pic16_emitcode("movlw","0x%x",t);
6112             pic16_emitcode("andwf","%s,w",
6113                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6114             pic16_emitcode("movwf","%s",
6115                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6116               
6117             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6118             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6119             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6120           }
6121           continue;
6122         }
6123
6124         if (AOP_TYPE(left) == AOP_ACC) {
6125           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6126           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6127         } else {
6128           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6129           pic16_emitcode("andwf","%s,w",
6130                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6131           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6132           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6133         }
6134         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6135         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6136       }
6137     }
6138   }
6139
6140   release :
6141     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6142   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6143   pic16_freeAsmop(result,NULL,ic,TRUE);     
6144 }
6145
6146 /*-----------------------------------------------------------------*/
6147 /* genOr  - code for or                                            */
6148 /*-----------------------------------------------------------------*/
6149 static void genOr (iCode *ic, iCode *ifx)
6150 {
6151     operand *left, *right, *result;
6152     int size, offset=0;
6153     unsigned long lit = 0L;
6154
6155     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6156
6157     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6158     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6159     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6160
6161     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6162
6163     /* if left is a literal & right is not then exchange them */
6164     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6165         AOP_NEEDSACC(left)) {
6166         operand *tmp = right ;
6167         right = left;
6168         left = tmp;
6169     }
6170
6171     /* if result = right then exchange them */
6172     if(pic16_sameRegs(AOP(result),AOP(right))){
6173         operand *tmp = right ;
6174         right = left;
6175         left = tmp;
6176     }
6177
6178     /* if right is bit then exchange them */
6179     if (AOP_TYPE(right) == AOP_CRY &&
6180         AOP_TYPE(left) != AOP_CRY){
6181         operand *tmp = right ;
6182         right = left;
6183         left = tmp;
6184     }
6185
6186     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6187
6188     if(AOP_TYPE(right) == AOP_LIT)
6189         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6190
6191     size = AOP_SIZE(result);
6192
6193     // if(bit | yy)
6194     // xx = bit | yy;
6195     if (AOP_TYPE(left) == AOP_CRY){
6196         if(AOP_TYPE(right) == AOP_LIT){
6197             // c = bit & literal;
6198             if(lit){
6199                 // lit != 0 => result = 1
6200                 if(AOP_TYPE(result) == AOP_CRY){
6201                   if(size)
6202                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6203                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6204                   //     AOP(result)->aopu.aop_dir,
6205                   //     AOP(result)->aopu.aop_dir);
6206                     else if(ifx)
6207                         continueIfTrue(ifx);
6208                     goto release;
6209                 }
6210             } else {
6211                 // lit == 0 => result = left
6212                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6213                     goto release;
6214                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6215             }
6216         } else {
6217             if (AOP_TYPE(right) == AOP_CRY){
6218               if(pic16_sameRegs(AOP(result),AOP(left))){
6219                 // c = bit | bit;
6220                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6221                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6222                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6223
6224                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6225                          AOP(result)->aopu.aop_dir,
6226                          AOP(result)->aopu.aop_dir);
6227                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6228                          AOP(right)->aopu.aop_dir,
6229                          AOP(right)->aopu.aop_dir);
6230                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6231                          AOP(result)->aopu.aop_dir,
6232                          AOP(result)->aopu.aop_dir);
6233               } else {
6234                 if( AOP_TYPE(result) == AOP_ACC) {
6235                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6236                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6237                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6238                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6239
6240                 } else {
6241
6242                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6243                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6244                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6245                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6246
6247                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6248                                  AOP(result)->aopu.aop_dir,
6249                                  AOP(result)->aopu.aop_dir);
6250                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6251                                  AOP(right)->aopu.aop_dir,
6252                                  AOP(right)->aopu.aop_dir);
6253                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6254                                  AOP(left)->aopu.aop_dir,
6255                                  AOP(left)->aopu.aop_dir);
6256                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6257                                  AOP(result)->aopu.aop_dir,
6258                                  AOP(result)->aopu.aop_dir);
6259                 }
6260               }
6261             } else {
6262                 // c = bit | val;
6263                 symbol *tlbl = newiTempLabel(NULL);
6264                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6265
6266
6267                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6268                 if( AOP_TYPE(right) == AOP_ACC) {
6269                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6270                   emitSKPNZ;
6271                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6272                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6273                 }
6274
6275
6276
6277                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6278                     pic16_emitcode(";XXX setb","c");
6279                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6280                          AOP(left)->aopu.aop_dir,tlbl->key+100);
6281                 pic16_toBoolean(right);
6282                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6283                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6284                     jmpTrueOrFalse(ifx, tlbl);
6285                     goto release;
6286                 } else {
6287                     CLRC;
6288                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6289                 }
6290             }
6291         }
6292         // bit = c
6293         // val = c
6294         if(size)
6295             pic16_outBitC(result);
6296         // if(bit | ...)
6297         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6298             genIfxJump(ifx, "c");           
6299         goto release ;
6300     }
6301
6302     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6303     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6304     if((AOP_TYPE(right) == AOP_LIT) &&
6305        (AOP_TYPE(result) == AOP_CRY) &&
6306        (AOP_TYPE(left) != AOP_CRY)){
6307         if(lit){
6308           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6309             // result = 1
6310             if(size)
6311                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6312             else 
6313                 continueIfTrue(ifx);
6314             goto release;
6315         } else {
6316           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6317             // lit = 0, result = boolean(left)
6318             if(size)
6319                 pic16_emitcode(";XXX setb","c");
6320             pic16_toBoolean(right);
6321             if(size){
6322                 symbol *tlbl = newiTempLabel(NULL);
6323                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6324                 CLRC;
6325                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6326             } else {
6327                 genIfxJump (ifx,"a");
6328                 goto release;
6329             }
6330         }
6331         pic16_outBitC(result);
6332         goto release ;
6333     }
6334
6335     /* if left is same as result */
6336     if(pic16_sameRegs(AOP(result),AOP(left))){
6337       int know_W = -1;
6338       for(;size--; offset++,lit>>=8) {
6339         if(AOP_TYPE(right) == AOP_LIT){
6340           if((lit & 0xff) == 0)
6341             /*  or'ing with 0 has no effect */
6342             continue;
6343           else {
6344             int p = my_powof2(lit & 0xff);
6345             if(p>=0) {
6346               /* only one bit is set in the literal, so use a bsf instruction */
6347               pic16_emitpcode(POC_BSF,
6348                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6349             } else {
6350               if(know_W != (lit & 0xff))
6351                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6352               know_W = lit & 0xff;
6353               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6354             }
6355                     
6356           }
6357         } else {
6358           if (AOP_TYPE(left) == AOP_ACC) {
6359             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
6360             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6361           } else {                  
6362             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6363             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
6364
6365             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6366             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6367
6368           }
6369         }
6370       }
6371     } else {
6372         // left & result in different registers
6373         if(AOP_TYPE(result) == AOP_CRY){
6374             // result = bit
6375             // if(size), result in bit
6376             // if(!size && ifx), conditional oper: if(left | right)
6377             symbol *tlbl = newiTempLabel(NULL);
6378             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6379             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6380
6381
6382             if(size)
6383                 pic16_emitcode(";XXX setb","c");
6384             while(sizer--){
6385                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6386                 pic16_emitcode(";XXX orl","a,%s",
6387                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6388                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6389                 offset++;
6390             }
6391             if(size){
6392                 CLRC;
6393                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6394                 pic16_outBitC(result);
6395             } else if(ifx)
6396                 jmpTrueOrFalse(ifx, tlbl);
6397         } else for(;(size--);offset++){
6398           // normal case
6399           // result = left & right
6400           if(AOP_TYPE(right) == AOP_LIT){
6401             int t = (lit >> (offset*8)) & 0x0FFL;
6402             switch(t) { 
6403             case 0x00:
6404               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
6405               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6406
6407               pic16_emitcode("movf","%s,w",
6408                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6409               pic16_emitcode("movwf","%s",
6410                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6411               break;
6412             default:
6413               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
6414               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6415               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6416
6417               pic16_emitcode("movlw","0x%x",t);
6418               pic16_emitcode("iorwf","%s,w",
6419                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6420               pic16_emitcode("movwf","%s",
6421                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6422               
6423             }
6424             continue;
6425           }
6426
6427           // faster than result <- left, anl result,right
6428           // and better if result is SFR
6429           if (AOP_TYPE(left) == AOP_ACC) {
6430             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
6431             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6432           } else {
6433             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6434             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6435
6436             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6437             pic16_emitcode("iorwf","%s,w",
6438                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6439           }
6440           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6441           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6442         }
6443     }
6444
6445 release :
6446     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6447     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6448     pic16_freeAsmop(result,NULL,ic,TRUE);     
6449 }
6450
6451 /*-----------------------------------------------------------------*/
6452 /* genXor - code for xclusive or                                   */
6453 /*-----------------------------------------------------------------*/
6454 static void genXor (iCode *ic, iCode *ifx)
6455 {
6456   operand *left, *right, *result;
6457   int size, offset=0;
6458   unsigned long lit = 0L;
6459
6460   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6461
6462   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6463   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6464   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6465
6466   /* if left is a literal & right is not ||
6467      if left needs acc & right does not */
6468   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6469       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6470     operand *tmp = right ;
6471     right = left;
6472     left = tmp;
6473   }
6474
6475   /* if result = right then exchange them */
6476   if(pic16_sameRegs(AOP(result),AOP(right))){
6477     operand *tmp = right ;
6478     right = left;
6479     left = tmp;
6480   }
6481
6482   /* if right is bit then exchange them */
6483   if (AOP_TYPE(right) == AOP_CRY &&
6484       AOP_TYPE(left) != AOP_CRY){
6485     operand *tmp = right ;
6486     right = left;
6487     left = tmp;
6488   }
6489   if(AOP_TYPE(right) == AOP_LIT)
6490     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6491
6492   size = AOP_SIZE(result);
6493
6494   // if(bit ^ yy)
6495   // xx = bit ^ yy;
6496   if (AOP_TYPE(left) == AOP_CRY){
6497     if(AOP_TYPE(right) == AOP_LIT){
6498       // c = bit & literal;
6499       if(lit>>1){
6500         // lit>>1  != 0 => result = 1
6501         if(AOP_TYPE(result) == AOP_CRY){
6502           if(size)
6503             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
6504             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6505           else if(ifx)
6506             continueIfTrue(ifx);
6507           goto release;
6508         }
6509         pic16_emitcode("setb","c");
6510       } else{
6511         // lit == (0 or 1)
6512         if(lit == 0){
6513           // lit == 0, result = left
6514           if(size && pic16_sameRegs(AOP(result),AOP(left)))
6515             goto release;
6516           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6517         } else{
6518           // lit == 1, result = not(left)
6519           if(size && pic16_sameRegs(AOP(result),AOP(left))){
6520             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
6521             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
6522             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6523             goto release;
6524           } else {
6525             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6526             pic16_emitcode("cpl","c");
6527           }
6528         }
6529       }
6530
6531     } else {
6532       // right != literal
6533       symbol *tlbl = newiTempLabel(NULL);
6534       if (AOP_TYPE(right) == AOP_CRY){
6535         // c = bit ^ bit;
6536         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6537       }
6538       else{
6539         int sizer = AOP_SIZE(right);
6540         // c = bit ^ val
6541         // if val>>1 != 0, result = 1
6542         pic16_emitcode("setb","c");
6543         while(sizer){
6544           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
6545           if(sizer == 1)
6546             // test the msb of the lsb
6547             pic16_emitcode("anl","a,#0xfe");
6548           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6549           sizer--;
6550         }
6551         // val = (0,1)
6552         pic16_emitcode("rrc","a");
6553       }
6554       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6555       pic16_emitcode("cpl","c");
6556       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
6557     }
6558     // bit = c
6559     // val = c
6560     if(size)
6561       pic16_outBitC(result);
6562     // if(bit | ...)
6563     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6564       genIfxJump(ifx, "c");           
6565     goto release ;
6566   }
6567
6568   if(pic16_sameRegs(AOP(result),AOP(left))){
6569     /* if left is same as result */
6570     for(;size--; offset++) {
6571       if(AOP_TYPE(right) == AOP_LIT){
6572         int t  = (lit >> (offset*8)) & 0x0FFL;
6573         if(t == 0x00L)
6574           continue;
6575         else
6576           if (IS_AOP_PREG(left)) {
6577             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6578             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6579             pic16_aopPut(AOP(result),"a",offset);
6580           } else {
6581             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6582             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6583             pic16_emitcode("xrl","%s,%s",
6584                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
6585                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6586           }
6587       } else {
6588         if (AOP_TYPE(left) == AOP_ACC)
6589           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6590         else {
6591           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6592           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6593 /*
6594           if (IS_AOP_PREG(left)) {
6595             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6596             pic16_aopPut(AOP(result),"a",offset);
6597           } else
6598             pic16_emitcode("xrl","%s,a",
6599                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6600 */
6601         }
6602       }
6603     }
6604   } else {
6605     // left & result in different registers
6606     if(AOP_TYPE(result) == AOP_CRY){
6607       // result = bit
6608       // if(size), result in bit
6609       // if(!size && ifx), conditional oper: if(left ^ right)
6610       symbol *tlbl = newiTempLabel(NULL);
6611       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6612       if(size)
6613         pic16_emitcode("setb","c");
6614       while(sizer--){
6615         if((AOP_TYPE(right) == AOP_LIT) &&
6616            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6617           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6618         } else {
6619           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6620           pic16_emitcode("xrl","a,%s",
6621                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6622         }
6623         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6624         offset++;
6625       }
6626       if(size){
6627         CLRC;
6628         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6629         pic16_outBitC(result);
6630       } else if(ifx)
6631         jmpTrueOrFalse(ifx, tlbl);
6632     } else for(;(size--);offset++){
6633       // normal case
6634       // result = left & right
6635       if(AOP_TYPE(right) == AOP_LIT){
6636         int t = (lit >> (offset*8)) & 0x0FFL;
6637         switch(t) { 
6638         case 0x00:
6639           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6640           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6641           pic16_emitcode("movf","%s,w",
6642                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6643           pic16_emitcode("movwf","%s",
6644                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6645           break;
6646         case 0xff:
6647           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
6648           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6649           pic16_emitcode("comf","%s,w",
6650                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6651           pic16_emitcode("movwf","%s",
6652                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6653           break;
6654         default:
6655           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6656           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6657           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6658           pic16_emitcode("movlw","0x%x",t);
6659           pic16_emitcode("xorwf","%s,w",
6660                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6661           pic16_emitcode("movwf","%s",
6662                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6663
6664         }
6665         continue;
6666       }
6667
6668       // faster than result <- left, anl result,right
6669       // and better if result is SFR
6670       if (AOP_TYPE(left) == AOP_ACC) {
6671         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6672         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6673       } else {
6674         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6675         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6676         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6677         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6678       }
6679       if ( AOP_TYPE(result) != AOP_ACC){
6680         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6681         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6682       }
6683     }
6684   }
6685
6686   release :
6687     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6688   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6689   pic16_freeAsmop(result,NULL,ic,TRUE);     
6690 }
6691
6692 /*-----------------------------------------------------------------*/
6693 /* genInline - write the inline code out                           */
6694 /*-----------------------------------------------------------------*/
6695 static void genInline (iCode *ic)
6696 {
6697   char *buffer, *bp, *bp1;
6698     
6699         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6700
6701         _G.inLine += (!options.asmpeep);
6702
6703         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6704         strcpy(buffer,IC_INLINE(ic));
6705
6706 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
6707
6708         /* emit each line as a code */
6709         while (*bp) {
6710                 if (*bp == '\n') {
6711                         *bp++ = '\0';
6712
6713                         if(*bp1)
6714                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6715                         bp1 = bp;
6716                 } else {
6717                         if (*bp == ':') {
6718                                 bp++;
6719                                 *bp = '\0';
6720                                 bp++;
6721
6722                                 /* print label, use this special format with NULL directive
6723                                  * to denote that the argument should not be indented with tab */
6724                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6725                                 bp1 = bp;
6726                         } else
6727                                 bp++;
6728                 }
6729         }
6730
6731         if ((bp1 != bp) && *bp1)
6732                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6733
6734
6735     Safe_free(buffer);
6736
6737     _G.inLine -= (!options.asmpeep);
6738 }
6739
6740 /*-----------------------------------------------------------------*/
6741 /* genRRC - rotate right with carry                                */
6742 /*-----------------------------------------------------------------*/
6743 static void genRRC (iCode *ic)
6744 {
6745   operand *left , *result ;
6746   int size, offset = 0, same;
6747
6748   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6749
6750   /* rotate right with carry */
6751   left = IC_LEFT(ic);
6752   result=IC_RESULT(ic);
6753   pic16_aopOp (left,ic,FALSE);
6754   pic16_aopOp (result,ic,FALSE);
6755
6756   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6757
6758   same = pic16_sameRegs(AOP(result),AOP(left));
6759
6760   size = AOP_SIZE(result);    
6761
6762   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
6763
6764   /* get the lsb and put it into the carry */
6765   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
6766
6767   offset = 0 ;
6768
6769   while(size--) {
6770
6771     if(same) {
6772       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
6773     } else {
6774       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
6775       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6776     }
6777
6778     offset++;
6779   }
6780
6781   pic16_freeAsmop(left,NULL,ic,TRUE);
6782   pic16_freeAsmop(result,NULL,ic,TRUE);
6783 }
6784
6785 /*-----------------------------------------------------------------*/
6786 /* genRLC - generate code for rotate left with carry               */
6787 /*-----------------------------------------------------------------*/
6788 static void genRLC (iCode *ic)
6789 {    
6790   operand *left , *result ;
6791   int size, offset = 0;
6792   int same;
6793
6794   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6795   /* rotate right with carry */
6796   left = IC_LEFT(ic);
6797   result=IC_RESULT(ic);
6798   pic16_aopOp (left,ic,FALSE);
6799   pic16_aopOp (result,ic,FALSE);
6800
6801   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6802
6803   same = pic16_sameRegs(AOP(result),AOP(left));
6804
6805   /* move it to the result */
6806   size = AOP_SIZE(result);    
6807
6808   /* get the msb and put it into the carry */
6809   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
6810
6811   offset = 0 ;
6812
6813   while(size--) {
6814
6815     if(same) {
6816       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
6817     } else {
6818       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
6819       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6820     }
6821
6822     offset++;
6823   }
6824
6825
6826   pic16_freeAsmop(left,NULL,ic,TRUE);
6827   pic16_freeAsmop(result,NULL,ic,TRUE);
6828 }
6829
6830
6831 /* gpasm can get the highest order bit with HIGH/UPPER
6832  * so the following probably is not needed -- VR */
6833  
6834 /*-----------------------------------------------------------------*/
6835 /* genGetHbit - generates code get highest order bit               */
6836 /*-----------------------------------------------------------------*/
6837 static void genGetHbit (iCode *ic)
6838 {
6839     operand *left, *result;
6840     left = IC_LEFT(ic);
6841     result=IC_RESULT(ic);
6842     pic16_aopOp (left,ic,FALSE);
6843     pic16_aopOp (result,ic,FALSE);
6844
6845     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6846     /* get the highest order byte into a */
6847     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6848     if(AOP_TYPE(result) == AOP_CRY){
6849         pic16_emitcode("rlc","a");
6850         pic16_outBitC(result);
6851     }
6852     else{
6853         pic16_emitcode("rl","a");
6854         pic16_emitcode("anl","a,#0x01");
6855         pic16_outAcc(result);
6856     }
6857
6858
6859     pic16_freeAsmop(left,NULL,ic,TRUE);
6860     pic16_freeAsmop(result,NULL,ic,TRUE);
6861 }
6862
6863 #if 0
6864 /*-----------------------------------------------------------------*/
6865 /* AccRol - rotate left accumulator by known count                 */
6866 /*-----------------------------------------------------------------*/
6867 static void AccRol (int shCount)
6868 {
6869     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6870     shCount &= 0x0007;              // shCount : 0..7
6871     switch(shCount){
6872         case 0 :
6873             break;
6874         case 1 :
6875             pic16_emitcode("rl","a");
6876             break;
6877         case 2 :
6878             pic16_emitcode("rl","a");
6879             pic16_emitcode("rl","a");
6880             break;
6881         case 3 :
6882             pic16_emitcode("swap","a");
6883             pic16_emitcode("rr","a");
6884             break;
6885         case 4 :
6886             pic16_emitcode("swap","a");
6887             break;
6888         case 5 :
6889             pic16_emitcode("swap","a");
6890             pic16_emitcode("rl","a");
6891             break;
6892         case 6 :
6893             pic16_emitcode("rr","a");
6894             pic16_emitcode("rr","a");
6895             break;
6896         case 7 :
6897             pic16_emitcode("rr","a");
6898             break;
6899     }
6900 }
6901 #endif
6902
6903 /*-----------------------------------------------------------------*/
6904 /* AccLsh - left shift accumulator by known count                  */
6905 /*-----------------------------------------------------------------*/
6906 static void AccLsh (int shCount)
6907 {
6908         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6909         switch(shCount){
6910                 case 0 :
6911                         return;
6912                         break;
6913                 case 1 :
6914                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6915                         break;
6916                 case 2 :
6917                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6918                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6919                         break;
6920                 case 3 :
6921                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6922                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6923                         break;
6924                 case 4 :
6925                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6926                         break;
6927                 case 5 :
6928                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6929                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6930                         break;
6931                 case 6 :
6932                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6933                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6934                         break;
6935                 case 7 :
6936                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6937                         break;
6938         }
6939
6940         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
6941 }
6942
6943 /*-----------------------------------------------------------------*/
6944 /* AccRsh - right shift accumulator by known count                 */
6945 /*-----------------------------------------------------------------*/
6946 static void AccRsh (int shCount, int andmask)
6947 {
6948         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6949         switch(shCount){
6950                 case 0 :
6951                         return; break;
6952                 case 1 :
6953                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6954 //                      andmask = 0;    /* no need */
6955                         break;
6956                 case 2 :
6957                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6958                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6959 //                      andmask = 0;    /* no need */
6960                         break;
6961                 case 3 :
6962                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6963                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6964                         break;
6965                 case 4 :
6966                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6967                         break;
6968                 case 5 :
6969                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6970                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6971                         break;
6972                 case 6 :
6973                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6974                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6975                         break;
6976                 case 7 :
6977                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6978                         break;
6979         }
6980         
6981         if(andmask)
6982                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
6983         else
6984                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
6985 }
6986
6987 #if 0
6988 /*-----------------------------------------------------------------*/
6989 /* AccSRsh - signed right shift accumulator by known count                 */
6990 /*-----------------------------------------------------------------*/
6991 static void AccSRsh (int shCount)
6992 {
6993     symbol *tlbl ;
6994     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6995     if(shCount != 0){
6996         if(shCount == 1){
6997             pic16_emitcode("mov","c,acc.7");
6998             pic16_emitcode("rrc","a");
6999         } else if(shCount == 2){
7000             pic16_emitcode("mov","c,acc.7");
7001             pic16_emitcode("rrc","a");
7002             pic16_emitcode("mov","c,acc.7");
7003             pic16_emitcode("rrc","a");
7004         } else {
7005             tlbl = newiTempLabel(NULL);
7006             /* rotate right accumulator */
7007             AccRol(8 - shCount);
7008             /* and kill the higher order bits */
7009             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7010             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7011             pic16_emitcode("orl","a,#0x%02x",
7012                      (unsigned char)~SRMask[shCount]);
7013             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7014         }
7015     }
7016 }
7017 #endif
7018 /*-----------------------------------------------------------------*/
7019 /* shiftR1Left2Result - shift right one byte from left to result   */
7020 /*-----------------------------------------------------------------*/
7021 static void shiftR1Left2ResultSigned (operand *left, int offl,
7022                                 operand *result, int offr,
7023                                 int shCount)
7024 {
7025   int same;
7026
7027   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7028
7029   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7030
7031   switch(shCount) {
7032   case 1:
7033     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7034     if(same) 
7035       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7036     else {
7037       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7038       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7039     }
7040
7041     break;
7042   case 2:
7043
7044     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7045     if(same) 
7046       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7047     else {
7048       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7049       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7050     }
7051     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7052     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7053
7054     break;
7055
7056   case 3:
7057     if(same)
7058       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7059     else {
7060       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7061       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7062     }
7063
7064     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7065     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7066     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7067
7068     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7069     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7070
7071     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7072     break;
7073
7074   case 4:
7075     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7076     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
7077     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7078     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
7079     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7080     break;
7081   case 5:
7082     if(same) {
7083       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
7084     } else {
7085       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
7086       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7087     }
7088     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
7089     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
7090     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7091     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
7092     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7093     break;
7094
7095   case 6:
7096     if(same) {
7097       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7098       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7099       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7100       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7101       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7102       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7103     } else {
7104       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7105       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7106       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7107       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7108       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
7109     }
7110     break;
7111
7112   case 7:
7113     if(same) {
7114       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7115       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7116       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7117       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7118     } else {
7119       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7120       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7121       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7122     }
7123
7124   default:
7125     break;
7126   }
7127 }
7128
7129 /*-----------------------------------------------------------------*/
7130 /* shiftR1Left2Result - shift right one byte from left to result   */
7131 /*-----------------------------------------------------------------*/
7132 static void shiftR1Left2Result (operand *left, int offl,
7133                                 operand *result, int offr,
7134                                 int shCount, int sign)
7135 {
7136   int same;
7137
7138   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7139
7140   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7141
7142   /* Copy the msb into the carry if signed. */
7143   if(sign) {
7144     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7145     return;
7146   }
7147
7148
7149
7150   switch(shCount) {
7151   case 1:
7152     emitCLRC;
7153     if(same) 
7154       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7155     else {
7156       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7157       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7158     }
7159     break;
7160   case 2:
7161     emitCLRC;
7162     if(same) {
7163       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7164     } else {
7165       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7166       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7167     }
7168     emitCLRC;
7169     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7170
7171     break;
7172   case 3:
7173     if(same)
7174       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7175     else {
7176       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7177       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7178     }
7179
7180     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7181     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7182     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7183     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7184     break;
7185       
7186   case 4:
7187     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7188     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7189     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7190     break;
7191
7192   case 5:
7193     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7194     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7195     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7196     emitCLRC;
7197     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7198
7199     break;
7200   case 6:
7201
7202     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
7203     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7204     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7205     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7206     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7207     break;
7208
7209   case 7:
7210
7211     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7212     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7213     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7214
7215     break;
7216
7217   default:
7218     break;
7219   }
7220 }
7221
7222 /*-----------------------------------------------------------------*/
7223 /* shiftL1Left2Result - shift left one byte from left to result    */
7224 /*-----------------------------------------------------------------*/
7225 static void shiftL1Left2Result (operand *left, int offl,
7226                                 operand *result, int offr, int shCount)
7227 {
7228   int same;
7229
7230   //    char *l;
7231   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7232
7233   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7234   DEBUGpic16_emitcode ("; ***","same =  %d",same);
7235     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7236     //    MOVA(l);
7237     /* shift left accumulator */
7238     //AccLsh(shCount); // don't comment out just yet...
7239   //    pic16_aopPut(AOP(result),"a",offr);
7240
7241   switch(shCount) {
7242   case 1:
7243     /* Shift left 1 bit position */
7244     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7245     if(same) {
7246       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7247     } else {
7248       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7249       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7250     }
7251     break;
7252   case 2:
7253     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7254     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7255     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7256     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7257     break;
7258   case 3:
7259     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7260     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7261     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7262     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7263     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7264     break;
7265   case 4:
7266     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7267     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7268     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7269     break;
7270   case 5:
7271     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7272     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7273     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7274     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7275     break;
7276   case 6:
7277     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7278     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7279     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7280     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7281     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7282     break;
7283   case 7:
7284     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7285     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7286     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7287     break;
7288
7289   default:
7290     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7291   }
7292
7293 }
7294
7295 /*-----------------------------------------------------------------*/
7296 /* movLeft2Result - move byte from left to result                  */
7297 /*-----------------------------------------------------------------*/
7298 static void movLeft2Result (operand *left, int offl,
7299                             operand *result, int offr)
7300 {
7301   char *l;
7302   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7303   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7304     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7305
7306     if (*l == '@' && (IS_AOP_PREG(result))) {
7307       pic16_emitcode("mov","a,%s",l);
7308       pic16_aopPut(AOP(result),"a",offr);
7309     } else {
7310       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7311       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7312     }
7313   }
7314 }
7315
7316 /*-----------------------------------------------------------------*/
7317 /* shiftL2Left2Result - shift left two bytes from left to result   */
7318 /*-----------------------------------------------------------------*/
7319 static void shiftL2Left2Result (operand *left, int offl,
7320                                 operand *result, int offr, int shCount)
7321 {
7322   int same = pic16_sameRegs(AOP(result), AOP(left));
7323   int i;
7324
7325   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7326
7327   if (same && (offl != offr)) { // shift bytes
7328     if (offr > offl) {
7329        for(i=1;i>-1;i--) {
7330          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7331          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7332        }
7333     } else { // just treat as different later on
7334                 same = 0;
7335     }
7336   }
7337
7338   if(same) {
7339     switch(shCount) {
7340     case 0:
7341       break;
7342     case 1:
7343     case 2:
7344     case 3:
7345
7346       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7347       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7348       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7349
7350       while(--shCount) {
7351                 emitCLRC;
7352                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7353                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7354       }
7355
7356       break;
7357     case 4:
7358     case 5:
7359       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
7360       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
7361       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7362       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7363       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
7364       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7365       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7366       if(shCount >=5) {
7367                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7368                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7369       }
7370       break;
7371     case 6:
7372       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7373       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7374       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7375       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7376       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7377       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7378       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7379       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7380       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7381       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7382       break;
7383     case 7:
7384       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7385       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7386       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7387       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7388       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7389     }
7390
7391   } else {
7392     switch(shCount) {
7393     case 0:
7394       break;
7395     case 1:
7396     case 2:
7397     case 3:
7398       /* note, use a mov/add for the shift since the mov has a
7399          chance of getting optimized out */
7400       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7401       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7402       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7403       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
7404       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7405
7406       while(--shCount) {
7407                 emitCLRC;
7408                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7409                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7410       }
7411       break;
7412
7413     case 4:
7414     case 5:
7415       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7416       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7417       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7418       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7419       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7420       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7421       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7422       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7423
7424
7425       if(shCount == 5) {
7426                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7427                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7428       }
7429       break;
7430     case 6:
7431       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7432       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7433       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7434       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7435
7436       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7437       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7438       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7439       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7440       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7441       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7442       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7443       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7444       break;
7445     case 7:
7446       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7447       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7448       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7449       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7450       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7451     }
7452   }
7453
7454 }
7455 /*-----------------------------------------------------------------*/
7456 /* shiftR2Left2Result - shift right two bytes from left to result  */
7457 /*-----------------------------------------------------------------*/
7458 static void shiftR2Left2Result (operand *left, int offl,
7459                                 operand *result, int offr,
7460                                 int shCount, int sign)
7461 {
7462   int same = pic16_sameRegs(AOP(result), AOP(left));
7463   int i;
7464   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7465
7466   if (same && (offl != offr)) { // shift right bytes
7467     if (offr < offl) {
7468        for(i=0;i<2;i++) {
7469          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7470          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7471        }
7472     } else { // just treat as different later on
7473                 same = 0;
7474     }
7475   }
7476
7477   switch(shCount) {
7478   case 0:
7479     break;
7480   case 1:
7481   case 2:
7482   case 3:
7483     if(sign)
7484       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7485     else
7486       emitCLRC;
7487
7488     if(same) {
7489       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7490       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7491     } else {
7492       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7493       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7494       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7495       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7496     }
7497
7498     while(--shCount) {
7499       if(sign)
7500                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7501       else
7502                 emitCLRC;
7503       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7504       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7505     }
7506     break;
7507   case 4:
7508   case 5:
7509     if(same) {
7510
7511       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7512       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7513       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7514
7515       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7516       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7517       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7518       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7519     } else {
7520       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7521       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7522       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7523
7524       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7525       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7526       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7527       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7528       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7529     }
7530
7531     if(shCount >=5) {
7532       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7533       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7534     }
7535
7536     if(sign) {
7537       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7538       pic16_emitpcode(POC_BTFSC, 
7539                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7540       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7541     }
7542
7543     break;
7544
7545   case 6:
7546     if(same) {
7547
7548       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7549       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7550
7551       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7552       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7553       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7554       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7555       if(sign) {
7556         pic16_emitpcode(POC_BTFSC, 
7557                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7558         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7559       }
7560       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7561       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7562       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7563       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7564     } else {
7565       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7566       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7567       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7568       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7569       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7570       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7571       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7572       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7573       if(sign) {
7574         pic16_emitpcode(POC_BTFSC, 
7575                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7576         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7577       }
7578       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7579       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7580
7581         
7582     }
7583
7584     break;
7585   case 7:
7586     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7587     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7588     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7589     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
7590     if(sign) {
7591       emitSKPNC;
7592       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
7593     } else 
7594       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7595   }
7596 }
7597
7598
7599 /*-----------------------------------------------------------------*/
7600 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7601 /*-----------------------------------------------------------------*/
7602 static void shiftLLeftOrResult (operand *left, int offl,
7603                                 operand *result, int offr, int shCount)
7604 {
7605     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7606
7607     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7608     /* shift left accumulator */
7609     AccLsh(shCount);
7610     /* or with result */
7611     /* back to result */
7612     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7613 }
7614
7615 /*-----------------------------------------------------------------*/
7616 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7617 /*-----------------------------------------------------------------*/
7618 static void shiftRLeftOrResult (operand *left, int offl,
7619                                 operand *result, int offr, int shCount)
7620 {
7621     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7622     
7623     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7624     /* shift right accumulator */
7625     AccRsh(shCount, 1);
7626     /* or with result */
7627     /* back to result */
7628     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7629 }
7630
7631 /*-----------------------------------------------------------------*/
7632 /* genlshOne - left shift a one byte quantity by known count       */
7633 /*-----------------------------------------------------------------*/
7634 static void genlshOne (operand *result, operand *left, int shCount)
7635 {       
7636     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7637     shiftL1Left2Result(left, LSB, result, LSB, shCount);
7638 }
7639
7640 /*-----------------------------------------------------------------*/
7641 /* genlshTwo - left shift two bytes by known amount != 0           */
7642 /*-----------------------------------------------------------------*/
7643 static void genlshTwo (operand *result,operand *left, int shCount)
7644 {
7645     int size;
7646     
7647     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7648     size = pic16_getDataSize(result);
7649
7650     /* if shCount >= 8 */
7651     if (shCount >= 8) {
7652         shCount -= 8 ;
7653
7654         if (size > 1){
7655             if (shCount)
7656                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7657             else 
7658                 movLeft2Result(left, LSB, result, MSB16);
7659         }
7660         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7661     }
7662
7663     /*  1 <= shCount <= 7 */
7664     else {  
7665         if(size == 1)
7666             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7667         else 
7668             shiftL2Left2Result(left, LSB, result, LSB, shCount);
7669     }
7670 }
7671
7672 /*-----------------------------------------------------------------*/
7673 /* shiftLLong - shift left one long from left to result            */
7674 /* offr = LSB or MSB16                                             */
7675 /*-----------------------------------------------------------------*/
7676 static void shiftLLong (operand *left, operand *result, int offr )
7677 {
7678     int size = AOP_SIZE(result);
7679     int same = pic16_sameRegs(AOP(left),AOP(result));
7680         int i;
7681
7682     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
7683
7684         if (same && (offr == MSB16)) { //shift one byte
7685                 for(i=size-1;i>=MSB16;i--) {
7686                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
7687                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
7688                 }
7689         } else {
7690                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
7691         }
7692         
7693     if (size >= LSB+offr ){
7694                 if (same) {
7695                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
7696                 } else {
7697                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
7698                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
7699                 }
7700          }
7701
7702     if(size >= MSB16+offr){
7703                 if (same) {
7704                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
7705                 } else {
7706                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
7707                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
7708                 }
7709     }
7710
7711     if(size >= MSB24+offr){
7712                 if (same) {
7713                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
7714                 } else {
7715                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
7716                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
7717                 }
7718     }
7719
7720     if(size > MSB32+offr){
7721                 if (same) {
7722                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
7723                 } else {
7724                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
7725                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
7726                 }
7727     }
7728     if(offr != LSB)
7729                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7730
7731 }
7732
7733 /*-----------------------------------------------------------------*/
7734 /* genlshFour - shift four byte by a known amount != 0             */
7735 /*-----------------------------------------------------------------*/
7736 static void genlshFour (operand *result, operand *left, int shCount)
7737 {
7738     int size;
7739
7740     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7741     size = AOP_SIZE(result);
7742
7743     /* if shifting more that 3 bytes */
7744     if (shCount >= 24 ) {
7745         shCount -= 24;
7746         if (shCount)
7747             /* lowest order of left goes to the highest
7748             order of the destination */
7749             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7750         else
7751             movLeft2Result(left, LSB, result, MSB32);
7752
7753                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7754                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7755                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
7756
7757         return;
7758     }
7759
7760     /* more than two bytes */
7761     else if ( shCount >= 16 ) {
7762         /* lower order two bytes goes to higher order two bytes */
7763         shCount -= 16;
7764         /* if some more remaining */
7765         if (shCount)
7766             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7767         else {
7768             movLeft2Result(left, MSB16, result, MSB32);
7769             movLeft2Result(left, LSB, result, MSB24);
7770         }
7771                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7772                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7773         return;
7774     }    
7775
7776     /* if more than 1 byte */
7777     else if ( shCount >= 8 ) {
7778         /* lower order three bytes goes to higher order  three bytes */
7779         shCount -= 8;
7780         if(size == 2){
7781             if(shCount)
7782                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7783             else
7784                 movLeft2Result(left, LSB, result, MSB16);
7785         }
7786         else{   /* size = 4 */
7787             if(shCount == 0){
7788                 movLeft2Result(left, MSB24, result, MSB32);
7789                 movLeft2Result(left, MSB16, result, MSB24);
7790                 movLeft2Result(left, LSB, result, MSB16);
7791                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7792             }
7793             else if(shCount == 1)
7794                 shiftLLong(left, result, MSB16);
7795             else{
7796                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7797                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7798                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7799                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7800             }
7801         }
7802     }
7803
7804     /* 1 <= shCount <= 7 */
7805     else if(shCount <= 3)
7806     { 
7807         shiftLLong(left, result, LSB);
7808         while(--shCount >= 1)
7809             shiftLLong(result, result, LSB);
7810     }
7811     /* 3 <= shCount <= 7, optimize */
7812     else{
7813         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7814         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7815         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7816     }
7817 }
7818
7819 /*-----------------------------------------------------------------*/
7820 /* genLeftShiftLiteral - left shifting by known count              */
7821 /*-----------------------------------------------------------------*/
7822 static void genLeftShiftLiteral (operand *left,
7823                                  operand *right,
7824                                  operand *result,
7825                                  iCode *ic)
7826 {    
7827     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7828     int size;
7829
7830     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7831     pic16_freeAsmop(right,NULL,ic,TRUE);
7832
7833     pic16_aopOp(left,ic,FALSE);
7834     pic16_aopOp(result,ic,FALSE);
7835
7836     size = getSize(operandType(result));
7837
7838 #if VIEW_SIZE
7839     pic16_emitcode("; shift left ","result %d, left %d",size,
7840              AOP_SIZE(left));
7841 #endif
7842
7843     /* I suppose that the left size >= result size */
7844     if(shCount == 0){
7845         while(size--){
7846             movLeft2Result(left, size, result, size);
7847         }
7848     }
7849
7850     else if(shCount >= (size * 8))
7851         while(size--)
7852             pic16_aopPut(AOP(result),zero,size);
7853     else{
7854         switch (size) {
7855             case 1:
7856                 genlshOne (result,left,shCount);
7857                 break;
7858
7859             case 2:
7860             case 3:
7861                 genlshTwo (result,left,shCount);
7862                 break;
7863
7864             case 4:
7865                 genlshFour (result,left,shCount);
7866                 break;
7867         }
7868     }
7869     pic16_freeAsmop(left,NULL,ic,TRUE);
7870     pic16_freeAsmop(result,NULL,ic,TRUE);
7871 }
7872
7873 /*-----------------------------------------------------------------*
7874  * genMultiAsm - repeat assembly instruction for size of register.
7875  * if endian == 1, then the high byte (i.e base address + size of 
7876  * register) is used first else the low byte is used first;
7877  *-----------------------------------------------------------------*/
7878 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7879 {
7880
7881   int offset = 0;
7882
7883   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7884
7885   if(!reg)
7886     return;
7887
7888   if(!endian) {
7889     endian = 1;
7890   } else {
7891     endian = -1;
7892     offset = size-1;
7893   }
7894
7895   while(size--) {
7896     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
7897     offset += endian;
7898   }
7899
7900 }
7901 /*-----------------------------------------------------------------*/
7902 /* genLeftShift - generates code for left shifting                 */
7903 /*-----------------------------------------------------------------*/
7904 static void genLeftShift (iCode *ic)
7905 {
7906   operand *left,*right, *result;
7907   int size, offset;
7908   char *l;
7909   symbol *tlbl , *tlbl1;
7910   pCodeOp *pctemp;
7911
7912   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7913
7914   right = IC_RIGHT(ic);
7915   left  = IC_LEFT(ic);
7916   result = IC_RESULT(ic);
7917
7918   pic16_aopOp(right,ic,FALSE);
7919
7920   /* if the shift count is known then do it 
7921      as efficiently as possible */
7922   if (AOP_TYPE(right) == AOP_LIT) {
7923     genLeftShiftLiteral (left,right,result,ic);
7924     return ;
7925   }
7926
7927   /* shift count is unknown then we have to form 
7928      a loop get the loop count in B : Note: we take
7929      only the lower order byte since shifting
7930      more that 32 bits make no sense anyway, ( the
7931      largest size of an object can be only 32 bits ) */  
7932
7933     
7934   pic16_aopOp(left,ic,FALSE);
7935   pic16_aopOp(result,ic,FALSE);
7936
7937   /* now move the left to the result if they are not the
7938      same */
7939   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7940       AOP_SIZE(result) > 1) {
7941
7942     size = AOP_SIZE(result);
7943     offset=0;
7944     while (size--) {
7945       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7946       if (*l == '@' && (IS_AOP_PREG(result))) {
7947
7948         pic16_emitcode("mov","a,%s",l);
7949         pic16_aopPut(AOP(result),"a",offset);
7950       } else {
7951         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7952         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7953         //pic16_aopPut(AOP(result),l,offset);
7954       }
7955       offset++;
7956     }
7957   }
7958
7959   size = AOP_SIZE(result);
7960
7961   /* if it is only one byte then */
7962   if (size == 1) {
7963     if(optimized_for_speed) {
7964       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
7965       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
7966       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
7967       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7968       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7969       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
7970       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
7971       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
7972       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
7973       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
7974       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
7975       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
7976     } else {
7977
7978       tlbl = newiTempLabel(NULL);
7979       if (!pic16_sameRegs(AOP(left),AOP(result))) {
7980                 pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7981                 pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7982       }
7983
7984       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7985       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
7986       pic16_emitpLabel(tlbl->key);
7987       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
7988       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7989       emitSKPC;
7990       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7991     }
7992     goto release ;
7993   }
7994     
7995   if (pic16_sameRegs(AOP(left),AOP(result))) {
7996
7997     tlbl = newiTempLabel(NULL);
7998     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7999     genMultiAsm(POC_RRCF, result, size,1);
8000     pic16_emitpLabel(tlbl->key);
8001     genMultiAsm(POC_RLCF, result, size,0);
8002     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8003     emitSKPC;
8004     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8005     goto release;
8006   }
8007
8008   //tlbl = newiTempLabel(NULL);
8009   //offset = 0 ;   
8010   //tlbl1 = newiTempLabel(NULL);
8011
8012   //reAdjustPreg(AOP(result));    
8013     
8014   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
8015   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8016   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8017   //MOVA(l);
8018   //pic16_emitcode("add","a,acc");         
8019   //pic16_aopPut(AOP(result),"a",offset++);
8020   //while (--size) {
8021   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8022   //  MOVA(l);
8023   //  pic16_emitcode("rlc","a");         
8024   //  pic16_aopPut(AOP(result),"a",offset++);
8025   //}
8026   //reAdjustPreg(AOP(result));
8027
8028   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8029   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8030
8031
8032   tlbl = newiTempLabel(NULL);
8033   tlbl1= newiTempLabel(NULL);
8034
8035   size = AOP_SIZE(result);
8036   offset = 1;
8037
8038   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8039
8040   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8041
8042   /* offset should be 0, 1 or 3 */
8043   
8044   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8045   emitSKPNZ;
8046   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8047
8048   pic16_emitpcode(POC_MOVWF, pctemp);
8049
8050
8051   pic16_emitpLabel(tlbl->key);
8052
8053   emitCLRC;
8054   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
8055   while(--size)
8056     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
8057
8058   pic16_emitpcode(POC_DECFSZ,  pctemp);
8059   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8060   pic16_emitpLabel(tlbl1->key);
8061
8062   pic16_popReleaseTempReg(pctemp);
8063
8064
8065  release:
8066   pic16_freeAsmop (right,NULL,ic,TRUE);
8067   pic16_freeAsmop(left,NULL,ic,TRUE);
8068   pic16_freeAsmop(result,NULL,ic,TRUE);
8069 }
8070
8071 /*-----------------------------------------------------------------*/
8072 /* genrshOne - right shift a one byte quantity by known count      */
8073 /*-----------------------------------------------------------------*/
8074 static void genrshOne (operand *result, operand *left,
8075                        int shCount, int sign)
8076 {
8077     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8078     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8079 }
8080
8081 /*-----------------------------------------------------------------*/
8082 /* genrshTwo - right shift two bytes by known amount != 0          */
8083 /*-----------------------------------------------------------------*/
8084 static void genrshTwo (operand *result,operand *left,
8085                        int shCount, int sign)
8086 {
8087   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8088   /* if shCount >= 8 */
8089   if (shCount >= 8) {
8090     shCount -= 8 ;
8091     if (shCount)
8092       shiftR1Left2Result(left, MSB16, result, LSB,
8093                          shCount, sign);
8094     else
8095       movLeft2Result(left, MSB16, result, LSB);
8096
8097     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8098
8099     if(sign) {
8100       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
8101       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8102     }
8103   }
8104
8105   /*  1 <= shCount <= 7 */
8106   else
8107     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
8108 }
8109
8110 /*-----------------------------------------------------------------*/
8111 /* shiftRLong - shift right one long from left to result           */
8112 /* offl = LSB or MSB16                                             */
8113 /*-----------------------------------------------------------------*/
8114 static void shiftRLong (operand *left, int offl,
8115                         operand *result, int sign)
8116 {
8117     int size = AOP_SIZE(result);
8118     int same = pic16_sameRegs(AOP(left),AOP(result));
8119     int i;
8120     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8121
8122         if (same && (offl == MSB16)) { //shift one byte right
8123                 for(i=MSB16;i<size;i++) {
8124                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8125                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8126                 }
8127         }
8128
8129     if(sign)
8130                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8131         else
8132                 emitCLRC;
8133
8134         if (same) {
8135                 if (offl == LSB)
8136                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8137         } else {
8138         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8139         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8140         }
8141
8142     if(offl == MSB16) {
8143         /* add sign of "a" */
8144         pic16_addSign(result, MSB32, sign);
8145         }
8146
8147         if (same) {
8148         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8149         } else {
8150         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8151         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8152         }
8153         
8154         if (same) {
8155         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8156         } else {
8157         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8158         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8159         }
8160
8161         if (same) {
8162         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8163         } else {
8164         if(offl == LSB){
8165                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8166                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8167         }
8168         }
8169 }
8170
8171 /*-----------------------------------------------------------------*/
8172 /* genrshFour - shift four byte by a known amount != 0             */
8173 /*-----------------------------------------------------------------*/
8174 static void genrshFour (operand *result, operand *left,
8175                         int shCount, int sign)
8176 {
8177   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8178   /* if shifting more that 3 bytes */
8179   if(shCount >= 24 ) {
8180     shCount -= 24;
8181     if(shCount)
8182       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8183     else
8184       movLeft2Result(left, MSB32, result, LSB);
8185
8186     pic16_addSign(result, MSB16, sign);
8187   }
8188   else if(shCount >= 16){
8189     shCount -= 16;
8190     if(shCount)
8191       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8192     else{
8193       movLeft2Result(left, MSB24, result, LSB);
8194       movLeft2Result(left, MSB32, result, MSB16);
8195     }
8196     pic16_addSign(result, MSB24, sign);
8197   }
8198   else if(shCount >= 8){
8199     shCount -= 8;
8200     if(shCount == 1)
8201       shiftRLong(left, MSB16, result, sign);
8202     else if(shCount == 0){
8203       movLeft2Result(left, MSB16, result, LSB);
8204       movLeft2Result(left, MSB24, result, MSB16);
8205       movLeft2Result(left, MSB32, result, MSB24);
8206       pic16_addSign(result, MSB32, sign);
8207     }
8208     else{ //shcount >= 2
8209       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8210       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8211       /* the last shift is signed */
8212       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8213       pic16_addSign(result, MSB32, sign);
8214     }
8215   }
8216   else{   /* 1 <= shCount <= 7 */
8217     if(shCount <= 2){
8218       shiftRLong(left, LSB, result, sign);
8219       if(shCount == 2)
8220         shiftRLong(result, LSB, result, sign);
8221     }
8222     else{
8223       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8224       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8225       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8226     }
8227   }
8228 }
8229
8230 /*-----------------------------------------------------------------*/
8231 /* genRightShiftLiteral - right shifting by known count            */
8232 /*-----------------------------------------------------------------*/
8233 static void genRightShiftLiteral (operand *left,
8234                                   operand *right,
8235                                   operand *result,
8236                                   iCode *ic,
8237                                   int sign)
8238 {    
8239   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8240   int lsize,res_size;
8241
8242   pic16_freeAsmop(right,NULL,ic,TRUE);
8243
8244   pic16_aopOp(left,ic,FALSE);
8245   pic16_aopOp(result,ic,FALSE);
8246
8247   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8248
8249 #if VIEW_SIZE
8250   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8251                  AOP_SIZE(left));
8252 #endif
8253
8254   lsize = pic16_getDataSize(left);
8255   res_size = pic16_getDataSize(result);
8256   /* test the LEFT size !!! */
8257
8258   /* I suppose that the left size >= result size */
8259   if(shCount == 0){
8260     while(res_size--)
8261       movLeft2Result(left, lsize, result, res_size);
8262   }
8263
8264   else if(shCount >= (lsize * 8)){
8265
8266     if(res_size == 1) {
8267       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8268       if(sign) {
8269         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8270         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8271       }
8272     } else {
8273
8274       if(sign) {
8275         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8276         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8277         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8278         while(res_size--)
8279           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8280
8281       } else {
8282
8283         while(res_size--)
8284           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8285       }
8286     }
8287   } else {
8288
8289     switch (res_size) {
8290     case 1:
8291       genrshOne (result,left,shCount,sign);
8292       break;
8293
8294     case 2:
8295       genrshTwo (result,left,shCount,sign);
8296       break;
8297
8298     case 4:
8299       genrshFour (result,left,shCount,sign);
8300       break;
8301     default :
8302       break;
8303     }
8304
8305   }
8306
8307   pic16_freeAsmop(left,NULL,ic,TRUE);
8308   pic16_freeAsmop(result,NULL,ic,TRUE);
8309 }
8310
8311 /*-----------------------------------------------------------------*/
8312 /* genSignedRightShift - right shift of signed number              */
8313 /*-----------------------------------------------------------------*/
8314 static void genSignedRightShift (iCode *ic)
8315 {
8316   operand *right, *left, *result;
8317   int size, offset;
8318   //  char *l;
8319   symbol *tlbl, *tlbl1 ;
8320   pCodeOp *pctemp;
8321
8322   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8323
8324   /* we do it the hard way put the shift count in b
8325      and loop thru preserving the sign */
8326   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8327
8328   right = IC_RIGHT(ic);
8329   left  = IC_LEFT(ic);
8330   result = IC_RESULT(ic);
8331
8332   pic16_aopOp(right,ic,FALSE);  
8333   pic16_aopOp(left,ic,FALSE);
8334   pic16_aopOp(result,ic,FALSE);
8335
8336
8337   if ( AOP_TYPE(right) == AOP_LIT) {
8338     genRightShiftLiteral (left,right,result,ic,1);
8339     return ;
8340   }
8341   /* shift count is unknown then we have to form 
8342      a loop get the loop count in B : Note: we take
8343      only the lower order byte since shifting
8344      more that 32 bits make no sense anyway, ( the
8345      largest size of an object can be only 32 bits ) */  
8346
8347   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8348   //pic16_emitcode("inc","b");
8349   //pic16_freeAsmop (right,NULL,ic,TRUE);
8350   //pic16_aopOp(left,ic,FALSE);
8351   //pic16_aopOp(result,ic,FALSE);
8352
8353   /* now move the left to the result if they are not the
8354      same */
8355   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8356       AOP_SIZE(result) > 1) {
8357
8358     size = AOP_SIZE(result);
8359     offset=0;
8360     while (size--) { 
8361       /*
8362         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8363         if (*l == '@' && IS_AOP_PREG(result)) {
8364
8365         pic16_emitcode("mov","a,%s",l);
8366         pic16_aopPut(AOP(result),"a",offset);
8367         } else
8368         pic16_aopPut(AOP(result),l,offset);
8369       */
8370       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8371       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8372
8373       offset++;
8374     }
8375   }
8376
8377   /* mov the highest order bit to OVR */    
8378   tlbl = newiTempLabel(NULL);
8379   tlbl1= newiTempLabel(NULL);
8380
8381   size = AOP_SIZE(result);
8382   offset = size - 1;
8383
8384   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8385
8386   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8387
8388   /* offset should be 0, 1 or 3 */
8389   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
8390   emitSKPNZ;
8391   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8392
8393   pic16_emitpcode(POC_MOVWF, pctemp);
8394
8395
8396   pic16_emitpLabel(tlbl->key);
8397
8398   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
8399   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
8400
8401   while(--size) {
8402     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
8403   }
8404
8405   pic16_emitpcode(POC_DECFSZ,  pctemp);
8406   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8407   pic16_emitpLabel(tlbl1->key);
8408
8409   pic16_popReleaseTempReg(pctemp);
8410 #if 0
8411   size = AOP_SIZE(result);
8412   offset = size - 1;
8413   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8414   pic16_emitcode("rlc","a");
8415   pic16_emitcode("mov","ov,c");
8416   /* if it is only one byte then */
8417   if (size == 1) {
8418     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8419     MOVA(l);
8420     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8421     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8422     pic16_emitcode("mov","c,ov");
8423     pic16_emitcode("rrc","a");
8424     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8425     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8426     pic16_aopPut(AOP(result),"a",0);
8427     goto release ;
8428   }
8429
8430   reAdjustPreg(AOP(result));
8431   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8432   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8433   pic16_emitcode("mov","c,ov");
8434   while (size--) {
8435     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8436     MOVA(l);
8437     pic16_emitcode("rrc","a");         
8438     pic16_aopPut(AOP(result),"a",offset--);
8439   }
8440   reAdjustPreg(AOP(result));
8441   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8442   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8443
8444  release:
8445 #endif
8446
8447   pic16_freeAsmop(left,NULL,ic,TRUE);
8448   pic16_freeAsmop(result,NULL,ic,TRUE);
8449   pic16_freeAsmop(right,NULL,ic,TRUE);
8450 }
8451
8452 /*-----------------------------------------------------------------*/
8453 /* genRightShift - generate code for right shifting                */
8454 /*-----------------------------------------------------------------*/
8455 static void genRightShift (iCode *ic)
8456 {
8457     operand *right, *left, *result;
8458     sym_link *letype ;
8459     int size, offset;
8460     char *l;
8461     symbol *tlbl, *tlbl1 ;
8462
8463     /* if signed then we do it the hard way preserve the
8464     sign bit moving it inwards */
8465     letype = getSpec(operandType(IC_LEFT(ic)));
8466     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8467
8468     if (!SPEC_USIGN(letype)) {
8469         genSignedRightShift (ic);
8470         return ;
8471     }
8472
8473     /* signed & unsigned types are treated the same : i.e. the
8474     signed is NOT propagated inwards : quoting from the
8475     ANSI - standard : "for E1 >> E2, is equivalent to division
8476     by 2**E2 if unsigned or if it has a non-negative value,
8477     otherwise the result is implementation defined ", MY definition
8478     is that the sign does not get propagated */
8479
8480     right = IC_RIGHT(ic);
8481     left  = IC_LEFT(ic);
8482     result = IC_RESULT(ic);
8483
8484     pic16_aopOp(right,ic,FALSE);
8485
8486     /* if the shift count is known then do it 
8487     as efficiently as possible */
8488     if (AOP_TYPE(right) == AOP_LIT) {
8489         genRightShiftLiteral (left,right,result,ic, 0);
8490         return ;
8491     }
8492
8493     /* shift count is unknown then we have to form 
8494     a loop get the loop count in B : Note: we take
8495     only the lower order byte since shifting
8496     more that 32 bits make no sense anyway, ( the
8497     largest size of an object can be only 32 bits ) */  
8498
8499     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8500     pic16_emitcode("inc","b");
8501     pic16_aopOp(left,ic,FALSE);
8502     pic16_aopOp(result,ic,FALSE);
8503
8504     /* now move the left to the result if they are not the
8505     same */
8506     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8507         AOP_SIZE(result) > 1) {
8508
8509         size = AOP_SIZE(result);
8510         offset=0;
8511         while (size--) {
8512             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8513             if (*l == '@' && IS_AOP_PREG(result)) {
8514
8515                 pic16_emitcode("mov","a,%s",l);
8516                 pic16_aopPut(AOP(result),"a",offset);
8517             } else
8518                 pic16_aopPut(AOP(result),l,offset);
8519             offset++;
8520         }
8521     }
8522
8523     tlbl = newiTempLabel(NULL);
8524     tlbl1= newiTempLabel(NULL);
8525     size = AOP_SIZE(result);
8526     offset = size - 1;
8527
8528     /* if it is only one byte then */
8529     if (size == 1) {
8530
8531       tlbl = newiTempLabel(NULL);
8532       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8533         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8534         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8535       }
8536
8537       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8538       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8539       pic16_emitpLabel(tlbl->key);
8540       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8541       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8542       emitSKPC;
8543       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8544
8545       goto release ;
8546     }
8547
8548     reAdjustPreg(AOP(result));
8549     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8550     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8551     CLRC;
8552     while (size--) {
8553         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8554         MOVA(l);
8555         pic16_emitcode("rrc","a");         
8556         pic16_aopPut(AOP(result),"a",offset--);
8557     }
8558     reAdjustPreg(AOP(result));
8559
8560     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8561     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8562
8563 release:
8564     pic16_freeAsmop(left,NULL,ic,TRUE);
8565     pic16_freeAsmop (right,NULL,ic,TRUE);
8566     pic16_freeAsmop(result,NULL,ic,TRUE);
8567 }
8568
8569 /*-----------------------------------------------------------------*/
8570 /* genUnpackBits - generates code for unpacking bits               */
8571 /*-----------------------------------------------------------------*/
8572 static void genUnpackBits (operand *result, char *rname, int ptype)
8573 {    
8574     int shCnt ;
8575     int rlen = 0 ;
8576     sym_link *etype;
8577     int offset = 0 ;
8578
8579         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8580         etype = getSpec(operandType(result));
8581
8582         /* read the first byte  */
8583         switch (ptype) {
8584                 case POINTER:
8585                 case IPOINTER:
8586                 case PPOINTER:
8587                 case FPOINTER:
8588                 case GPOINTER:
8589                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
8590                         break;
8591                 case CPOINTER:
8592                         pic16_emitcode("clr","a");
8593                         pic16_emitcode("movc","a","@a+dptr");
8594                         break;
8595         }
8596         
8597
8598         /* if we have bitdisplacement then it fits   */
8599         /* into this byte completely or if length is */
8600         /* less than a byte                          */
8601         if ((shCnt = SPEC_BSTR(etype)) || 
8602                 (SPEC_BLEN(etype) <= 8))  {
8603
8604                 /* shift right acc */
8605                 AccRsh(shCnt, 0);
8606
8607                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8608                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
8609
8610 /* VR -- normally I would use the following, but since we use the hack,
8611  * to avoid the masking from AccRsh, why not mask it right now? */
8612
8613 /*
8614                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
8615 */
8616
8617                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
8618           return ;
8619         }
8620
8621
8622
8623         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
8624         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
8625         exit(-1);
8626
8627     /* bit field did not fit in a byte  */
8628     rlen = SPEC_BLEN(etype) - 8;
8629     pic16_aopPut(AOP(result),"a",offset++);
8630
8631     while (1)  {
8632
8633         switch (ptype) {
8634         case POINTER:
8635         case IPOINTER:
8636             pic16_emitcode("inc","%s",rname);
8637             pic16_emitcode("mov","a,@%s",rname);
8638             break;
8639             
8640         case PPOINTER:
8641             pic16_emitcode("inc","%s",rname);
8642             pic16_emitcode("movx","a,@%s",rname);
8643             break;
8644
8645         case FPOINTER:
8646             pic16_emitcode("inc","dptr");
8647             pic16_emitcode("movx","a,@dptr");
8648             break;
8649             
8650         case CPOINTER:
8651             pic16_emitcode("clr","a");
8652             pic16_emitcode("inc","dptr");
8653             pic16_emitcode("movc","a","@a+dptr");
8654             break;
8655             
8656         case GPOINTER:
8657             pic16_emitcode("inc","dptr");
8658             pic16_emitcode("lcall","__gptrget");
8659             break;
8660         }
8661
8662         rlen -= 8;            
8663         /* if we are done */
8664         if ( rlen <= 0 )
8665             break ;
8666         
8667         pic16_aopPut(AOP(result),"a",offset++);
8668                               
8669     }
8670     
8671     if (rlen) {
8672         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
8673         pic16_aopPut(AOP(result),"a",offset);          
8674     }
8675     
8676     return ;
8677 }
8678
8679
8680 static void genDataPointerGet(operand *left,
8681                               operand *result,
8682                               iCode *ic)
8683 {
8684   int size, offset = 0, leoffset=0 ;
8685
8686         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8687         pic16_aopOp(result, ic, FALSE);
8688
8689         size = AOP_SIZE(result);
8690 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
8691
8692
8693 #if 0
8694         /* The following tests may save a redudant movff instruction when
8695          * accessing unions */
8696          
8697         /* if they are the same */
8698         if (operandsEqu (left, result)) {
8699                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
8700                 goto release;
8701         }
8702
8703         /* if they are the same registers */
8704         if (pic16_sameRegs(AOP(left),AOP(result))) {
8705                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
8706                 goto release;
8707         }
8708 #endif
8709
8710 #if 0
8711         if ( AOP_TYPE(left) == AOP_PCODE) {
8712                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
8713                                 AOP(left)->aopu.pcop->name,
8714                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
8715                                 PCOR(AOP(left)->aopu.pcop)->instance:
8716                                 PCOI(AOP(left)->aopu.pcop)->offset);
8717         }
8718 #endif
8719
8720         if(AOP(left)->aopu.pcop->type == PO_DIR)
8721                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
8722
8723         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8724
8725         while (size--) {
8726                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
8727                 
8728                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
8729                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
8730                         mov2w(AOP(left), offset); // patch 8
8731                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
8732                 } else {
8733                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
8734                                 pic16_popGet(AOP(left), offset), //patch 8
8735                                 pic16_popGet(AOP(result), offset)));
8736                 }
8737
8738                 offset++;
8739                 leoffset++;
8740         }
8741
8742 //release:
8743     pic16_freeAsmop(result,NULL,ic,TRUE);
8744 }
8745
8746 void pic16_loadFSR0(operand *op)
8747 {
8748         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
8749 }
8750
8751
8752 /*-----------------------------------------------------------------*/
8753 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
8754 /*-----------------------------------------------------------------*/
8755 static void genNearPointerGet (operand *left, 
8756                                operand *result, 
8757                                iCode *ic)
8758 {
8759     asmop *aop = NULL;
8760     //regs *preg = NULL ;
8761     sym_link *rtype, *retype;
8762     sym_link *ltype = operandType(left);    
8763
8764         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8765         rtype = operandType(result);
8766         retype= getSpec(rtype);
8767     
8768         pic16_aopOp(left,ic,FALSE);
8769
8770         pic16_DumpOp("(left)",left);
8771         pic16_DumpOp("(result)",result);
8772
8773         /* if left is rematerialisable and
8774          * result is not bit variable type and
8775          * the left is pointer to data space i.e
8776          * lower 128 bytes of space */
8777         if (AOP_TYPE(left) == AOP_PCODE
8778                 && !IS_BITFIELD(retype)
8779                 && DCL_TYPE(ltype) == POINTER) {
8780
8781                 genDataPointerGet (left,result,ic);
8782                 pic16_freeAsmop(left, NULL, ic, TRUE);
8783           return ;
8784         }
8785     
8786         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8787
8788         /* if the value is already in a pointer register
8789          * then don't need anything more */
8790         if (!AOP_INPREG(AOP(left))) {
8791                 /* otherwise get a free pointer register */
8792                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8793                 
8794                 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
8795                 if( (AOP_TYPE(left) == AOP_PCODE) 
8796                         && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
8797                                 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
8798                 {
8799                         pic16_loadFSR0( left );  // patch 10
8800                 } else {
8801                         // set up FSR0 with address from left
8802                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
8803                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
8804                 }
8805         }
8806 //       else
8807 //      rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8808     
8809         pic16_aopOp (result,ic,FALSE);
8810     
8811       /* if bitfield then unpack the bits */
8812     if (IS_BITFIELD(retype)) 
8813         genUnpackBits (result, NULL, POINTER);
8814     else {
8815         /* we have can just get the values */
8816       int size = AOP_SIZE(result);
8817       int offset = 0;   
8818         
8819       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8820
8821
8822         /* fsr0 is loaded already -- VR */
8823 //      pic16_loadFSR0( left );
8824
8825 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
8826 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
8827       while(size--) {
8828
8829         if(size) {
8830                 pic16_emitpcode(POC_MOVFF,
8831                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
8832                                 pic16_popGet(AOP(result), offset++)));
8833         } else {
8834                 pic16_emitpcode(POC_MOVFF,
8835                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
8836                                 pic16_popGet(AOP(result), offset++)));
8837         }
8838       }
8839 #if 0
8840 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
8841 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
8842         if(size)
8843           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
8844 #endif
8845 /*
8846         while (size--) {
8847             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
8848
8849                 pic16_emitcode("mov","a,@%s",rname);
8850                 pic16_aopPut(AOP(result),"a",offset);
8851             } else {
8852                 sprintf(buffer,"@%s",rname);
8853                 pic16_aopPut(AOP(result),buffer,offset);
8854             }
8855             offset++ ;
8856             if (size)
8857                 pic16_emitcode("inc","%s",rname);
8858         }
8859 */
8860     }
8861
8862     /* now some housekeeping stuff */
8863     if (aop) {
8864         /* we had to allocate for this iCode */
8865     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8866         pic16_freeAsmop(NULL,aop,ic,TRUE);
8867     } else { 
8868         /* we did not allocate which means left
8869            already in a pointer register, then
8870            if size > 0 && this could be used again
8871            we have to point it back to where it 
8872            belongs */
8873     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8874         if (AOP_SIZE(result) > 1 &&
8875             !OP_SYMBOL(left)->remat &&
8876             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8877               ic->depth )) {
8878 //          int size = AOP_SIZE(result) - 1;
8879 //          while (size--)
8880 //              pic16_emitcode("dec","%s",rname);
8881         }
8882     }
8883
8884     /* done */
8885     pic16_freeAsmop(left,NULL,ic,TRUE);
8886     pic16_freeAsmop(result,NULL,ic,TRUE);
8887      
8888 }
8889
8890 /*-----------------------------------------------------------------*/
8891 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
8892 /*-----------------------------------------------------------------*/
8893 static void genPagedPointerGet (operand *left, 
8894                                operand *result, 
8895                                iCode *ic)
8896 {
8897     asmop *aop = NULL;
8898     regs *preg = NULL ;
8899     char *rname ;
8900     sym_link *rtype, *retype;    
8901
8902     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8903
8904     rtype = operandType(result);
8905     retype= getSpec(rtype);
8906     
8907     pic16_aopOp(left,ic,FALSE);
8908
8909   /* if the value is already in a pointer register
8910        then don't need anything more */
8911     if (!AOP_INPREG(AOP(left))) {
8912         /* otherwise get a free pointer register */
8913         aop = newAsmop(0);
8914         preg = getFreePtr(ic,&aop,FALSE);
8915         pic16_emitcode("mov","%s,%s",
8916                 preg->name,
8917                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
8918         rname = preg->name ;
8919     } else
8920         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8921     
8922     pic16_freeAsmop(left,NULL,ic,TRUE);
8923     pic16_aopOp (result,ic,FALSE);
8924
8925     /* if bitfield then unpack the bits */
8926     if (IS_BITFIELD(retype)) 
8927         genUnpackBits (result,rname,PPOINTER);
8928     else {
8929         /* we have can just get the values */
8930         int size = AOP_SIZE(result);
8931         int offset = 0 ;        
8932         
8933         while (size--) {
8934             
8935             pic16_emitcode("movx","a,@%s",rname);
8936             pic16_aopPut(AOP(result),"a",offset);
8937             
8938             offset++ ;
8939             
8940             if (size)
8941                 pic16_emitcode("inc","%s",rname);
8942         }
8943     }
8944
8945     /* now some housekeeping stuff */
8946     if (aop) {
8947         /* we had to allocate for this iCode */
8948         pic16_freeAsmop(NULL,aop,ic,TRUE);
8949     } else { 
8950         /* we did not allocate which means left
8951            already in a pointer register, then
8952            if size > 0 && this could be used again
8953            we have to point it back to where it 
8954            belongs */
8955         if (AOP_SIZE(result) > 1 &&
8956             !OP_SYMBOL(left)->remat &&
8957             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8958               ic->depth )) {
8959             int size = AOP_SIZE(result) - 1;
8960             while (size--)
8961                 pic16_emitcode("dec","%s",rname);
8962         }
8963     }
8964
8965     /* done */
8966     pic16_freeAsmop(result,NULL,ic,TRUE);
8967     
8968         
8969 }
8970
8971 /*-----------------------------------------------------------------*/
8972 /* genFarPointerGet - gget value from far space                    */
8973 /*-----------------------------------------------------------------*/
8974 static void genFarPointerGet (operand *left,
8975                               operand *result, iCode *ic)
8976 {
8977     int size, offset ;
8978     sym_link *retype = getSpec(operandType(result));
8979
8980     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8981
8982     pic16_aopOp(left,ic,FALSE);
8983
8984     /* if the operand is already in dptr 
8985     then we do nothing else we move the value to dptr */
8986     if (AOP_TYPE(left) != AOP_STR) {
8987         /* if this is remateriazable */
8988         if (AOP_TYPE(left) == AOP_IMMD)
8989             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8990         else { /* we need to get it byte by byte */
8991             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
8992             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
8993             if (options.model == MODEL_FLAT24)
8994             {
8995                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
8996             }
8997         }
8998     }
8999     /* so dptr know contains the address */
9000     pic16_freeAsmop(left,NULL,ic,TRUE);
9001     pic16_aopOp(result,ic,FALSE);
9002
9003     /* if bit then unpack */
9004     if (IS_BITFIELD(retype)) 
9005         genUnpackBits(result,"dptr",FPOINTER);
9006     else {
9007         size = AOP_SIZE(result);
9008         offset = 0 ;
9009
9010         while (size--) {
9011             pic16_emitcode("movx","a,@dptr");
9012             pic16_aopPut(AOP(result),"a",offset++);
9013             if (size)
9014                 pic16_emitcode("inc","dptr");
9015         }
9016     }
9017
9018     pic16_freeAsmop(result,NULL,ic,TRUE);
9019 }
9020 #if 0
9021 /*-----------------------------------------------------------------*/
9022 /* genCodePointerGet - get value from code space                  */
9023 /*-----------------------------------------------------------------*/
9024 static void genCodePointerGet (operand *left,
9025                                 operand *result, iCode *ic)
9026 {
9027     int size, offset ;
9028     sym_link *retype = getSpec(operandType(result));
9029
9030     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9031
9032     pic16_aopOp(left,ic,FALSE);
9033
9034     /* if the operand is already in dptr 
9035     then we do nothing else we move the value to dptr */
9036     if (AOP_TYPE(left) != AOP_STR) {
9037         /* if this is remateriazable */
9038         if (AOP_TYPE(left) == AOP_IMMD)
9039             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9040         else { /* we need to get it byte by byte */
9041             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9042             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9043             if (options.model == MODEL_FLAT24)
9044             {
9045                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9046             }
9047         }
9048     }
9049     /* so dptr know contains the address */
9050     pic16_freeAsmop(left,NULL,ic,TRUE);
9051     pic16_aopOp(result,ic,FALSE);
9052
9053     /* if bit then unpack */
9054     if (IS_BITFIELD(retype)) 
9055         genUnpackBits(result,"dptr",CPOINTER);
9056     else {
9057         size = AOP_SIZE(result);
9058         offset = 0 ;
9059
9060         while (size--) {
9061             pic16_emitcode("clr","a");
9062             pic16_emitcode("movc","a,@a+dptr");
9063             pic16_aopPut(AOP(result),"a",offset++);
9064             if (size)
9065                 pic16_emitcode("inc","dptr");
9066         }
9067     }
9068
9069     pic16_freeAsmop(result,NULL,ic,TRUE);
9070 }
9071 #endif
9072 /*-----------------------------------------------------------------*/
9073 /* genGenPointerGet - gget value from generic pointer space        */
9074 /*-----------------------------------------------------------------*/
9075 static void genGenPointerGet (operand *left,
9076                               operand *result, iCode *ic)
9077 {
9078   int size, offset, lit;
9079   sym_link *retype = getSpec(operandType(result));
9080
9081         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9082         pic16_aopOp(left,ic,FALSE);
9083         pic16_aopOp(result,ic,FALSE);
9084         size = AOP_SIZE(result);
9085
9086         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9087
9088         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9089
9090                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9091                 // load FSR0 from immediate
9092                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9093
9094 //              pic16_loadFSR0( left );
9095
9096                 offset = 0;
9097                 while(size--) {
9098                         if(size) {
9099                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9100                         } else {
9101                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9102                         }
9103                         offset++;
9104                 }
9105                 goto release;
9106
9107         }
9108         else { /* we need to get it byte by byte */
9109                 // set up FSR0 with address from left
9110                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9111                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9112
9113                 offset = 0 ;
9114
9115                 while(size--) {
9116                         if(size) {
9117                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9118                         } else {
9119                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9120                         }
9121                         offset++;
9122                 }
9123                 goto release;
9124         }
9125
9126   /* if bit then unpack */
9127         if (IS_BITFIELD(retype)) 
9128                 genUnpackBits(result,"BAD",GPOINTER);
9129
9130         release:
9131         pic16_freeAsmop(left,NULL,ic,TRUE);
9132         pic16_freeAsmop(result,NULL,ic,TRUE);
9133
9134 }
9135
9136 /*-----------------------------------------------------------------*/
9137 /* genConstPointerGet - get value from const generic pointer space */
9138 /*-----------------------------------------------------------------*/
9139 static void genConstPointerGet (operand *left,
9140                                 operand *result, iCode *ic)
9141 {
9142   //sym_link *retype = getSpec(operandType(result));
9143   // symbol *albl = newiTempLabel(NULL);        // patch 15
9144   // symbol *blbl = newiTempLabel(NULL);        //
9145   // PIC_OPCODE poc;                            // patch 15
9146   int size;
9147   int offset = 0;
9148
9149   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9150   pic16_aopOp(left,ic,FALSE);
9151   pic16_aopOp(result,ic,TRUE);
9152   size = AOP_SIZE(result);
9153
9154   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9155
9156   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9157 #if 0                                                                   // patch 15
9158   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9159   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9160   pic16_emitpLabel(albl->key);
9161
9162   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9163     
9164   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9165   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9166   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9167   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9168   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9169
9170   pic16_emitpLabel(blbl->key);
9171
9172   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9173 #endif                                                                  // patch 15
9174
9175
9176   // set up table pointer
9177   if( (AOP_TYPE(left) == AOP_PCODE) 
9178       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9179           || (AOP(left)->aopu.pcop->type == PO_DIR)))                   // patch 15 ......
9180     {
9181       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9182       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9183       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9184       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9185       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9186       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9187     }
9188   else
9189     {
9190       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9191       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9192       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9193     }
9194
9195
9196   while(size--)
9197     {
9198       pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9199       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9200       offset++;
9201     }
9202                                                                         // .... patch 15
9203   pic16_freeAsmop(left,NULL,ic,TRUE);
9204   pic16_freeAsmop(result,NULL,ic,TRUE);
9205
9206 }
9207 /*-----------------------------------------------------------------*/
9208 /* genPointerGet - generate code for pointer get                   */
9209 /*-----------------------------------------------------------------*/
9210 static void genPointerGet (iCode *ic)
9211 {
9212     operand *left, *result ;
9213     sym_link *type, *etype;
9214     int p_type;
9215
9216     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9217
9218     left = IC_LEFT(ic);
9219     result = IC_RESULT(ic) ;
9220
9221     /* depending on the type of pointer we need to
9222     move it to the correct pointer register */
9223     type = operandType(left);
9224     etype = getSpec(type);
9225
9226 #if 0
9227     if (IS_PTR_CONST(type))
9228 #else
9229     if (IS_CODEPTR(type))
9230 #endif
9231       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9232
9233     /* if left is of type of pointer then it is simple */
9234     if (IS_PTR(type) && !IS_FUNC(type->next)) 
9235         p_type = DCL_TYPE(type);
9236     else {
9237         /* we have to go by the storage class */
9238         p_type = PTR_TYPE(SPEC_OCLS(etype));
9239
9240         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9241
9242         if (SPEC_OCLS(etype)->codesp ) {
9243           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9244           //p_type = CPOINTER ; 
9245         }
9246         else
9247             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9248               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9249                /*p_type = FPOINTER ;*/ 
9250             else
9251                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9252                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9253 /*                  p_type = PPOINTER; */
9254                 else
9255                     if (SPEC_OCLS(etype) == idata )
9256                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9257 /*                      p_type = IPOINTER; */
9258                     else
9259                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9260 /*                      p_type = POINTER ; */
9261     }
9262
9263     /* now that we have the pointer type we assign
9264     the pointer values */
9265     switch (p_type) {
9266
9267     case POINTER:       
9268     case IPOINTER:
9269         genNearPointerGet (left,result,ic);
9270         break;
9271
9272     case PPOINTER:
9273         genPagedPointerGet(left,result,ic);
9274         break;
9275
9276     case FPOINTER:
9277         genFarPointerGet (left,result,ic);
9278         break;
9279
9280     case CPOINTER:
9281         genConstPointerGet (left,result,ic);
9282         //pic16_emitcodePointerGet (left,result,ic);
9283         break;
9284
9285     case GPOINTER:
9286 #if 0
9287       if (IS_PTR_CONST(type))
9288         genConstPointerGet (left,result,ic);
9289       else
9290 #endif
9291         genGenPointerGet (left,result,ic);
9292       break;
9293     }
9294
9295 }
9296
9297 /*-----------------------------------------------------------------*/
9298 /* genPackBits - generates code for packed bit storage             */
9299 /*-----------------------------------------------------------------*/
9300 static void genPackBits (sym_link    *etype ,
9301                          operand *right ,
9302                          char *rname, int p_type)
9303 {
9304   int shCnt = 0 ;
9305   int offset = 0  ;
9306   int rLen = 0 ;
9307   int blen, bstr ;   
9308   char *l ;
9309
9310         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9311         blen = SPEC_BLEN(etype);
9312         bstr = SPEC_BSTR(etype);
9313
9314         if(AOP_TYPE(right) == AOP_LIT) {
9315                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
9316                 offset++;
9317         } else
9318                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
9319
9320 /*      l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9321         MOVA(l);   
9322 */
9323         /* if the bit lenth is less than or    */
9324         /* it exactly fits a byte then         */
9325         if((shCnt=SPEC_BSTR(etype))
9326                 || SPEC_BLEN(etype) <= 8 )  {
9327
9328                 /* shift left acc */
9329                 AccLsh(shCnt);
9330
9331                 /* using PRODL as a temporary register here */
9332                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
9333
9334                 switch (p_type) {
9335                         case FPOINTER:
9336                         case POINTER:
9337                         case GPOINTER:
9338                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9339 //                              pic16_emitcode ("mov","b,a");
9340 //                              pic16_emitcode("mov","a,@%s",rname);
9341                                 break;
9342                 }
9343 #if 1
9344                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9345                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
9346                                         (unsigned char)(0xff >> (8-bstr))) ));
9347                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
9348                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9349 #endif
9350
9351 #if 0
9352                 pic16_emitcode ("anl","a,#0x%02x",(unsigned char)
9353                                         ((unsigned char)(0xFF << (blen+bstr)) | 
9354                                         (unsigned char)(0xFF >> (8-bstr)) ) );
9355                 pic16_emitcode ("orl","a,b");
9356                 if (p_type == GPOINTER)
9357                         pic16_emitcode("pop","b");
9358
9359                 
9360                 switch (p_type) {
9361                         case POINTER:
9362                                 pic16_emitcode("mov","@%s,a",rname);
9363                                 break;
9364                         case FPOINTER:
9365                                 pic16_emitcode("movx","@dptr,a");
9366                                 break;
9367                         case GPOINTER:
9368                                 DEBUGpic16_emitcode(";lcall","__gptrput");
9369                                 break;
9370                 }
9371 #endif
9372
9373           return;
9374         }
9375
9376
9377         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9378         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9379         exit(-1);
9380
9381
9382     /* if we r done */
9383     if ( SPEC_BLEN(etype) <= 8 )
9384         return ;
9385
9386     pic16_emitcode("inc","%s",rname);
9387     rLen = SPEC_BLEN(etype) ;     
9388
9389
9390
9391     /* now generate for lengths greater than one byte */
9392     while (1) {
9393
9394         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
9395
9396         rLen -= 8 ;
9397         if (rLen <= 0 )
9398             break ;
9399
9400         switch (p_type) {
9401             case POINTER:
9402                 if (*l == '@') {
9403                     MOVA(l);
9404                     pic16_emitcode("mov","@%s,a",rname);
9405                 } else
9406                     pic16_emitcode("mov","@%s,%s",rname,l);
9407                 break;
9408
9409             case FPOINTER:
9410                 MOVA(l);
9411                 pic16_emitcode("movx","@dptr,a");
9412                 break;
9413
9414             case GPOINTER:
9415                 MOVA(l);
9416                 DEBUGpic16_emitcode(";lcall","__gptrput");
9417                 break;  
9418         }   
9419         pic16_emitcode ("inc","%s",rname);
9420     }
9421
9422     MOVA(l);
9423
9424     /* last last was not complete */
9425     if (rLen)   {
9426         /* save the byte & read byte */
9427         switch (p_type) {
9428             case POINTER:
9429                 pic16_emitcode ("mov","b,a");
9430                 pic16_emitcode("mov","a,@%s",rname);
9431                 break;
9432
9433             case FPOINTER:
9434                 pic16_emitcode ("mov","b,a");
9435                 pic16_emitcode("movx","a,@dptr");
9436                 break;
9437
9438             case GPOINTER:
9439                 pic16_emitcode ("push","b");
9440                 pic16_emitcode ("push","acc");
9441                 pic16_emitcode ("lcall","__gptrget");
9442                 pic16_emitcode ("pop","b");
9443                 break;
9444         }
9445
9446         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
9447         pic16_emitcode ("orl","a,b");
9448     }
9449
9450     if (p_type == GPOINTER)
9451         pic16_emitcode("pop","b");
9452
9453     switch (p_type) {
9454
9455     case POINTER:
9456         pic16_emitcode("mov","@%s,a",rname);
9457         break;
9458         
9459     case FPOINTER:
9460         pic16_emitcode("movx","@dptr,a");
9461         break;
9462         
9463     case GPOINTER:
9464         DEBUGpic16_emitcode(";lcall","__gptrput");
9465         break;                  
9466     }
9467 }
9468 /*-----------------------------------------------------------------*/
9469 /* genDataPointerSet - remat pointer to data space                 */
9470 /*-----------------------------------------------------------------*/
9471 static void genDataPointerSet(operand *right,
9472                               operand *result,
9473                               iCode *ic)
9474 {
9475     int size, offset = 0, resoffset=0 ;
9476
9477     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9478     pic16_aopOp(right,ic,FALSE);
9479
9480     size = AOP_SIZE(right);
9481         fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9482
9483 #if 1
9484     if ( AOP_TYPE(result) == AOP_PCODE) {
9485       fprintf(stderr,"genDataPointerSet   %s, %d\n",
9486               AOP(result)->aopu.pcop->name,
9487                 (AOP(result)->aopu.pcop->type == PO_DIR)?
9488               PCOR(AOP(result)->aopu.pcop)->instance:
9489               PCOI(AOP(result)->aopu.pcop)->offset);
9490     }
9491 #endif
9492
9493         if(AOP(result)->aopu.pcop->type == PO_DIR)
9494                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
9495
9496         while (size--) {
9497                 if (AOP_TYPE(right) == AOP_LIT) {
9498                   unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9499
9500                         lit = lit >> (8*offset);
9501                         if(lit&0xff) {
9502                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
9503                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
9504                         } else {
9505                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
9506                         }
9507                 } else {
9508                         mov2w(AOP(right), offset);
9509                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
9510                 }
9511                 offset++;
9512                 resoffset++;
9513         }
9514
9515     pic16_freeAsmop(right,NULL,ic,TRUE);
9516 }
9517
9518
9519
9520 /*-----------------------------------------------------------------*/
9521 /* genNearPointerSet - pic16_emitcode for near pointer put         */
9522 /*-----------------------------------------------------------------*/
9523 static void genNearPointerSet (operand *right,
9524                                operand *result, 
9525                                iCode *ic)
9526 {
9527   asmop *aop = NULL;
9528   char *l;
9529   sym_link *retype;
9530   sym_link *ptype = operandType(result);
9531   sym_link *resetype;
9532     
9533         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9534         retype= getSpec(operandType(right));
9535         resetype = getSpec(operandType(result));
9536   
9537         pic16_aopOp(result,ic,FALSE);
9538     
9539         /* if the result is rematerializable &
9540          * in data space & not a bit variable */
9541         
9542         /* and result is not a bit variable */
9543         if (AOP_TYPE(result) == AOP_PCODE
9544 //              && AOP_TYPE(result) == AOP_IMMD
9545                 && DCL_TYPE(ptype) == POINTER
9546                 && !IS_BITFIELD(retype)
9547                 && !IS_BITFIELD(resetype)) {
9548
9549                 genDataPointerSet (right,result,ic);
9550                 pic16_freeAsmop(result,NULL,ic,TRUE);
9551           return;
9552         }
9553
9554         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9555         pic16_aopOp(right,ic,FALSE);
9556         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9557
9558         /* if the value is already in a pointer register
9559          * then don't need anything more */
9560         if (!AOP_INPREG(AOP(result))) {
9561                 /* otherwise get a free pointer register */
9562                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9563
9564                 if( (AOP_TYPE(result) == AOP_PCODE) 
9565                         && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
9566                                 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
9567                 {
9568                         pic16_loadFSR0( result );  // patch 10
9569                 } else {
9570                         // set up FSR0 with address of result
9571                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9572                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9573                 }
9574
9575         }
9576 //      else
9577 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9578
9579         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9580
9581         /* if bitfield then unpack the bits */
9582         if (IS_BITFIELD(resetype)) {
9583                 genPackBits (resetype, right, NULL, POINTER);
9584         } else {
9585                 /* we have can just get the values */
9586           int size = AOP_SIZE(right);
9587           int offset = 0 ;    
9588
9589                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9590                 while (size--) {
9591                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9592                         if (*l == '@' ) {
9593                                 //MOVA(l);
9594                                 //pic16_emitcode("mov","@%s,a",rname);
9595                                 pic16_emitcode("movf","indf0,w ;1");
9596                         } else {
9597
9598                                 if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
9599                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
9600                                         if (size) {                                                                     // 
9601                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
9602                                         } else {                                                                        // 
9603                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
9604                                         }                                                                               // 
9605                                 } else { // no literal                                                                  // 
9606                                         if(size) {                                                                      // 
9607                                                 pic16_emitpcode(POC_MOVFF,                                              // 
9608                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
9609                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));         // 
9610                                         } else {                                                                        // 
9611                                                 pic16_emitpcode(POC_MOVFF,                                              // 
9612                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
9613                                                                         pic16_popCopyReg(&pic16_pc_indf0)));            //
9614                                         }                                                                               //
9615                                 }                                                                                       // patch 10
9616                         }
9617                         offset++;
9618                 }
9619         }
9620
9621         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9622         /* now some housekeeping stuff */
9623         if (aop) {
9624                 /* we had to allocate for this iCode */
9625                 pic16_freeAsmop(NULL,aop,ic,TRUE);
9626         } else { 
9627                 /* we did not allocate which means left
9628                  * already in a pointer register, then
9629                  * if size > 0 && this could be used again
9630                  * we have to point it back to where it 
9631                  * belongs */
9632                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9633                 if (AOP_SIZE(right) > 1
9634                         && !OP_SYMBOL(result)->remat
9635                         && ( OP_SYMBOL(result)->liveTo > ic->seq
9636                                 || ic->depth )) {
9637
9638                   int size = AOP_SIZE(right) - 1;
9639
9640                         while (size--)
9641                                 pic16_emitcode("decf","fsr0,f");
9642                         //pic16_emitcode("dec","%s",rname);
9643                 }
9644         }
9645
9646         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9647         /* done */
9648 //release:
9649         pic16_freeAsmop(right,NULL,ic,TRUE);
9650         pic16_freeAsmop(result,NULL,ic,TRUE);
9651 }
9652
9653 /*-----------------------------------------------------------------*/
9654 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
9655 /*-----------------------------------------------------------------*/
9656 static void genPagedPointerSet (operand *right,
9657                                operand *result, 
9658                                iCode *ic)
9659 {
9660     asmop *aop = NULL;
9661     regs *preg = NULL ;
9662     char *rname , *l;
9663     sym_link *retype;
9664        
9665     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9666
9667     retype= getSpec(operandType(right));
9668     
9669     pic16_aopOp(result,ic,FALSE);
9670     
9671     /* if the value is already in a pointer register
9672        then don't need anything more */
9673     if (!AOP_INPREG(AOP(result))) {
9674         /* otherwise get a free pointer register */
9675         aop = newAsmop(0);
9676         preg = getFreePtr(ic,&aop,FALSE);
9677         pic16_emitcode("mov","%s,%s",
9678                 preg->name,
9679                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
9680         rname = preg->name ;
9681     } else
9682         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9683     
9684     pic16_freeAsmop(result,NULL,ic,TRUE);
9685     pic16_aopOp (right,ic,FALSE);
9686
9687     /* if bitfield then unpack the bits */
9688     if (IS_BITFIELD(retype)) 
9689         genPackBits (retype,right,rname,PPOINTER);
9690     else {
9691         /* we have can just get the values */
9692         int size = AOP_SIZE(right);
9693         int offset = 0 ;        
9694         
9695         while (size--) {
9696             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9697             
9698             MOVA(l);
9699             pic16_emitcode("movx","@%s,a",rname);
9700
9701             if (size)
9702                 pic16_emitcode("inc","%s",rname);
9703
9704             offset++;
9705         }
9706     }
9707     
9708     /* now some housekeeping stuff */
9709     if (aop) {
9710         /* we had to allocate for this iCode */
9711         pic16_freeAsmop(NULL,aop,ic,TRUE);
9712     } else { 
9713         /* we did not allocate which means left
9714            already in a pointer register, then
9715            if size > 0 && this could be used again
9716            we have to point it back to where it 
9717            belongs */
9718         if (AOP_SIZE(right) > 1 &&
9719             !OP_SYMBOL(result)->remat &&
9720             ( OP_SYMBOL(result)->liveTo > ic->seq ||
9721               ic->depth )) {
9722             int size = AOP_SIZE(right) - 1;
9723             while (size--)
9724                 pic16_emitcode("dec","%s",rname);
9725         }
9726     }
9727
9728     /* done */
9729     pic16_freeAsmop(right,NULL,ic,TRUE);
9730     
9731         
9732 }
9733
9734 /*-----------------------------------------------------------------*/
9735 /* genFarPointerSet - set value from far space                     */
9736 /*-----------------------------------------------------------------*/
9737 static void genFarPointerSet (operand *right,
9738                               operand *result, iCode *ic)
9739 {
9740     int size, offset ;
9741     sym_link *retype = getSpec(operandType(right));
9742
9743     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9744     pic16_aopOp(result,ic,FALSE);
9745
9746     /* if the operand is already in dptr 
9747     then we do nothing else we move the value to dptr */
9748     if (AOP_TYPE(result) != AOP_STR) {
9749         /* if this is remateriazable */
9750         if (AOP_TYPE(result) == AOP_IMMD)
9751             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
9752         else { /* we need to get it byte by byte */
9753             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
9754             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
9755             if (options.model == MODEL_FLAT24)
9756             {
9757                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
9758             }
9759         }
9760     }
9761     /* so dptr know contains the address */
9762     pic16_freeAsmop(result,NULL,ic,TRUE);
9763     pic16_aopOp(right,ic,FALSE);
9764
9765     /* if bit then unpack */
9766     if (IS_BITFIELD(retype)) 
9767         genPackBits(retype,right,"dptr",FPOINTER);
9768     else {
9769         size = AOP_SIZE(right);
9770         offset = 0 ;
9771
9772         while (size--) {
9773             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9774             MOVA(l);
9775             pic16_emitcode("movx","@dptr,a");
9776             if (size)
9777                 pic16_emitcode("inc","dptr");
9778         }
9779     }
9780
9781     pic16_freeAsmop(right,NULL,ic,TRUE);
9782 }
9783
9784 /*-----------------------------------------------------------------*/
9785 /* genGenPointerSet - set value from generic pointer space         */
9786 /*-----------------------------------------------------------------*/
9787 static void genGenPointerSet (operand *right,
9788                               operand *result, iCode *ic)
9789 {
9790         int i, size, offset, lit;
9791         sym_link *retype = getSpec(operandType(right));
9792
9793         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9794
9795         pic16_aopOp(result,ic,FALSE);
9796         pic16_aopOp(right,ic,FALSE);
9797         size = AOP_SIZE(right);
9798         offset = 0;
9799
9800         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9801
9802         /* if the operand is already in dptr 
9803                 then we do nothing else we move the value to dptr */
9804         if (AOP_TYPE(result) != AOP_STR) {
9805                 /* if this is remateriazable */
9806                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9807                 // WARNING: anythig until "else" is untested!
9808                 if (AOP_TYPE(result) == AOP_IMMD) {
9809                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9810                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
9811                         // load FSR0 from immediate
9812                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9813                         offset = 0;
9814                         while(size--) {
9815                                 if(size) {
9816                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
9817                                 } else {
9818                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
9819                                 }
9820                                 offset++;
9821                         }
9822                         goto release;
9823                 }
9824                 else { /* we need to get it byte by byte */
9825                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9826                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9827
9828                         // set up FSR0 with address of result
9829                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9830                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9831
9832                         /* hack hack! see if this the FSR. If so don't load W */
9833                         if(AOP_TYPE(right) != AOP_ACC) {
9834
9835                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9836
9837                                 if(AOP_TYPE(right) == AOP_LIT)
9838                                 {
9839                                         // copy literal
9840                                         // note: pic16_popGet handles sign extension
9841                                         for(i=0;i<size;i++) {
9842                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
9843                                                 if(i < size-1)
9844                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
9845                                                 else
9846                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9847                                         }
9848                                 } else {
9849                                         // copy regs
9850
9851                                         for(i=0;i<size;i++) {
9852                                                 if(i < size-1)
9853                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
9854                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
9855                                                 else
9856                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
9857                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
9858                                         }
9859                                 }
9860                                 goto release;
9861                         } 
9862                         // right = ACC
9863                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9864                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9865                         goto release;
9866         } // if (AOP_TYPE(result) != AOP_IMMD)
9867
9868         } // if (AOP_TYPE(result) != AOP_STR)
9869         /* so dptr know contains the address */
9870
9871
9872         /* if bit then unpack */
9873         if (IS_BITFIELD(retype)) 
9874                 genPackBits(retype,right,"dptr",GPOINTER);
9875         else {
9876                 size = AOP_SIZE(right);
9877                 offset = 0 ;
9878
9879                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
9880
9881                 // set up FSR0 with address of result
9882                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9883                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9884         
9885                 while (size--) {
9886                         if (AOP_TYPE(right) == AOP_LIT) {
9887                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9888                                 if (size) {
9889                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
9890                                 } else {
9891                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9892                                 }
9893                         } else { // no literal
9894                                 if(size) {
9895                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
9896                                 } else {
9897                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
9898                                 }
9899                         }
9900                         offset++;
9901                 }
9902         }
9903
9904         release:
9905         pic16_freeAsmop(right,NULL,ic,TRUE);
9906         pic16_freeAsmop(result,NULL,ic,TRUE);
9907 }
9908
9909 /*-----------------------------------------------------------------*/
9910 /* genPointerSet - stores the value into a pointer location        */
9911 /*-----------------------------------------------------------------*/
9912 static void genPointerSet (iCode *ic)
9913 {    
9914     operand *right, *result ;
9915     sym_link *type, *etype;
9916     int p_type;
9917
9918     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9919
9920     right = IC_RIGHT(ic);
9921     result = IC_RESULT(ic) ;
9922
9923     /* depending on the type of pointer we need to
9924     move it to the correct pointer register */
9925     type = operandType(result);
9926     etype = getSpec(type);
9927     /* if left is of type of pointer then it is simple */
9928     if (IS_PTR(type) && !IS_FUNC(type->next)) {
9929         p_type = DCL_TYPE(type);
9930     }
9931     else {
9932         /* we have to go by the storage class */
9933         p_type = PTR_TYPE(SPEC_OCLS(etype));
9934
9935 /*      if (SPEC_OCLS(etype)->codesp ) { */
9936 /*          p_type = CPOINTER ;  */
9937 /*      } */
9938 /*      else */
9939 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9940 /*              p_type = FPOINTER ; */
9941 /*          else */
9942 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9943 /*                  p_type = PPOINTER ; */
9944 /*              else */
9945 /*                  if (SPEC_OCLS(etype) == idata ) */
9946 /*                      p_type = IPOINTER ; */
9947 /*                  else */
9948 /*                      p_type = POINTER ; */
9949     }
9950
9951     /* now that we have the pointer type we assign
9952     the pointer values */
9953     switch (p_type) {
9954
9955     case POINTER:
9956     case IPOINTER:
9957         genNearPointerSet (right,result,ic);
9958         break;
9959
9960     case PPOINTER:
9961         genPagedPointerSet (right,result,ic);
9962         break;
9963
9964     case FPOINTER:
9965         genFarPointerSet (right,result,ic);
9966         break;
9967
9968     case GPOINTER:
9969         genGenPointerSet (right,result,ic);
9970         break;
9971
9972     default:
9973       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9974               "genPointerSet: illegal pointer type");
9975     }
9976 }
9977
9978 /*-----------------------------------------------------------------*/
9979 /* genIfx - generate code for Ifx statement                        */
9980 /*-----------------------------------------------------------------*/
9981 static void genIfx (iCode *ic, iCode *popIc)
9982 {
9983   operand *cond = IC_COND(ic);
9984   int isbit =0;
9985
9986   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9987
9988   pic16_aopOp(cond,ic,FALSE);
9989
9990   /* get the value into acc */
9991   if (AOP_TYPE(cond) != AOP_CRY)
9992     pic16_toBoolean(cond);
9993   else
9994     isbit = 1;
9995   /* the result is now in the accumulator */
9996   pic16_freeAsmop(cond,NULL,ic,TRUE);
9997
9998   /* if there was something to be popped then do it */
9999   if (popIc)
10000     genIpop(popIc);
10001
10002   /* if the condition is  a bit variable */
10003   if (isbit && IS_ITEMP(cond) && 
10004       SPIL_LOC(cond)) {
10005     genIfxJump(ic,SPIL_LOC(cond)->rname);
10006     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10007   }
10008   else {
10009     if (isbit && !IS_ITEMP(cond))
10010       genIfxJump(ic,OP_SYMBOL(cond)->rname);
10011     else
10012       genIfxJump(ic,"a");
10013   }
10014   ic->generated = 1;
10015
10016 }
10017
10018 /*-----------------------------------------------------------------*/
10019 /* genAddrOf - generates code for address of                       */
10020 /*-----------------------------------------------------------------*/
10021 static void genAddrOf (iCode *ic)
10022 {
10023   operand *result, *left;
10024   int size;
10025   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
10026   pCodeOp *pcop0, *pcop1, *pcop2;
10027
10028         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10029
10030         pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10031         pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10032
10033         sym = OP_SYMBOL( left );
10034
10035         size = AOP_SIZE(IC_RESULT(ic));
10036
10037         if(pic16_debug_verbose) {
10038                 fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10039                         __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10040         }
10041         
10042         /* Assume that what we want the address of is in data space
10043          * since there is no stack on the PIC, yet! -- VR */
10044         /* low */
10045         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10046
10047         /* high */
10048         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10049         
10050         /* upper */
10051         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10052         
10053
10054         if (size == 3) {
10055                 pic16_emitpcode(POC_MOVLW, pcop0);
10056                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10057                 pic16_emitpcode(POC_MOVLW, pcop1);
10058                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10059                 pic16_emitpcode(POC_MOVLW, pcop2);
10060                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10061         } else
10062         if (size == 2) {
10063                 pic16_emitpcode(POC_MOVLW, pcop0);
10064                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10065                 pic16_emitpcode(POC_MOVLW, pcop1);
10066                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10067         } else {
10068                 pic16_emitpcode(POC_MOVLW, pcop0);
10069                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10070         }
10071
10072         pic16_freeAsmop(result,NULL,ic,TRUE);
10073         pic16_freeAsmop(left, NULL, ic, FALSE);
10074 }
10075
10076
10077 #if 0
10078 /*-----------------------------------------------------------------*/
10079 /* genFarFarAssign - assignment when both are in far space         */
10080 /*-----------------------------------------------------------------*/
10081 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10082 {
10083     int size = AOP_SIZE(right);
10084     int offset = 0;
10085     char *l ;
10086     /* first push the right side on to the stack */
10087     while (size--) {
10088         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10089         MOVA(l);
10090         pic16_emitcode ("push","acc");
10091     }
10092     
10093     pic16_freeAsmop(right,NULL,ic,FALSE);
10094     /* now assign DPTR to result */
10095     pic16_aopOp(result,ic,FALSE);
10096     size = AOP_SIZE(result);
10097     while (size--) {
10098         pic16_emitcode ("pop","acc");
10099         pic16_aopPut(AOP(result),"a",--offset);
10100     }
10101     pic16_freeAsmop(result,NULL,ic,FALSE);
10102         
10103 }
10104 #endif
10105
10106 /*-----------------------------------------------------------------*/
10107 /* genAssign - generate code for assignment                        */
10108 /*-----------------------------------------------------------------*/
10109 static void genAssign (iCode *ic)
10110 {
10111   operand *result, *right;
10112   int size, offset,know_W;
10113   unsigned long lit = 0L;
10114
10115   result = IC_RESULT(ic);
10116   right  = IC_RIGHT(ic) ;
10117
10118   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10119   
10120   /* if they are the same */
10121   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10122     return ;
10123
10124   pic16_aopOp(right,ic,FALSE);
10125   pic16_aopOp(result,ic,TRUE);
10126
10127   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10128
10129   /* if they are the same registers */
10130   if (pic16_sameRegs(AOP(right),AOP(result)))
10131     goto release;
10132
10133   /* if the result is a bit */
10134   if (AOP_TYPE(result) == AOP_CRY) {
10135     /* if the right size is a literal then
10136        we know what the value is */
10137     if (AOP_TYPE(right) == AOP_LIT) {
10138           
10139       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10140                   pic16_popGet(AOP(result),0));
10141
10142       if (((int) operandLitValue(right))) 
10143         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10144                        AOP(result)->aopu.aop_dir,
10145                        AOP(result)->aopu.aop_dir);
10146       else
10147         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10148                        AOP(result)->aopu.aop_dir,
10149                        AOP(result)->aopu.aop_dir);
10150       goto release;
10151     }
10152
10153     /* the right is also a bit variable */
10154     if (AOP_TYPE(right) == AOP_CRY) {
10155       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10156       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10157       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10158
10159       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10160                      AOP(result)->aopu.aop_dir,
10161                      AOP(result)->aopu.aop_dir);
10162       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10163                      AOP(right)->aopu.aop_dir,
10164                      AOP(right)->aopu.aop_dir);
10165       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10166                      AOP(result)->aopu.aop_dir,
10167                      AOP(result)->aopu.aop_dir);
10168       goto release ;
10169     }
10170
10171     /* we need to or */
10172     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10173     pic16_toBoolean(right);
10174     emitSKPZ;
10175     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10176     //pic16_aopPut(AOP(result),"a",0);
10177     goto release ;
10178   }
10179
10180   /* bit variables done */
10181   /* general case */
10182   size = AOP_SIZE(result);
10183   offset = 0 ;
10184   if(AOP_TYPE(right) == AOP_LIT)
10185     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10186
10187 /* VR - What is this?! */
10188   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10189   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10190     if(aopIdx(AOP(result),0) == 4) {
10191   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10192       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10193       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10194       goto release;
10195     } else
10196       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10197   }
10198
10199   know_W=-1;
10200   while (size--) {
10201   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10202     if(AOP_TYPE(right) == AOP_LIT) {
10203       if(lit&0xff) {
10204         if(know_W != (lit&0xff))
10205           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10206         know_W = lit&0xff;
10207         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10208       } else
10209         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10210
10211       lit >>= 8;
10212
10213     } else if (AOP_TYPE(right) == AOP_CRY) {
10214       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10215       if(offset == 0) {
10216         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10217         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10218       }
10219     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10220         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10221         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10222     } else {
10223   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10224
10225 #if 1
10226         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10227            normally should work, but mind that the W register live range
10228            is not checked, so if the code generator assumes that the W
10229            is already loaded after such a pair, wrong code will be generated.
10230            
10231            Checking the live range is the next step.
10232            This is experimental code yet and has not been fully tested yet.
10233            USE WITH CARE. Revert to old code by setting 0 to the condition above.
10234            Vangelis Rokas 030603 (vrokas@otenet.gr) */
10235            
10236         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10237 #else   
10238         /* This is the old code, which is assumed(?!) that works fine(!?) */
10239
10240         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10241         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10242 #endif
10243     }
10244             
10245     offset++;
10246   }
10247
10248     
10249  release:
10250   pic16_freeAsmop (right,NULL,ic,FALSE);
10251   pic16_freeAsmop (result,NULL,ic,TRUE);
10252 }   
10253
10254 /*-----------------------------------------------------------------*/
10255 /* genJumpTab - generates code for jump table                       */
10256 /*-----------------------------------------------------------------*/
10257 static void genJumpTab (iCode *ic)
10258 {
10259     symbol *jtab;
10260     char *l;
10261
10262     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10263
10264     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
10265     /* get the condition into accumulator */
10266     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10267     MOVA(l);
10268     /* multiply by three */
10269     pic16_emitcode("add","a,acc");
10270     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10271
10272     jtab = newiTempLabel(NULL);
10273     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10274     pic16_emitcode("jmp","@a+dptr");
10275     pic16_emitcode("","%05d_DS_:",jtab->key+100);
10276
10277     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
10278     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
10279     emitSKPNC;
10280     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
10281     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
10282     pic16_emitpLabel(jtab->key);
10283
10284     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10285
10286     /* now generate the jump labels */
10287     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10288          jtab = setNextItem(IC_JTLABELS(ic))) {
10289         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
10290         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
10291         
10292     }
10293
10294 }
10295
10296 /*-----------------------------------------------------------------*/
10297 /* genMixedOperation - gen code for operators between mixed types  */
10298 /*-----------------------------------------------------------------*/
10299 /*
10300   TSD - Written for the PIC port - but this unfortunately is buggy.
10301   This routine is good in that it is able to efficiently promote 
10302   types to different (larger) sizes. Unfortunately, the temporary
10303   variables that are optimized out by this routine are sometimes
10304   used in other places. So until I know how to really parse the 
10305   iCode tree, I'm going to not be using this routine :(.
10306 */
10307 static int genMixedOperation (iCode *ic)
10308 {
10309 #if 0
10310   operand *result = IC_RESULT(ic);
10311   sym_link *ctype = operandType(IC_LEFT(ic));
10312   operand *right = IC_RIGHT(ic);
10313   int ret = 0;
10314   int big,small;
10315   int offset;
10316
10317   iCode *nextic;
10318   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10319
10320   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10321
10322   nextic = ic->next;
10323   if(!nextic)
10324     return 0;
10325
10326   nextright = IC_RIGHT(nextic);
10327   nextleft  = IC_LEFT(nextic);
10328   nextresult = IC_RESULT(nextic);
10329
10330   pic16_aopOp(right,ic,FALSE);
10331   pic16_aopOp(result,ic,FALSE);
10332   pic16_aopOp(nextright,  nextic, FALSE);
10333   pic16_aopOp(nextleft,   nextic, FALSE);
10334   pic16_aopOp(nextresult, nextic, FALSE);
10335
10336   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10337
10338     operand *t = right;
10339     right = nextright;
10340     nextright = t; 
10341
10342     pic16_emitcode(";remove right +","");
10343
10344   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10345 /*
10346     operand *t = right;
10347     right = nextleft;
10348     nextleft = t; 
10349 */
10350     pic16_emitcode(";remove left +","");
10351   } else
10352     return 0;
10353
10354   big = AOP_SIZE(nextleft);
10355   small = AOP_SIZE(nextright);
10356
10357   switch(nextic->op) {
10358
10359   case '+':
10360     pic16_emitcode(";optimize a +","");
10361     /* if unsigned or not an integral type */
10362     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10363       pic16_emitcode(";add a bit to something","");
10364     } else {
10365
10366       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10367
10368       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10369         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10370         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10371       } else
10372         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10373
10374       offset = 0;
10375       while(--big) {
10376
10377         offset++;
10378
10379         if(--small) {
10380           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10381             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10382             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10383           }
10384
10385           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10386           emitSKPNC;
10387           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10388                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10389                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10390           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10391           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10392
10393         } else {
10394           pic16_emitcode("rlf","known_zero,w");
10395
10396           /*
10397             if right is signed
10398               btfsc  right,7
10399                addlw ff
10400           */
10401           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10402             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10403             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10404           } else {
10405             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10406           }
10407         }
10408       }
10409       ret = 1;
10410     }
10411   }
10412   ret = 1;
10413
10414 release:
10415   pic16_freeAsmop(right,NULL,ic,TRUE);
10416   pic16_freeAsmop(result,NULL,ic,TRUE);
10417   pic16_freeAsmop(nextright,NULL,ic,TRUE);
10418   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
10419   if(ret)
10420     nextic->generated = 1;
10421
10422   return ret;
10423 #else
10424   return 0;
10425 #endif
10426 }
10427 /*-----------------------------------------------------------------*/
10428 /* genCast - gen code for casting                                  */
10429 /*-----------------------------------------------------------------*/
10430 static void genCast (iCode *ic)
10431 {
10432   operand *result = IC_RESULT(ic);
10433   sym_link *ctype = operandType(IC_LEFT(ic));
10434   sym_link *rtype = operandType(IC_RIGHT(ic));
10435   operand *right = IC_RIGHT(ic);
10436   int size, offset ;
10437
10438         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10439         /* if they are equivalent then do nothing */
10440         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10441                 return ;
10442
10443         pic16_aopOp(right,ic,FALSE) ;
10444         pic16_aopOp(result,ic,FALSE);
10445
10446         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10447
10448         /* if the result is a bit */
10449         if (AOP_TYPE(result) == AOP_CRY) {
10450         
10451                 /* if the right size is a literal then
10452                  * we know what the value is */
10453                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10454
10455                 if (AOP_TYPE(right) == AOP_LIT) {
10456                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10457                                 pic16_popGet(AOP(result),0));
10458
10459                         if (((int) operandLitValue(right))) 
10460                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
10461                                         AOP(result)->aopu.aop_dir,
10462                                         AOP(result)->aopu.aop_dir);
10463                         else
10464                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
10465                                         AOP(result)->aopu.aop_dir,
10466                                         AOP(result)->aopu.aop_dir);
10467                         goto release;
10468                 }
10469
10470                 /* the right is also a bit variable */
10471                 if (AOP_TYPE(right) == AOP_CRY) {
10472                         emitCLRC;
10473                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10474
10475                         pic16_emitcode("clrc","");
10476                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10477                                 AOP(right)->aopu.aop_dir,
10478                                 AOP(right)->aopu.aop_dir);
10479                         pic16_aopPut(AOP(result),"c",0);
10480                         goto release ;
10481                 }
10482
10483                 /* we need to or */
10484                 if (AOP_TYPE(right) == AOP_REG) {
10485                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10486                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
10487                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10488                 }
10489                 pic16_toBoolean(right);
10490                 pic16_aopPut(AOP(result),"a",0);
10491                 goto release ;
10492         }
10493
10494         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10495           int offset = 1;
10496
10497                 size = AOP_SIZE(result);
10498
10499                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10500
10501                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
10502                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10503                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
10504
10505                 while (size--)
10506                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
10507
10508                 goto release;
10509         }
10510
10511         /* if they are the same size : or less */
10512         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10513
10514                 /* if they are in the same place */
10515                 if (pic16_sameRegs(AOP(right),AOP(result)))
10516                         goto release;
10517
10518                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10519 #if 0
10520                 if (IS_PTR_CONST(rtype))
10521 #else
10522                 if (IS_CODEPTR(rtype))
10523 #endif
10524                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
10525
10526 #if 0
10527                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10528 #else
10529                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
10530 #endif
10531                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
10532
10533 #if 0
10534                 if(AOP_TYPE(right) == AOP_IMMD) {
10535                   pCodeOp *pcop0, *pcop1, *pcop2;
10536                   symbol *sym = OP_SYMBOL( right );
10537
10538                         size = AOP_SIZE(result);
10539                         /* low */
10540                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10541                         /* high */
10542                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10543                         /* upper */
10544                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10545         
10546                         if (size == 3) {
10547                                 pic16_emitpcode(POC_MOVLW, pcop0);
10548                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10549                                 pic16_emitpcode(POC_MOVLW, pcop1);
10550                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10551                                 pic16_emitpcode(POC_MOVLW, pcop2);
10552                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10553                         } else
10554                         if (size == 2) {
10555                                 pic16_emitpcode(POC_MOVLW, pcop0);
10556                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10557                                 pic16_emitpcode(POC_MOVLW, pcop1);
10558                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10559                         } else {
10560                                 pic16_emitpcode(POC_MOVLW, pcop0);
10561                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10562                         }
10563                 } else
10564 #endif
10565                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10566                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
10567                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10568                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
10569                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10570                         if(AOP_SIZE(result) <2)
10571                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10572                 } else {
10573                         /* if they in different places then copy */
10574                         size = AOP_SIZE(result);
10575                         offset = 0 ;
10576                         while (size--) {
10577                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10578                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10579                                 offset++;
10580                         }
10581                 }
10582                 goto release;
10583         }
10584
10585         /* if the result is of type pointer */
10586         if (IS_PTR(ctype)) {
10587           int p_type;
10588           sym_link *type = operandType(right);
10589           sym_link *etype = getSpec(type);
10590
10591                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
10592
10593                 /* pointer to generic pointer */
10594                 if (IS_GENPTR(ctype)) {
10595                   char *l = zero;
10596             
10597                         if (IS_PTR(type)) 
10598                                 p_type = DCL_TYPE(type);
10599                         else {
10600                 /* we have to go by the storage class */
10601                 p_type = PTR_TYPE(SPEC_OCLS(etype));
10602
10603 /*              if (SPEC_OCLS(etype)->codesp )  */
10604 /*                  p_type = CPOINTER ;  */
10605 /*              else */
10606 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10607 /*                      p_type = FPOINTER ; */
10608 /*                  else */
10609 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10610 /*                          p_type = PPOINTER; */
10611 /*                      else */
10612 /*                          if (SPEC_OCLS(etype) == idata ) */
10613 /*                              p_type = IPOINTER ; */
10614 /*                          else */
10615 /*                              p_type = POINTER ; */
10616             }
10617                 
10618             /* the first two bytes are known */
10619       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
10620             size = GPTRSIZE - 1; 
10621             offset = 0 ;
10622             while (size--) {
10623               if(offset < AOP_SIZE(right)) {
10624       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
10625                 if ((AOP_TYPE(right) == AOP_PCODE) && 
10626                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10627                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10628                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10629                 } else { 
10630                   pic16_aopPut(AOP(result),
10631                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10632                          offset);
10633                 }
10634               } else 
10635                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
10636               offset++;
10637             }
10638             /* the last byte depending on type */
10639             switch (p_type) {
10640             case IPOINTER:
10641             case POINTER:
10642                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
10643                 break;
10644             case FPOINTER:
10645               pic16_emitcode(";BUG!? ","%d",__LINE__);
10646                 l = one;
10647                 break;
10648             case CPOINTER:
10649               pic16_emitcode(";BUG!? ","%d",__LINE__);
10650                 l = "#0x02";
10651                 break;                          
10652             case PPOINTER:
10653               pic16_emitcode(";BUG!? ","%d",__LINE__);
10654                 l = "#0x03";
10655                 break;
10656                 
10657             default:
10658                 /* this should never happen */
10659                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10660                        "got unknown pointer type");
10661                 exit(1);
10662             }
10663             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
10664             goto release ;
10665         }
10666         
10667         /* just copy the pointers */
10668         size = AOP_SIZE(result);
10669         offset = 0 ;
10670         while (size--) {
10671             pic16_aopPut(AOP(result),
10672                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10673                    offset);
10674             offset++;
10675         }
10676         goto release ;
10677     }
10678     
10679
10680
10681     /* so we now know that the size of destination is greater
10682     than the size of the source.
10683     Now, if the next iCode is an operator then we might be
10684     able to optimize the operation without performing a cast.
10685     */
10686     if(genMixedOperation(ic))
10687       goto release;
10688
10689     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10690     
10691     /* we move to result for the size of source */
10692     size = AOP_SIZE(right);
10693     offset = 0 ;
10694     while (size--) {
10695       pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
10696       pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
10697       offset++;
10698     }
10699
10700     /* now depending on the sign of the destination */
10701     size = AOP_SIZE(result) - AOP_SIZE(right);
10702     /* if unsigned or not an integral type */
10703     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
10704       while (size--)
10705         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
10706     } else {
10707       /* we need to extend the sign :( */
10708
10709       if(size == 1) {
10710         /* Save one instruction of casting char to int */
10711         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
10712         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10713         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
10714       } else {
10715         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
10716
10717         if(offset)
10718           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10719         else
10720           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
10721         
10722         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
10723
10724         while (size--)
10725           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
10726       }
10727     }
10728
10729 release:
10730     pic16_freeAsmop(right,NULL,ic,TRUE);
10731     pic16_freeAsmop(result,NULL,ic,TRUE);
10732
10733 }
10734
10735 /*-----------------------------------------------------------------*/
10736 /* genDjnz - generate decrement & jump if not zero instrucion      */
10737 /*-----------------------------------------------------------------*/
10738 static int genDjnz (iCode *ic, iCode *ifx)
10739 {
10740     symbol *lbl, *lbl1;
10741     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10742
10743     if (!ifx)
10744         return 0;
10745     
10746     /* if the if condition has a false label
10747        then we cannot save */
10748     if (IC_FALSE(ifx))
10749         return 0;
10750
10751     /* if the minus is not of the form 
10752        a = a - 1 */
10753     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10754         !IS_OP_LITERAL(IC_RIGHT(ic)))
10755         return 0;
10756
10757     if (operandLitValue(IC_RIGHT(ic)) != 1)
10758         return 0;
10759
10760     /* if the size of this greater than one then no
10761        saving */
10762     if (getSize(operandType(IC_RESULT(ic))) > 1)
10763         return 0;
10764
10765     /* otherwise we can save BIG */
10766     lbl = newiTempLabel(NULL);
10767     lbl1= newiTempLabel(NULL);
10768
10769     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10770     
10771     if (IS_AOP_PREG(IC_RESULT(ic))) {
10772         pic16_emitcode("dec","%s",
10773                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10774         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10775         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
10776     } else {    
10777
10778
10779       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
10780       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
10781
10782       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10783       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10784
10785     }
10786 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10787 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
10788 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10789 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
10790
10791     
10792     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10793     ifx->generated = 1;
10794     return 1;
10795 }
10796
10797 /*-----------------------------------------------------------------*/
10798 /* genReceive - generate code for a receive iCode                  */
10799 /*-----------------------------------------------------------------*/
10800 static void genReceive (iCode *ic)
10801 {    
10802         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10803
10804         if (isOperandInFarSpace(IC_RESULT(ic)) &&
10805                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10806                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10807
10808           int size = getSize(operandType(IC_RESULT(ic)));
10809           int offset =  pic16_fReturnSizePic - size;
10810
10811                 while (size--) {
10812                         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
10813                                         fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
10814                         offset++;
10815                 }
10816
10817                 DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
10818
10819                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
10820                 size = AOP_SIZE(IC_RESULT(ic));
10821                 offset = 0;
10822                 while (size--) {
10823                         pic16_emitcode ("pop","acc");
10824                         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10825                 }
10826         } else {
10827                 DEBUGpic16_emitcode ("; ***","2 %s  %d",__FUNCTION__,__LINE__);
10828
10829                 _G.accInUse++;
10830                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
10831                 _G.accInUse--;
10832                 assignResultValue(IC_RESULT(ic), 0);
10833         }
10834
10835         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10836 }
10837
10838 /*-----------------------------------------------------------------*/
10839 /* genDummyRead - generate code for dummy read of volatiles        */
10840 /*-----------------------------------------------------------------*/
10841 static void
10842 genDummyRead (iCode * ic)
10843 {
10844   pic16_emitcode ("; genDummyRead","");
10845   pic16_emitcode ("; not implemented","");
10846
10847   ic = ic;
10848 }
10849
10850 /*-----------------------------------------------------------------*/
10851 /* genpic16Code - generate code for pic16 based controllers        */
10852 /*-----------------------------------------------------------------*/
10853 /*
10854  * At this point, ralloc.c has gone through the iCode and attempted
10855  * to optimize in a way suitable for a PIC. Now we've got to generate
10856  * PIC instructions that correspond to the iCode.
10857  *
10858  * Once the instructions are generated, we'll pass through both the
10859  * peep hole optimizer and the pCode optimizer.
10860  *-----------------------------------------------------------------*/
10861
10862 void genpic16Code (iCode *lic)
10863 {
10864     iCode *ic;
10865     int cln = 0;
10866
10867     lineHead = lineCurr = NULL;
10868
10869     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
10870     pic16_addpBlock(pb);
10871
10872 #if 0
10873     /* if debug information required */
10874     if (options.debug && currFunc) {
10875       if (currFunc) {
10876         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
10877         _G.debugLine = 1;
10878         if (IS_STATIC(currFunc->etype)) {
10879           pic16_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
10880           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(moduleName,currFunc->name));
10881         } else {
10882           pic16_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
10883           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,currFunc->name));
10884         }
10885         _G.debugLine = 0;
10886       }
10887     }
10888 #endif
10889
10890     for (ic = lic ; ic ; ic = ic->next ) {
10891
10892       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
10893         if ( cln != ic->lineno ) {
10894             if ( options.debug ) {
10895                 _G.debugLine = 1;
10896                 pic16_emitcode("",";C$%s$%d$%d$%d ==.",
10897                          FileBaseName(ic->filename),ic->lineno,
10898                          ic->level,ic->block);
10899                 _G.debugLine = 0;
10900             }
10901             
10902             if(!options.noCcodeInAsm) {
10903                 pic16_addpCode2pBlock(pb,
10904                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
10905                                 printCLine(ic->filename, ic->lineno)));
10906             }
10907
10908             cln = ic->lineno ;
10909         }
10910         
10911         if(options.iCodeInAsm) {
10912                 /* insert here code to print iCode as comment */
10913                 pic16_emitpcomment("ic:%d: %s", ic->seq, printILine(ic));
10914         }
10915         
10916         /* if the result is marked as
10917            spilt and rematerializable or code for
10918            this has already been generated then
10919            do nothing */
10920         if (resultRemat(ic) || ic->generated ) 
10921             continue ;
10922         
10923         /* depending on the operation */
10924         switch (ic->op) {
10925         case '!' :
10926             pic16_genNot(ic);
10927             break;
10928             
10929         case '~' :
10930             pic16_genCpl(ic);
10931             break;
10932             
10933         case UNARYMINUS:
10934             genUminus (ic);
10935             break;
10936             
10937         case IPUSH:
10938             genIpush (ic);
10939             break;
10940             
10941         case IPOP:
10942             /* IPOP happens only when trying to restore a 
10943                spilt live range, if there is an ifx statement
10944                following this pop then the if statement might
10945                be using some of the registers being popped which
10946                would destroy the contents of the register so
10947                we need to check for this condition and handle it */
10948             if (ic->next            && 
10949                 ic->next->op == IFX &&
10950                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10951                 genIfx (ic->next,ic);
10952             else
10953                 genIpop (ic);
10954             break; 
10955             
10956         case CALL:
10957             genCall (ic);
10958             break;
10959             
10960         case PCALL:
10961             genPcall (ic);
10962             break;
10963             
10964         case FUNCTION:
10965             genFunction (ic);
10966             break;
10967             
10968         case ENDFUNCTION:
10969             genEndFunction (ic);
10970             break;
10971             
10972         case RETURN:
10973             genRet (ic);
10974             break;
10975             
10976         case LABEL:
10977             genLabel (ic);
10978             break;
10979             
10980         case GOTO:
10981             genGoto (ic);
10982             break;
10983             
10984         case '+' :
10985             pic16_genPlus (ic) ;
10986             break;
10987             
10988         case '-' :
10989             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10990                 pic16_genMinus (ic);
10991             break;
10992             
10993         case '*' :
10994             genMult (ic);
10995             break;
10996             
10997         case '/' :
10998             genDiv (ic) ;
10999             break;
11000             
11001         case '%' :
11002             genMod (ic);
11003             break;
11004             
11005         case '>' :
11006             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
11007             break;
11008             
11009         case '<' :
11010             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11011             break;
11012             
11013         case LE_OP:
11014         case GE_OP:
11015         case NE_OP:
11016             
11017             /* note these two are xlated by algebraic equivalence
11018                during parsing SDCC.y */
11019             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11020                    "got '>=' or '<=' shouldn't have come here");
11021             break;      
11022             
11023         case EQ_OP:
11024             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11025             break;          
11026             
11027         case AND_OP:
11028             genAndOp (ic);
11029             break;
11030             
11031         case OR_OP:
11032             genOrOp (ic);
11033             break;
11034             
11035         case '^' :
11036             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11037             break;
11038             
11039         case '|' :
11040                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11041             break;
11042             
11043         case BITWISEAND:
11044             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11045             break;
11046             
11047         case INLINEASM:
11048             genInline (ic);
11049             break;
11050             
11051         case RRC:
11052             genRRC (ic);
11053             break;
11054             
11055         case RLC:
11056             genRLC (ic);
11057             break;
11058             
11059         case GETHBIT:
11060             genGetHbit (ic);
11061             break;
11062             
11063         case LEFT_OP:
11064             genLeftShift (ic);
11065             break;
11066             
11067         case RIGHT_OP:
11068             genRightShift (ic);
11069             break;
11070             
11071         case GET_VALUE_AT_ADDRESS:
11072             genPointerGet(ic);
11073             break;
11074             
11075         case '=' :
11076             if (POINTER_SET(ic))
11077                 genPointerSet(ic);
11078             else
11079                 genAssign(ic);
11080             break;
11081             
11082         case IFX:
11083             genIfx (ic,NULL);
11084             break;
11085             
11086         case ADDRESS_OF:
11087             genAddrOf (ic);
11088             break;
11089             
11090         case JUMPTABLE:
11091             genJumpTab (ic);
11092             break;
11093             
11094         case CAST:
11095             genCast (ic);
11096             break;
11097             
11098         case RECEIVE:
11099             genReceive(ic);
11100             break;
11101             
11102         case SEND:
11103             addSet(&_G.sendSet,ic);
11104             break;
11105
11106         case DUMMY_READ_VOLATILE:
11107           genDummyRead (ic);
11108           break;
11109
11110         default :
11111             ic = ic;
11112         }
11113     }
11114
11115
11116     /* now we are ready to call the
11117        peep hole optimizer */
11118     if (!options.nopeep) {
11119       peepHole (&lineHead);
11120     }
11121     /* now do the actual printing */
11122     printLine (lineHead,codeOutFile);
11123
11124 #ifdef PCODE_DEBUG
11125     DFPRINTF((stderr,"printing pBlock\n\n"));
11126     pic16_printpBlock(stdout,pb);
11127 #endif
11128
11129     return;
11130 }
11131